From owner-svn-soc-all@FreeBSD.ORG Sun Jun 17 02:29:07 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id 23577106566B for ; Sun, 17 Jun 2012 02:29:05 +0000 (UTC) (envelope-from exxo@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Sun, 17 Jun 2012 02:29:05 +0000 Date: Sun, 17 Jun 2012 02:29:05 +0000 From: exxo@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120617022905.23577106566B@hub.freebsd.org> Cc: Subject: socsvn commit: r237821 - in soc2012/exxo: openssl-1.0.1c/crypto/bio regress regress/openssl-1.0.1c X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Jun 2012 02:29:07 -0000 Author: exxo Date: Sun Jun 17 02:29:04 2012 New Revision: 237821 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237821 Log: Major rewrite in b_sock.c without breaking the API (however see TODO list), correct buffering issue in regress Modified: soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h soc2012/exxo/regress/openssl-1.0.1c/Makefile soc2012/exxo/regress/regress.in Modified: soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c ============================================================================== --- soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c Sun Jun 17 00:28:57 2012 (r237820) +++ soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c Sun Jun 17 02:29:04 2012 (r237821) @@ -59,6 +59,7 @@ #include #include #include +#include #define USE_SOCKETS #include "cryptlib.h" #include @@ -84,6 +85,10 @@ #define MAX_LISTEN 32 #endif +#ifdef OPENSSL_USE_IPV6 +extern const struct in6_addr in6addr_any; +#endif + #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) static int wsa_init_done=0; #endif @@ -123,8 +128,12 @@ int err = 1; int locked = 0; struct hostent *he; + struct addrinfo hint, *res = NULL; + char *addr = NULL; + int addrlen = 4; + int gai_err; - i=get_ip(str,ip); + i=get_ip(str,ip); /* Search for an IPv4 address in in standard dot notation */ if (i < 0) { BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); @@ -140,29 +149,66 @@ anything more */ if (i > 0) return(1); - /* do a gethostbyname */ - CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); - locked = 1; - he=BIO_gethostbyname(str); - if (he == NULL) + memset(&hint,0,sizeof(hint)); +#if OPENSSL_USE_IPV6 + hint.ai_family=AF_INET6; +#else + hint.ai_family=AF_INET; +#endif + gai_err = BIO_getaddrinfo(str, NULL, &hint, &res); + if (gai_err == 0) { - BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); + res=NULL; goto err; } + else if (gai_err < 0) /* Not supported fallback in gethostbyname */ + { + ERR_get_error(); /* suppress the error generated by BIO_getaddrinfo */ + /* do a gethostbyname */ + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); + locked = 1; + he=BIO_gethostbyname(str); + if (he == NULL) + { + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); + goto err; + } - /* cast to short because of win16 winsock definition */ - if ((short)he->h_addrtype != AF_INET) + /* cast to short because of win16 winsock definition */ + if ((short)he->h_addrtype != AF_INET) + { + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); + goto err; + } + addr = he->h_addr; + addrlen = he->h_length; + } + else { - BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); - goto err; + if (res->ai_family == AF_INET) + { + assert(res->ai_addrlen == sizeof(struct sockaddr_in)); + addr = (char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr; + addrlen = 4; + } + else if (res->ai_family == AF_INET6) + { + assert(res->ai_addrlen == sizeof(struct sockaddr_in6)); + addr = (char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr.s6_addr; + addrlen = 16; + } + else + goto err; } - for (i=0; i<4; i++) - ip[i]=he->h_addr_list[0][i]; + for (i=0; i < addrlen; i++) + ip[i]=addr[i]; /* Store the address in network byte order */ err = 0; err: if (locked) CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); + if (res) + BIO_freeaddrinfo(res); if (err) { ERR_add_error_data(2,"host=",str); @@ -498,7 +544,7 @@ #endif ERR_add_error_data(1, reason); } - return (-1); + return (0); } return (1); } @@ -670,122 +716,133 @@ return(1); } -int BIO_get_accept_socket(char *host, int bind_mode) +static int parse_ip(char *str, char **host, char **port, int *is_inet6) { - int ret=0; - union { - struct sockaddr sa; - struct sockaddr_in sa_in; -#if OPENSSL_USE_IPV6 - struct sockaddr_in6 sa_in6; -#endif - } server,client; - int s=INVALID_SOCKET,cs,addrlen; - unsigned char ip[4]; - unsigned short port; - char *str=NULL,*e; - char *h,*p; - unsigned long l; - int err_num; - - if (BIO_sock_init() != 1) return(INVALID_SOCKET); - - if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); - - h=p=NULL; - h=str; - for (e=str; *e; e++) - { - if (*e == ':') + char *tmp; + char *h = *host = NULL; + char *p = *port = NULL; + + *is_inet6 = 0; + if (*str == '\0') + return (0); + if (*str == '[' && (tmp = strchr(str + 1, ']'))) + { + h = str + 1; + *tmp++ = '\0'; + if (*tmp == ':') + p = tmp + 1; + else if (*tmp != '\0') + return (0); + *is_inet6 = 1; + } + else + { + if ((tmp = strchr(str, ':'))) { - p=e; + h = str; + *tmp++ = '\0'; + p = tmp; } - else if (*e == '/') + else if ((tmp = strchr(str, '/'))) { - *e='\0'; - break; + if (*(tmp + 1) != '\0') + return (0); + p = str; + *tmp = '\0'; } - } - if (p) *p++='\0'; /* points at last ':', '::port' is special [see below] */ - else p=h,h=NULL; - -#ifdef EAI_FAMILY - do { - static union { void *p; - int (WSAAPI *f)(const char *,const char *, - const struct addrinfo *, - struct addrinfo **); - } p_getaddrinfo = {NULL}; - static union { void *p; - void (WSAAPI *f)(struct addrinfo *); - } p_freeaddrinfo = {NULL}; - struct addrinfo *res,hint; + else + h = str; + } + if (h && (*h == '\0' || !strcmp(h, "*"))) + h = NULL; + if (p && (*p == '\0' || !strcmp(p, "*"))) + p = NULL; + *host = h; + *port = p; + return (1); + } - if (p_getaddrinfo.p==NULL) - { - if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL || - (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL) - p_getaddrinfo.p=(void*)-1; - } - if (p_getaddrinfo.p==(void *)-1) break; +static int fill_addr(union sa_storage *sa, char *host, char *port, int is_inet6) + { + unsigned short p; + int sa_len = 0; +#ifdef OPENSSL_USE_IPV6 + unsigned char h[16]; +#else + unsigned char h[4]; +#endif - /* '::port' enforces IPv6 wildcard listener. Some OSes, - * e.g. Solaris, default to IPv6 without any hint. Also - * note that commonly IPv6 wildchard socket can service - * IPv4 connections just as well... */ - memset(&hint,0,sizeof(hint)); - hint.ai_flags = AI_PASSIVE; - if (h) - { - if ((e = strchr(h,':'))) + if (!BIO_get_port(port,&p)) return (0); + memset((char *)sa,0,sizeof(*sa)); + memset(h, 0, sizeof(h)); + if (is_inet6) /* deal with inet6 format (ie: [host]:port) */ + { +#ifdef OPENSSL_USE_IPV6 + assert(sizeof(*sa) >= sizeof(struct sockaddr_in6)); + sa->sa_in6.sin6_family = AF_INET6; + sa->sa_in6.sin6_port = htons(p); + sa_len = sizeof(sa->sa_in6); +#ifdef SIN6_LEN /* BSD 4.4 */ + sa->sa_in6.sin6_len = sa_len; +#endif + if (h == NULL) + sa->sa_in6.sin6_addr = in6addr_any; + else { - *e = '\0'; - if (h[1]=='\0') h=NULL; -#if OPENSSL_USE_IPV6 - hint.ai_family = AF_INET6; + if (!BIO_get_host_ip(host, h)) return (0); + memcpy(&sa->sa_in6.sin6_addr.s6_addr, h, sizeof(h)); + } #else - h=NULL; + /* inet6 format used without OPENSSL configured properly, thus invalid */ + BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_INVALID_IP_ADDRESS); + return (0); +#endif + } + else /* we must resolve an inet4 address */ + { + assert(sizeof(*sa) >= sizeof(struct sockaddr_in)); + sa->sa_in.sin_family=AF_INET; + sa->sa_in.sin_port=htons(p); + sa_len = sizeof(sa->sa_in); +#if 1 + /* TODO add a definition at compile time */ + sa->sa_in.sin_len = sa_len; #endif - } - else if (h[0]=='*' && h[1]=='\0') + if (h == NULL) + sa->sa_in.sin_addr.s_addr=INADDR_ANY; + else { - hint.ai_family = AF_INET; - h=NULL; + /* + * TODO force inet4 listening even with OPENSSL_USE_IPV6 + * + * CONF_LOCAL(h) + * CONF_INETONLY(h) + */ + if (!BIO_get_host_ip(host, h)) return (0); + memcpy(&sa->sa_in.sin_addr.s_addr, h, 4); /* always 4 here especially when using inet6 */ } } + return (sa_len); + } - if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break; - - addrlen = res->ai_addrlen<=sizeof(server) ? - res->ai_addrlen : - sizeof(server); - memcpy(&server, res->ai_addr, addrlen); - - (*p_freeaddrinfo.f)(res); - goto again; - } while (0); -#endif - - if (!BIO_get_port(p,&port)) goto err; - - memset((char *)&server,0,sizeof(server)); - server.sa_in.sin_family=AF_INET; - server.sa_in.sin_port=htons(port); - addrlen = sizeof(server.sa_in); +int BIO_get_accept_socket(char *host, int bind_mode) + { + union sa_storage server,client; + int s=INVALID_SOCKET,cs,addrlen; + char *str=NULL; + char *h,*p; + int err_num; + int is_inet6 = 0; + int ret = 0; - if (h == NULL || strcmp(h,"*") == 0) - server.sa_in.sin_addr.s_addr=INADDR_ANY; - else + if (BIO_sock_init() != 1) return(INVALID_SOCKET); + if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); + if (parse_ip(str, &h, &p, &is_inet6) != 1) { - if (!BIO_get_host_ip(h,&(ip[0]))) goto err; - l=(unsigned long) - ((unsigned long)ip[0]<<24L)| - ((unsigned long)ip[1]<<16L)| - ((unsigned long)ip[2]<< 8L)| - ((unsigned long)ip[3]); - server.sa_in.sin_addr.s_addr=htonl(l); + BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_INVALID_IP_ADDRESS); + goto err; } - + if ((addrlen = fill_addr(&server, h, p, is_inet6)) == 0) goto err; /* Errors have been already generated */ again: s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL); if (s == INVALID_SOCKET) @@ -820,7 +877,7 @@ #endif { client = server; - if (h == NULL || strcmp(h,"*") == 0) + if (h == NULL) { #if OPENSSL_USE_IPV6 if (client.sa.sa_family == AF_INET6) Modified: soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h ============================================================================== --- soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h Sun Jun 17 00:28:57 2012 (r237820) +++ soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h Sun Jun 17 02:29:04 2012 (r237821) @@ -76,8 +76,12 @@ # endif #endif -/* under which condition ? */ +/* TODO + * Under which condition ? + */ #include +#include +#include #ifdef __cplusplus extern "C" { @@ -720,9 +724,40 @@ */ #ifndef EAI_FAMILY -struct addrinfo { /* dummy interface */ }; + +struct addrinfo /* fake interface */ + { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + int ai_addrlen; + char* ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; + }; + +/* dummy definitions */ +#define AI_PASSIVE 0 +#define AI_CANONNAME 0 +#define AI_NUMERICHOST 0 +#define AI_NUMERICSERV 0 +#define AI_ALL 0 +#define AI_V4MAPPED_CFG 0 +#define AI_ADDRCONFIG 0 +#define AI_V4MAPPED 0 + #endif +union sa_storage + { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sa_in6; +#endif + }; + int BIO_getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res); void BIO_freeaddrinfo(struct addrinfo *ai); Modified: soc2012/exxo/regress/openssl-1.0.1c/Makefile ============================================================================== --- soc2012/exxo/regress/openssl-1.0.1c/Makefile Sun Jun 17 00:28:57 2012 (r237820) +++ soc2012/exxo/regress/openssl-1.0.1c/Makefile Sun Jun 17 02:29:04 2012 (r237821) @@ -1,6 +1,7 @@ REGRESS_TARGETS = rg1 rg2 rg3 OPENSSL = ${.CURDIR}/../../openssl-1.0.1c +OPENSSL_FLAGS += -g -DOPENSSL_USE_IPV6 LIB_CRYPTO = $(OPENSSL)/libcrypto.a MAKE ?= make @@ -8,7 +9,7 @@ .PHONY: all clean openssl openssl-fconfig openssl-clean regress .MAIN: all -OPENSSL_CONFIGURE = cd $(OPENSSL) && ./config -g +OPENSSL_CONFIGURE = cd $(OPENSSL) && ./config $(OPENSSL_FLAGS) depend $(LIB_CRYPTO): .SILENT if ! [ -e $(OPENSSL)/Makefile.bak ]; then \ Modified: soc2012/exxo/regress/regress.in ============================================================================== --- soc2012/exxo/regress/regress.in Sun Jun 17 00:28:57 2012 (r237820) +++ soc2012/exxo/regress/regress.in Sun Jun 17 02:29:04 2012 (r237821) @@ -72,7 +72,9 @@ _startest_() { - ${BINDIR}/${BASENAME} > "${LOGDIR}/${BASENAME}-err.log" 2>&1 & + local args="" + + stdbuf -o L ${BINDIR}/${BASENAME} "${args}" > "${LOGDIR}/${BASENAME}-err.log" 2>&1 & PID=$! }