diff options
Diffstat (limited to 'src/crypto/bio')
-rw-r--r-- | src/crypto/bio/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/crypto/bio/bio.c | 10 | ||||
-rw-r--r-- | src/crypto/bio/bio_mem.c | 2 | ||||
-rw-r--r-- | src/crypto/bio/connect.c | 126 | ||||
-rw-r--r-- | src/crypto/bio/fd.c | 4 | ||||
-rw-r--r-- | src/crypto/bio/printf.c | 6 |
6 files changed, 81 insertions, 68 deletions
diff --git a/src/crypto/bio/CMakeLists.txt b/src/crypto/bio/CMakeLists.txt index 8de090a..7859b58 100644 --- a/src/crypto/bio/CMakeLists.txt +++ b/src/crypto/bio/CMakeLists.txt @@ -30,3 +30,4 @@ target_link_libraries(bio_test crypto) if (WIN32) target_link_libraries(bio_test ws2_32) endif() +add_dependencies(all_tests bio_test) diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c index 4bc98ba..7a1a9e3 100644 --- a/src/crypto/bio/bio.c +++ b/src/crypto/bio/bio.c @@ -529,7 +529,7 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { uint8_t header[6]; static const size_t kInitialHeaderLen = 2; - if (BIO_read(bio, header, kInitialHeaderLen) != kInitialHeaderLen) { + if (BIO_read(bio, header, kInitialHeaderLen) != (int) kInitialHeaderLen) { return 0; } @@ -559,7 +559,8 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { return 0; } - if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != num_bytes) { + if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != + (int)num_bytes) { return 0; } header_len = kInitialHeaderLen + num_bytes; @@ -585,7 +586,8 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { } if (len + header_len < len || - len + header_len > max_len) { + len + header_len > max_len || + len > INT_MAX) { return 0; } len += header_len; @@ -597,7 +599,7 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { } memcpy(*out, header, header_len); if (BIO_read(bio, (*out) + header_len, len - header_len) != - len - header_len) { + (int) (len - header_len)) { OPENSSL_free(*out); return 0; } diff --git a/src/crypto/bio/bio_mem.c b/src/crypto/bio/bio_mem.c index ef56111..6864f6f 100644 --- a/src/crypto/bio/bio_mem.c +++ b/src/crypto/bio/bio_mem.c @@ -176,7 +176,7 @@ static int mem_write(BIO *bio, const char *in, int inl) { if (INT_MAX - blen < inl) { goto err; } - if (BUF_MEM_grow_clean(b, blen + inl) != (blen + inl)) { + if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) { goto err; } memcpy(&b->data[blen], in, inl); diff --git a/src/crypto/bio/connect.c b/src/crypto/bio/connect.c index 2ed2def..0b34d7f 100644 --- a/src/crypto/bio/connect.c +++ b/src/crypto/bio/connect.c @@ -93,7 +93,6 @@ typedef struct bio_connect_st { char *param_port; int nbio; - uint8_t ip[4]; unsigned short port; struct sockaddr_storage them; @@ -114,23 +113,59 @@ static int closesocket(int sock) { } #endif -/* maybe_copy_ipv4_address sets |*ipv4| to the IPv4 address from |ss| (in - * big-endian order), if |ss| contains an IPv4 socket address. */ -static void maybe_copy_ipv4_address(uint8_t *ipv4, - const struct sockaddr_storage *ss) { - const struct sockaddr_in *sin; +/* split_host_and_port sets |*out_host| and |*out_port| to the host and port + * parsed from |name|. It returns one on success or zero on error. Even when + * successful, |*out_port| may be NULL on return if no port was specified. */ +static int split_host_and_port(char **out_host, char **out_port, const char *name) { + const char *host, *port = NULL; + size_t host_len = 0; - if (ss->ss_family != AF_INET) { - return; + *out_host = NULL; + *out_port = NULL; + + if (name[0] == '[') { /* bracketed IPv6 address */ + const char *close = strchr(name, ']'); + if (close == NULL) { + return 0; + } + host = name + 1; + host_len = close - host; + if (close[1] == ':') { /* [IP]:port */ + port = close + 2; + } else if (close[1] != 0) { + return 0; + } + } else { + const char *colon = strchr(name, ':'); + if (colon == NULL || strchr(colon + 1, ':') != NULL) { /* IPv6 address */ + host = name; + host_len = strlen(name); + } else { /* host:port */ + host = name; + host_len = colon - name; + port = colon + 1; + } } - sin = (const struct sockaddr_in*) ss; - memcpy(ipv4, &sin->sin_addr, 4); + *out_host = BUF_strndup(host, host_len); + if (*out_host == NULL) { + return 0; + } + if (port == NULL) { + *out_port = NULL; + return 1; + } + *out_port = OPENSSL_strdup(port); + if (*out_port == NULL) { + OPENSSL_free(*out_host); + *out_host = NULL; + return 0; + } + return 1; } static int conn_state(BIO *bio, BIO_CONNECT *c) { int ret = -1, i; - char *p, *q; int (*cb)(const BIO *, int, int) = NULL; if (c->info_callback != NULL) { @@ -140,36 +175,30 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) { for (;;) { switch (c->state) { case BIO_CONN_S_BEFORE: - p = c->param_hostname; - if (p == NULL) { + /* If there's a hostname and a port, assume that both are + * exactly what they say. If there is only a hostname, try + * (just once) to split it into a hostname and port. */ + + if (c->param_hostname == NULL) { OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED); goto exit_loop; } - for (; *p != 0; p++) { - if (*p == ':' || *p == '/') { - break; - } - } - i = *p; - if (i == ':' || i == '/') { - *(p++) = 0; - if (i == ':') { - for (q = p; *q; q++) { - if (*q == '/') { - *q = 0; - break; - } - } - OPENSSL_free(c->param_port); - c->param_port = BUF_strdup(p); + if (c->param_port == NULL) { + char *host, *port; + if (!split_host_and_port(&host, &port, c->param_hostname) || + port == NULL) { + OPENSSL_free(host); + OPENSSL_free(port); + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED); + ERR_add_error_data(2, "host=", c->param_hostname); + goto exit_loop; } - } - if (c->param_port == NULL) { - OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED); - ERR_add_error_data(2, "host=", c->param_hostname); - goto exit_loop; + OPENSSL_free(c->param_port); + c->param_port = port; + OPENSSL_free(c->param_hostname); + c->param_hostname = host; } if (!bio_ip_and_port_to_socket_and_addr( @@ -180,9 +209,6 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) { goto exit_loop; } - memset(c->ip, 0, 4); - maybe_copy_ipv4_address(c->ip, &c->them); - if (c->nbio) { if (!bio_socket_nbio(bio->num, 1)) { OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO); @@ -376,7 +402,6 @@ static int conn_write(BIO *bio, const char *in, int in_len) { static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { int *ip; - const char **pptr; long ret = 1; BIO_CONNECT *data; @@ -397,25 +422,6 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { ret = 1; } break; - case BIO_C_GET_CONNECT: - /* TODO(fork): can this be removed? (Or maybe this whole file). */ - if (ptr != NULL) { - pptr = (const char **)ptr; - if (num == 0) { - *pptr = data->param_hostname; - } else if (num == 1) { - *pptr = data->param_port; - } else if (num == 2) { - *pptr = (char *) &data->ip[0]; - } else if (num == 3) { - *((int *)ptr) = data->port; - } - if (!bio->init) { - *pptr = "not initialized"; - } - ret = 1; - } - break; case BIO_C_SET_CONNECT: if (ptr != NULL) { bio->init = 1; @@ -445,9 +451,9 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { if (ip != NULL) { *ip = bio->num; } - ret = 1; + ret = bio->num; } else { - ret = 0; + ret = -1; } break; case BIO_CTRL_GET_CLOSE: diff --git a/src/crypto/bio/fd.c b/src/crypto/bio/fd.c index 0b5baca..0b3484c 100644 --- a/src/crypto/bio/fd.c +++ b/src/crypto/bio/fd.c @@ -208,9 +208,9 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) { if (ip != NULL) { *ip = b->num; } - return 1; + return b->num; } else { - ret = 0; + ret = -1; } break; case BIO_CTRL_GET_CLOSE: diff --git a/src/crypto/bio/printf.c b/src/crypto/bio/printf.c index 2f5ae4a..3709fcb 100644 --- a/src/crypto/bio/printf.c +++ b/src/crypto/bio/printf.c @@ -87,7 +87,11 @@ int BIO_printf(BIO *bio, const char *format, ...) { } #endif - if (out_len >= sizeof(buf)) { + if (out_len < 0) { + return -1; + } + + if ((size_t) out_len >= sizeof(buf)) { const int requested_len = out_len; /* The output was truncated. Note that vsnprintf's return value * does not include a trailing NUL, but the buffer must be sized |