Loading crypto/bio/bio_lib.c +2 −2 Original line number Diff line number Diff line Loading @@ -325,9 +325,9 @@ long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) return (BIO_ctrl(b, cmd, larg, (char *)&i)); } char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) void *BIO_ptr_ctrl(BIO *b, int cmd, long larg) { char *p = NULL; void *p = NULL; if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) return (NULL); Loading crypto/bio/bss_acpt.c +271 −120 Original line number Diff line number Diff line Loading @@ -57,36 +57,27 @@ #include <stdio.h> #include <errno.h> #define USE_SOCKETS #include "internal/cryptlib.h" #include <openssl/bio.h> #include "bio_lcl.h" #ifndef OPENSSL_NO_SOCK /* * We are currently using deprecated functions here, and GCC warns * us about them, but since we know, we don't want to hear it. */ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" # if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ # undef FIONBIO # endif typedef struct bio_accept_st { int state; int accept_family; int bind_mode; /* Socket mode for BIO_listen */ int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */ char *param_addr; char *param_serv; int accept_sock; int accept_nbio; char *addr; int nbio; /* * If 0, it means normal, if 1, do a connect on bind failure, and if * there is no-one listening, bind with SO_REUSEADDR. If 2, always use * SO_REUSEADDR. */ int bind_mode; BIO_ADDRINFO *addr_first; const BIO_ADDRINFO *addr_iter; BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */ char *cache_accepting_name, *cache_accepting_serv; BIO_ADDR cache_peer_addr; char *cache_peer_name, *cache_peer_serv; BIO *bio_chain; } BIO_ACCEPT; Loading @@ -102,8 +93,11 @@ static BIO_ACCEPT *BIO_ACCEPT_new(void); static void BIO_ACCEPT_free(BIO_ACCEPT *a); # define ACPT_S_BEFORE 1 # define ACPT_S_GET_ACCEPT_SOCKET 2 # define ACPT_S_OK 3 # define ACPT_S_GET_ADDR 2 # define ACPT_S_CREATE_SOCKET 3 # define ACPT_S_LISTEN 4 # define ACPT_S_ACCEPT 5 # define ACPT_S_OK 6 static BIO_METHOD methods_acceptp = { BIO_TYPE_ACCEPT, Loading Loading @@ -144,8 +138,8 @@ static BIO_ACCEPT *BIO_ACCEPT_new(void) if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return (NULL); ret->accept_family = BIO_FAMILY_IPANY; ret->accept_sock = (int)INVALID_SOCKET; ret->bind_mode = BIO_BIND_NORMAL; return (ret); } Loading @@ -155,7 +149,12 @@ static void BIO_ACCEPT_free(BIO_ACCEPT *a) return; OPENSSL_free(a->param_addr); OPENSSL_free(a->addr); OPENSSL_free(a->param_serv); BIO_ADDRINFO_free(a->addr_first); OPENSSL_free(a->cache_accepting_name); OPENSSL_free(a->cache_accepting_serv); OPENSSL_free(a->cache_peer_name); OPENSSL_free(a->cache_peer_serv); BIO_free(a->bio_chain); OPENSSL_free(a); } Loading Loading @@ -194,102 +193,203 @@ static int acpt_free(BIO *a) static int acpt_state(BIO *b, BIO_ACCEPT *c) { BIO *bio = NULL, *dbio; int s = -1; int i; int s = -1, ret = -1; again: for (;;) { switch (c->state) { case ACPT_S_BEFORE: if (c->param_addr == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_PORT_SPECIFIED); return (-1); if (c->param_addr == NULL && c->param_serv == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED); ERR_add_error_data(4, "hostname=", c->param_addr, " service=", c->param_serv); goto exit_loop; } s = BIO_get_accept_socket(c->param_addr, c->bind_mode); if (s == (int)INVALID_SOCKET) return (-1); if (c->accept_nbio) { if (!BIO_socket_nbio(s, 1)) { closesocket(s); BIOerr(BIO_F_ACPT_STATE, BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET); return (-1); /* Because we're starting a new bind, any cached name and serv * are now obsolete and need to be cleaned out. * QUESTION: should this be done in acpt_close_socket() instead? */ OPENSSL_free(c->cache_accepting_name); c->cache_accepting_name = NULL; OPENSSL_free(c->cache_accepting_serv); c->cache_accepting_serv = NULL; OPENSSL_free(c->cache_peer_name); c->cache_peer_name = NULL; OPENSSL_free(c->cache_peer_serv); c->cache_peer_serv = NULL; c->state = ACPT_S_GET_ADDR; break; case ACPT_S_GET_ADDR: { int family = AF_UNSPEC; switch (c->accept_family) { case BIO_FAMILY_IPV6: if (1) { /* This is a trick we use to avoid bit rot. * at least the "else" part will always be * compiled. */ #ifdef AF_INET6 family = AF_INET6; } else { #endif BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); goto exit_loop; } break; case BIO_FAMILY_IPV4: family = AF_INET; break; case BIO_FAMILY_IPANY: family = AF_UNSPEC; break; default: BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); goto exit_loop; } c->accept_sock = s; b->num = s; c->state = ACPT_S_GET_ACCEPT_SOCKET; return (1); /* break; */ case ACPT_S_GET_ACCEPT_SOCKET: if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER, family, SOCK_STREAM, &c->addr_first) == 0) goto exit_loop; } if (c->addr_first == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); goto exit_loop; } /* We're currently not iterating, but set this as preparation * for possible future development in that regard */ c->addr_iter = c->addr_first; c->state = ACPT_S_CREATE_SOCKET; break; case ACPT_S_CREATE_SOCKET: ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), BIO_ADDRINFO_socktype(c->addr_iter), BIO_ADDRINFO_protocol(c->addr_iter), 0); if (ret == (int)INVALID_SOCKET) { SYSerr(SYS_F_SOCKET, get_last_socket_error()); ERR_add_error_data(4, "hostname=", c->param_addr, " service=", c->param_serv); BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } c->accept_sock = ret; b->num = ret; c->state = ACPT_S_LISTEN; break; case ACPT_S_LISTEN: { if (!BIO_listen(c->accept_sock, BIO_ADDRINFO_address(c->addr_iter), c->bind_mode)) { BIO_closesocket(c->accept_sock); goto exit_loop; } } { union BIO_sock_info_u info; info.addr = &c->cache_accepting_addr; if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS, &info)) { BIO_closesocket(c->accept_sock); goto exit_loop; } } c->cache_accepting_name = BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1); c->cache_accepting_serv = BIO_ADDR_service_string(&c->cache_accepting_addr, 1); c->state = ACPT_S_ACCEPT; s = -1; ret = 1; goto end; case ACPT_S_ACCEPT: if (b->next_bio != NULL) { c->state = ACPT_S_OK; goto again; break; } BIO_clear_retry_flags(b); b->retry_reason = 0; i = BIO_accept(c->accept_sock, &(c->addr)); /* -2 return means we should retry */ if (i == -2) { s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr, c->accepted_mode); /* If the returned socket is invalid, this might still be * retryable */ if (s < 0) { if (BIO_sock_should_retry(s)) { BIO_set_retry_special(b); b->retry_reason = BIO_RR_ACCEPT; return -1; goto end; } } if (i < 0) return (i); /* If it wasn't retryable, we fail */ if (s < 0) { ret = s; goto exit_loop; } bio = BIO_new_socket(i, BIO_CLOSE); bio = BIO_new_socket(s, BIO_CLOSE); if (bio == NULL) goto err; goto exit_loop; BIO_set_callback(bio, BIO_get_callback(b)); BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); if (c->nbio) { if (!BIO_socket_nbio(i, 1)) { BIOerr(BIO_F_ACPT_STATE, BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET); goto err; } } /* * If the accept BIO has an bio_chain, we dup it and put the new * socket at the end. */ if (c->bio_chain != NULL) { if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL) goto err; goto exit_loop; if (!BIO_push(dbio, bio)) goto err; goto exit_loop; bio = dbio; } if (BIO_push(b, bio) == NULL) goto err; goto exit_loop; c->cache_peer_name = BIO_ADDR_hostname_string(&c->cache_peer_addr, 1); c->cache_peer_serv = BIO_ADDR_service_string(&c->cache_peer_addr, 1); c->state = ACPT_S_OK; return (1); err: if (bio != NULL) BIO_free(bio); else if (s >= 0) closesocket(s); return (0); /* break; */ bio = NULL; ret = 1; goto end; case ACPT_S_OK: if (b->next_bio == NULL) { c->state = ACPT_S_GET_ACCEPT_SOCKET; goto again; c->state = ACPT_S_ACCEPT; break; } return (1); /* break; */ ret = 1; goto end; default: return (0); /* break; */ ret = 0; goto end; } } exit_loop: if (bio != NULL) BIO_free(bio); else if (s >= 0) BIO_closesocket(s); end: return ret; } static int acpt_read(BIO *b, char *out, int outl) Loading Loading @@ -344,6 +444,8 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; data->state = ACPT_S_BEFORE; acpt_close_socket(b); BIO_ADDRINFO_free(data->addr_first); data->addr_first = NULL; b->flags = 0; break; case BIO_C_DO_STATE_MACHINE: Loading @@ -353,25 +455,48 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_SET_ACCEPT: if (ptr != NULL) { if (num == 0) { b->init = 1; char *hold_serv = data->param_serv; /* We affect the hostname regardless. However, the input * string might contain a host:service spec, so we must * parse it, which might or might not affect the service */ OPENSSL_free(data->param_addr); data->param_addr = OPENSSL_strdup(ptr); data->param_addr = NULL; ret = BIO_parse_hostserv(ptr, &data->param_addr, &data->param_serv, BIO_PARSE_PRIO_SERV); if (hold_serv != data->param_serv) OPENSSL_free(hold_serv); b->init = 1; } else if (num == 1) { data->accept_nbio = (ptr != NULL); OPENSSL_free(data->param_serv); data->param_serv = BUF_strdup(ptr); b->init = 1; } else if (num == 2) { if (ptr != NULL) data->bind_mode |= BIO_SOCK_NONBLOCK; else data->bind_mode &= ~BIO_SOCK_NONBLOCK; } else if (num == 3) { BIO_free(data->bio_chain); data->bio_chain = (BIO *)ptr; } else if (num == 4) { data->accept_family = *(int *)ptr; } } break; case BIO_C_SET_NBIO: data->nbio = (int)num; if (num != 0) data->accepted_mode |= BIO_SOCK_NONBLOCK; else data->accepted_mode &= ~BIO_SOCK_NONBLOCK; break; case BIO_C_SET_FD: b->init = 1; b->num = *((int *)ptr); data->accept_sock = b->num; data->state = ACPT_S_GET_ACCEPT_SOCKET; data->state = ACPT_S_ACCEPT; b->shutdown = (int)num; b->init = 1; break; Loading @@ -386,9 +511,35 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_C_GET_ACCEPT: if (b->init) { if (ptr != NULL) { if (num == 0 && ptr != NULL) { pp = (char **)ptr; *pp = data->cache_accepting_name; } else if (num == 1 && ptr != NULL) { pp = (char **)ptr; *pp = data->cache_accepting_serv; } else if (num == 2 && ptr != NULL) { pp = (char **)ptr; *pp = data->param_addr; *pp = data->cache_peer_name; } else if (num == 3 && ptr != NULL) { pp = (char **)ptr; *pp = data->cache_peer_serv; } else if (num == 4) { switch (BIO_ADDRINFO_family(data->addr_iter)) { #ifdef AF_INET6 case AF_INET6: ret = BIO_FAMILY_IPV6; break; #endif case AF_INET: ret = BIO_FAMILY_IPV4; break; case 0: ret = data->accept_family; break; default: ret = -1; break; } } else ret = -1; } else Loading crypto/bio/bss_conn.c +151 −147 File changed.Preview size limit exceeded, changes collapsed. Show changes doc/crypto/BIO_f_ssl.pod +2 −1 Original line number Diff line number Diff line Loading @@ -169,7 +169,8 @@ unencrypted example in L<BIO_s_connect(3)>. /* We might want to do other things with ssl here */ BIO_set_conn_hostname(sbio, "localhost:https"); /* An empty host part means the loopback address */ BIO_set_conn_hostname(sbio, ":https"); out = BIO_new_fp(stdout, BIO_NOCLOSE); if(BIO_do_connect(sbio) <= 0) { Loading doc/crypto/BIO_s_accept.pod +6 −5 Original line number Diff line number Diff line Loading @@ -59,11 +59,12 @@ the accept socket. See L<BIO_s_fd(3)> BIO_set_accept_port() uses the string B<name> to set the accept port. The port is represented as a string of the form "host:port", where "host" is the interface to use and "port" is the port. The host can be "*" which is interpreted as meaning any interface; "port" has the same syntax as the port specified in BIO_set_conn_port() for connect BIOs, that is it can be a numerical port string or a string to lookup using getservbyname() and a string table. The host can be "*" or empty which is interpreted as meaning any interface. If the host is a IPv6 address, it has to be enclosed in brackets, for example "[::1]:https". "port" has the same syntax as the port specified in BIO_set_conn_port() for connect BIOs, that is it can be a numerical port string or a string to lookup using getservbyname() and a string table. BIO_new_accept() combines BIO_new() and BIO_set_accept_port() into a single call: that is it creates a new accept BIO with port Loading Loading
crypto/bio/bio_lib.c +2 −2 Original line number Diff line number Diff line Loading @@ -325,9 +325,9 @@ long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) return (BIO_ctrl(b, cmd, larg, (char *)&i)); } char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) void *BIO_ptr_ctrl(BIO *b, int cmd, long larg) { char *p = NULL; void *p = NULL; if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) return (NULL); Loading
crypto/bio/bss_acpt.c +271 −120 Original line number Diff line number Diff line Loading @@ -57,36 +57,27 @@ #include <stdio.h> #include <errno.h> #define USE_SOCKETS #include "internal/cryptlib.h" #include <openssl/bio.h> #include "bio_lcl.h" #ifndef OPENSSL_NO_SOCK /* * We are currently using deprecated functions here, and GCC warns * us about them, but since we know, we don't want to hear it. */ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" # if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ # undef FIONBIO # endif typedef struct bio_accept_st { int state; int accept_family; int bind_mode; /* Socket mode for BIO_listen */ int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */ char *param_addr; char *param_serv; int accept_sock; int accept_nbio; char *addr; int nbio; /* * If 0, it means normal, if 1, do a connect on bind failure, and if * there is no-one listening, bind with SO_REUSEADDR. If 2, always use * SO_REUSEADDR. */ int bind_mode; BIO_ADDRINFO *addr_first; const BIO_ADDRINFO *addr_iter; BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */ char *cache_accepting_name, *cache_accepting_serv; BIO_ADDR cache_peer_addr; char *cache_peer_name, *cache_peer_serv; BIO *bio_chain; } BIO_ACCEPT; Loading @@ -102,8 +93,11 @@ static BIO_ACCEPT *BIO_ACCEPT_new(void); static void BIO_ACCEPT_free(BIO_ACCEPT *a); # define ACPT_S_BEFORE 1 # define ACPT_S_GET_ACCEPT_SOCKET 2 # define ACPT_S_OK 3 # define ACPT_S_GET_ADDR 2 # define ACPT_S_CREATE_SOCKET 3 # define ACPT_S_LISTEN 4 # define ACPT_S_ACCEPT 5 # define ACPT_S_OK 6 static BIO_METHOD methods_acceptp = { BIO_TYPE_ACCEPT, Loading Loading @@ -144,8 +138,8 @@ static BIO_ACCEPT *BIO_ACCEPT_new(void) if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return (NULL); ret->accept_family = BIO_FAMILY_IPANY; ret->accept_sock = (int)INVALID_SOCKET; ret->bind_mode = BIO_BIND_NORMAL; return (ret); } Loading @@ -155,7 +149,12 @@ static void BIO_ACCEPT_free(BIO_ACCEPT *a) return; OPENSSL_free(a->param_addr); OPENSSL_free(a->addr); OPENSSL_free(a->param_serv); BIO_ADDRINFO_free(a->addr_first); OPENSSL_free(a->cache_accepting_name); OPENSSL_free(a->cache_accepting_serv); OPENSSL_free(a->cache_peer_name); OPENSSL_free(a->cache_peer_serv); BIO_free(a->bio_chain); OPENSSL_free(a); } Loading Loading @@ -194,102 +193,203 @@ static int acpt_free(BIO *a) static int acpt_state(BIO *b, BIO_ACCEPT *c) { BIO *bio = NULL, *dbio; int s = -1; int i; int s = -1, ret = -1; again: for (;;) { switch (c->state) { case ACPT_S_BEFORE: if (c->param_addr == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_PORT_SPECIFIED); return (-1); if (c->param_addr == NULL && c->param_serv == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED); ERR_add_error_data(4, "hostname=", c->param_addr, " service=", c->param_serv); goto exit_loop; } s = BIO_get_accept_socket(c->param_addr, c->bind_mode); if (s == (int)INVALID_SOCKET) return (-1); if (c->accept_nbio) { if (!BIO_socket_nbio(s, 1)) { closesocket(s); BIOerr(BIO_F_ACPT_STATE, BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET); return (-1); /* Because we're starting a new bind, any cached name and serv * are now obsolete and need to be cleaned out. * QUESTION: should this be done in acpt_close_socket() instead? */ OPENSSL_free(c->cache_accepting_name); c->cache_accepting_name = NULL; OPENSSL_free(c->cache_accepting_serv); c->cache_accepting_serv = NULL; OPENSSL_free(c->cache_peer_name); c->cache_peer_name = NULL; OPENSSL_free(c->cache_peer_serv); c->cache_peer_serv = NULL; c->state = ACPT_S_GET_ADDR; break; case ACPT_S_GET_ADDR: { int family = AF_UNSPEC; switch (c->accept_family) { case BIO_FAMILY_IPV6: if (1) { /* This is a trick we use to avoid bit rot. * at least the "else" part will always be * compiled. */ #ifdef AF_INET6 family = AF_INET6; } else { #endif BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); goto exit_loop; } break; case BIO_FAMILY_IPV4: family = AF_INET; break; case BIO_FAMILY_IPANY: family = AF_UNSPEC; break; default: BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); goto exit_loop; } c->accept_sock = s; b->num = s; c->state = ACPT_S_GET_ACCEPT_SOCKET; return (1); /* break; */ case ACPT_S_GET_ACCEPT_SOCKET: if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER, family, SOCK_STREAM, &c->addr_first) == 0) goto exit_loop; } if (c->addr_first == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); goto exit_loop; } /* We're currently not iterating, but set this as preparation * for possible future development in that regard */ c->addr_iter = c->addr_first; c->state = ACPT_S_CREATE_SOCKET; break; case ACPT_S_CREATE_SOCKET: ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), BIO_ADDRINFO_socktype(c->addr_iter), BIO_ADDRINFO_protocol(c->addr_iter), 0); if (ret == (int)INVALID_SOCKET) { SYSerr(SYS_F_SOCKET, get_last_socket_error()); ERR_add_error_data(4, "hostname=", c->param_addr, " service=", c->param_serv); BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } c->accept_sock = ret; b->num = ret; c->state = ACPT_S_LISTEN; break; case ACPT_S_LISTEN: { if (!BIO_listen(c->accept_sock, BIO_ADDRINFO_address(c->addr_iter), c->bind_mode)) { BIO_closesocket(c->accept_sock); goto exit_loop; } } { union BIO_sock_info_u info; info.addr = &c->cache_accepting_addr; if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS, &info)) { BIO_closesocket(c->accept_sock); goto exit_loop; } } c->cache_accepting_name = BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1); c->cache_accepting_serv = BIO_ADDR_service_string(&c->cache_accepting_addr, 1); c->state = ACPT_S_ACCEPT; s = -1; ret = 1; goto end; case ACPT_S_ACCEPT: if (b->next_bio != NULL) { c->state = ACPT_S_OK; goto again; break; } BIO_clear_retry_flags(b); b->retry_reason = 0; i = BIO_accept(c->accept_sock, &(c->addr)); /* -2 return means we should retry */ if (i == -2) { s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr, c->accepted_mode); /* If the returned socket is invalid, this might still be * retryable */ if (s < 0) { if (BIO_sock_should_retry(s)) { BIO_set_retry_special(b); b->retry_reason = BIO_RR_ACCEPT; return -1; goto end; } } if (i < 0) return (i); /* If it wasn't retryable, we fail */ if (s < 0) { ret = s; goto exit_loop; } bio = BIO_new_socket(i, BIO_CLOSE); bio = BIO_new_socket(s, BIO_CLOSE); if (bio == NULL) goto err; goto exit_loop; BIO_set_callback(bio, BIO_get_callback(b)); BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); if (c->nbio) { if (!BIO_socket_nbio(i, 1)) { BIOerr(BIO_F_ACPT_STATE, BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET); goto err; } } /* * If the accept BIO has an bio_chain, we dup it and put the new * socket at the end. */ if (c->bio_chain != NULL) { if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL) goto err; goto exit_loop; if (!BIO_push(dbio, bio)) goto err; goto exit_loop; bio = dbio; } if (BIO_push(b, bio) == NULL) goto err; goto exit_loop; c->cache_peer_name = BIO_ADDR_hostname_string(&c->cache_peer_addr, 1); c->cache_peer_serv = BIO_ADDR_service_string(&c->cache_peer_addr, 1); c->state = ACPT_S_OK; return (1); err: if (bio != NULL) BIO_free(bio); else if (s >= 0) closesocket(s); return (0); /* break; */ bio = NULL; ret = 1; goto end; case ACPT_S_OK: if (b->next_bio == NULL) { c->state = ACPT_S_GET_ACCEPT_SOCKET; goto again; c->state = ACPT_S_ACCEPT; break; } return (1); /* break; */ ret = 1; goto end; default: return (0); /* break; */ ret = 0; goto end; } } exit_loop: if (bio != NULL) BIO_free(bio); else if (s >= 0) BIO_closesocket(s); end: return ret; } static int acpt_read(BIO *b, char *out, int outl) Loading Loading @@ -344,6 +444,8 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; data->state = ACPT_S_BEFORE; acpt_close_socket(b); BIO_ADDRINFO_free(data->addr_first); data->addr_first = NULL; b->flags = 0; break; case BIO_C_DO_STATE_MACHINE: Loading @@ -353,25 +455,48 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_SET_ACCEPT: if (ptr != NULL) { if (num == 0) { b->init = 1; char *hold_serv = data->param_serv; /* We affect the hostname regardless. However, the input * string might contain a host:service spec, so we must * parse it, which might or might not affect the service */ OPENSSL_free(data->param_addr); data->param_addr = OPENSSL_strdup(ptr); data->param_addr = NULL; ret = BIO_parse_hostserv(ptr, &data->param_addr, &data->param_serv, BIO_PARSE_PRIO_SERV); if (hold_serv != data->param_serv) OPENSSL_free(hold_serv); b->init = 1; } else if (num == 1) { data->accept_nbio = (ptr != NULL); OPENSSL_free(data->param_serv); data->param_serv = BUF_strdup(ptr); b->init = 1; } else if (num == 2) { if (ptr != NULL) data->bind_mode |= BIO_SOCK_NONBLOCK; else data->bind_mode &= ~BIO_SOCK_NONBLOCK; } else if (num == 3) { BIO_free(data->bio_chain); data->bio_chain = (BIO *)ptr; } else if (num == 4) { data->accept_family = *(int *)ptr; } } break; case BIO_C_SET_NBIO: data->nbio = (int)num; if (num != 0) data->accepted_mode |= BIO_SOCK_NONBLOCK; else data->accepted_mode &= ~BIO_SOCK_NONBLOCK; break; case BIO_C_SET_FD: b->init = 1; b->num = *((int *)ptr); data->accept_sock = b->num; data->state = ACPT_S_GET_ACCEPT_SOCKET; data->state = ACPT_S_ACCEPT; b->shutdown = (int)num; b->init = 1; break; Loading @@ -386,9 +511,35 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_C_GET_ACCEPT: if (b->init) { if (ptr != NULL) { if (num == 0 && ptr != NULL) { pp = (char **)ptr; *pp = data->cache_accepting_name; } else if (num == 1 && ptr != NULL) { pp = (char **)ptr; *pp = data->cache_accepting_serv; } else if (num == 2 && ptr != NULL) { pp = (char **)ptr; *pp = data->param_addr; *pp = data->cache_peer_name; } else if (num == 3 && ptr != NULL) { pp = (char **)ptr; *pp = data->cache_peer_serv; } else if (num == 4) { switch (BIO_ADDRINFO_family(data->addr_iter)) { #ifdef AF_INET6 case AF_INET6: ret = BIO_FAMILY_IPV6; break; #endif case AF_INET: ret = BIO_FAMILY_IPV4; break; case 0: ret = data->accept_family; break; default: ret = -1; break; } } else ret = -1; } else Loading
crypto/bio/bss_conn.c +151 −147 File changed.Preview size limit exceeded, changes collapsed. Show changes
doc/crypto/BIO_f_ssl.pod +2 −1 Original line number Diff line number Diff line Loading @@ -169,7 +169,8 @@ unencrypted example in L<BIO_s_connect(3)>. /* We might want to do other things with ssl here */ BIO_set_conn_hostname(sbio, "localhost:https"); /* An empty host part means the loopback address */ BIO_set_conn_hostname(sbio, ":https"); out = BIO_new_fp(stdout, BIO_NOCLOSE); if(BIO_do_connect(sbio) <= 0) { Loading
doc/crypto/BIO_s_accept.pod +6 −5 Original line number Diff line number Diff line Loading @@ -59,11 +59,12 @@ the accept socket. See L<BIO_s_fd(3)> BIO_set_accept_port() uses the string B<name> to set the accept port. The port is represented as a string of the form "host:port", where "host" is the interface to use and "port" is the port. The host can be "*" which is interpreted as meaning any interface; "port" has the same syntax as the port specified in BIO_set_conn_port() for connect BIOs, that is it can be a numerical port string or a string to lookup using getservbyname() and a string table. The host can be "*" or empty which is interpreted as meaning any interface. If the host is a IPv6 address, it has to be enclosed in brackets, for example "[::1]:https". "port" has the same syntax as the port specified in BIO_set_conn_port() for connect BIOs, that is it can be a numerical port string or a string to lookup using getservbyname() and a string table. BIO_new_accept() combines BIO_new() and BIO_set_accept_port() into a single call: that is it creates a new accept BIO with port Loading