--- src/client.c 2011-05-02 18:12:53.000000000 +0200 +++ src/client.c 2011-06-17 15:19:44.000000000 +0200 @@ -106,10 +106,8 @@ if(!c->opt->option.retry) break; sleep(1); /* FIXME: not a good idea in ucontext threading */ -#ifndef USE_UCONTEXT str_stats(); str_cleanup(); -#endif } } else run_client(c); @@ -119,18 +117,17 @@ #ifdef DEBUG_STACK_SIZE stack_info(0); /* display computed value */ #endif +#ifdef USE_UCONTEXT + s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); +#endif str_stats(); -#if defined(USE_WIN32) && !defined(_WIN32_WCE) str_cleanup(); + /* s_log() is not allowed after str_cleanup() */ +#if defined(USE_WIN32) && !defined(_WIN32_WCE) _endthread(); #endif #ifdef USE_UCONTEXT - s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); - /* no str_cleanup() here, as all contexts share the same CPU thread */ s_poll_wait(NULL, 0, 0); /* wait on poll() */ - s_log(LOG_ERR, "INTERNAL ERROR: failed to drop context"); -#else - str_cleanup(); #endif return NULL; } @@ -314,9 +320,9 @@ while(1) { #if OPENSSL_VERSION_NUMBER<0x1000002f - /* this critical section is a crude workaround for CVE-2010-3864 */ - /* see http://www.securityfocus.com/bid/44884 for details */ - /* NOTE: this critical section also covers callbacks (e.g. OCSP) */ + /* this critical section is a crude workaround for CVE-2010-3864 * + * see http://www.securityfocus.com/bid/44884 for details * + * NOTE: this critical section also covers callbacks (e.g. OCSP) */ enter_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ if(c->opt->option.client) @@ -821,22 +827,26 @@ type=strchr(line, ':'); if(!type) { s_log(LOG_ERR, "Malformed IDENT response"); + str_free(line); longjmp(c->err, 1); } *type++='\0'; system=strchr(type, ':'); if(!system) { s_log(LOG_ERR, "Malformed IDENT response"); + str_free(line); longjmp(c->err, 1); } *system++='\0'; if(strcmp(type, " USERID ")) { s_log(LOG_ERR, "Incorrect INETD response type"); + str_free(line); longjmp(c->err, 1); } user=strchr(system, ':'); if(!user) { s_log(LOG_ERR, "Malformed IDENT response"); + str_free(line); longjmp(c->err, 1); } *user++='\0'; @@ -846,9 +856,11 @@ safestring(user); s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)", c->accepted_address, user); + str_free(line); longjmp(c->err, 1); } s_log(LOG_INFO, "IDENT authentication passed"); + str_free(line); } #if defined(_WIN32_WCE) || defined(__vms) @@ -878,8 +890,8 @@ execname_l=str2tstr(c->opt->execname); execargs_l=str2tstr(c->opt->execargs); CreateProcess(execname_l, execargs_l, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); - free(execname_l); - free(execargs_l); + str_free(execname_l); + str_free(execargs_l); closesocket(fd[1]); CloseHandle(pi.hProcess); @@ -916,6 +928,7 @@ longjmp(c->err, 1); case 0: /* child */ closesocket(fd[0]); + set_nonblock(fd[1], 0); /* switch back to blocking mode */ /* dup2() does not copy FD_CLOEXEC flag */ dup2(fd[1], 0); dup2(fd[1], 1); @@ -969,9 +982,10 @@ s=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#1"); if(s<0) longjmp(c->err, 1); - fd[1]=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#2"); - if(fd[1]<0) + c->fd=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#2"); + if(c->fd<0) longjmp(c->err, 1); + addrlen=sizeof addr; memset(&addr, 0, addrlen); addr.in.sin_family=AF_INET; @@ -979,22 +993,30 @@ addr.in.sin_port=htons(0); /* dynamic port allocation */ if(bind(s, &addr.sa, addrlen)) log_error(LOG_DEBUG, get_last_socket_error(), "bind#1"); - if(bind(fd[1], &addr.sa, addrlen)) + if(bind(c->fd, &addr.sa, addrlen)) log_error(LOG_DEBUG, get_last_socket_error(), "bind#2"); + if(listen(s, 1)) { + closesocket(s); sockerror("listen"); longjmp(c->err, 1); } if(getsockname(s, &addr.sa, &addrlen)) { + closesocket(s); sockerror("getsockname"); longjmp(c->err, 1); } - if(connect(fd[1], &addr.sa, addrlen)) { - sockerror("connect"); + if(connect_blocking(c, &addr, addr_len(addr))) { + closesocket(s); longjmp(c->err, 1); } - if((fd[0]=s_accept(s, &addr.sa, &addrlen, 1, "accept"))<0) + fd[0]=s_accept(s, &addr.sa, &addrlen, 1, "accept"); + if(fd[0]<0) { + closesocket(s); longjmp(c->err, 1); + } + fd[1]=c->fd; + c->fd=-1; closesocket(s); /* don't care about the result */ #else if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "socketpair")) --- src/stunnel.c 2011/06/18 04:05:08 1.1 +++ src/stunnel.c 2011/06/18 04:09:42 @@ -496,11 +496,9 @@ #endif static int setup_fd(int fd, int nonblock, char *msg) { -#ifdef USE_WIN32 - unsigned long l; -#else /* USE_WIN32 */ - int err, flags; -#endif /* USE_WIN32 */ +#ifdef FD_CLOEXEC + int err; +#endif /* FD_CLOEXEC */ if(fd<0) { sockerror(msg); @@ -512,11 +510,33 @@ closesocket(fd); return -1; } + #ifndef USE_NEW_LINUX_API -#if defined F_GETFL && defined F_SETFL && defined O_NONBLOCK && !defined __INNOTEK_LIBC__ + set_nonblock(fd, nonblock); +#ifdef FD_CLOEXEC + do { + err=fcntl(fd, F_SETFD, FD_CLOEXEC); + } while(err<0 && get_last_socket_error()==EINTR); + if(err<0) + sockerror("fcntl SETFD"); /* non-critical */ +#endif /* FD_CLOEXEC */ +#endif /* USE_NEW_LINUX_API */ + s_log(LOG_DEBUG, "%s: FD=%d allocated (%sblocking mode)", + msg, fd, nonblock?"non-":""); + return fd; +} + +void set_nonblock(int fd, unsigned long nonblock) { +#if defined F_GETFL && defined F_SETFL && defined O_NONBLOCK && !defined __INNOTEK_LIBC__ + int err, flags; + do { flags=fcntl(fd, F_GETFL, 0); } while(flags<0 && get_last_socket_error()==EINTR); + if(flags<0) { + sockerror("fcntl GETFL"); /* non-critical */ + return; + } if(nonblock) flags|=O_NONBLOCK; else @@ -526,21 +547,10 @@ } while(err<0 && get_last_socket_error()==EINTR); if(err<0) sockerror("fcntl SETFL"); /* non-critical */ -#ifdef FD_CLOEXEC - do { - err=fcntl(fd, F_SETFD, FD_CLOEXEC); - } while(err<0 && get_last_socket_error()==EINTR); - if(err<0) - sockerror("fcntl SETFD"); /* non-critical */ -#endif /* FD_CLOEXEC */ #else /* use fcntl() */ - if(ioctlsocket(fd, FIONBIO, &l)<0) + if(ioctlsocket(fd, FIONBIO, &nonblock)<0) sockerror("ioctlsocket"); /* non-critical */ #endif /* use fcntl() */ -#endif /* USE_NEW_LINUX_API */ - s_log(LOG_DEBUG, "%s: FD=%d allocated (%sblocking mode)", - msg, fd, nonblock?"non-":""); - return fd; } /**************************************** log messages to identify build */ --- src/prototypes.h 2011/06/18 04:05:02 1.1 +++ src/prototypes.h 2011/06/18 04:06:08 @@ -256,6 +256,7 @@ int s_accept(int, struct sockaddr *, socklen_t *, int, char *); void stunnel_info(int); void die(int); +void set_nonblock(int, unsigned long); /**************************************** prototypes for log.c */