- fix non-blocking socket handling (backport from 4.37)

OBS-URL: https://build.opensuse.org/package/show/security:Stunnel/stunnel?expand=0&rev=41
This commit is contained in:
Daniel Rahn 2011-06-18 04:15:45 +00:00 committed by Git OBS Bridge
parent 1ca0e0c995
commit 7464662073
3 changed files with 248 additions and 0 deletions

View File

@ -0,0 +1,241 @@
--- 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 */

View File

@ -1,3 +1,8 @@
-------------------------------------------------------------------
Sat Jun 18 03:59:20 UTC 2011 - daniel.rahn@novell.com
- fix non-blocking socket handling (backport from 4.37)
-------------------------------------------------------------------
Thu Jun 16 11:44:32 UTC 2011 - daniel.rahn@novell.com

View File

@ -33,6 +33,7 @@ Source2: stunnel.README
Source3: sysconfig.syslog-stunnel
Source4: stunnel.rc
Patch0: stunnel-listenqueue-option.patch
Patch1: non-blocking-socket-handling.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%define VENDOR SUSE
@ -50,6 +51,7 @@ without any changes to the program code.
%prep
%setup -q
%patch0 -p0
%patch1 -p0
%build
#autoreconf -fi