summaryrefslogtreecommitdiffstats
path: root/src/crypto/bio
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/bio')
-rw-r--r--src/crypto/bio/CMakeLists.txt1
-rw-r--r--src/crypto/bio/bio.c10
-rw-r--r--src/crypto/bio/bio_mem.c2
-rw-r--r--src/crypto/bio/connect.c126
-rw-r--r--src/crypto/bio/fd.c4
-rw-r--r--src/crypto/bio/printf.c6
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