pkgsrc/security/stud/patches/patch-stud.c
2015-03-04 12:04:30 +00:00

129 lines
4.6 KiB
C

$NetBSD: patch-stud.c,v 1.4 2015/03/04 12:04:30 jperkin Exp $
SunOS fixes as per https://github.com/bumptech/stud/pull/71
SSL fixes as per https://github.com/bumptech/stud/pull/130
TLS fixes as per https://github.com/bumptech/stud/pull/138
--- stud.c.orig 2012-08-10 23:40:19.000000000 +0000
+++ stud.c
@@ -189,9 +189,17 @@ typedef struct proxystate {
/* Set a file descriptor (socket) to non-blocking mode */
static void setnonblocking(int fd) {
- int flag = 1;
-
- assert(ioctl(fd, FIONBIO, &flag) == 0);
+ int flag;
+#if defined(O_NONBLOCK)
+ /* O_NONBLOCK is more portable and POSIX-standard */
+ flag = O_NONBLOCK;
+ assert (fcntl(fd, F_SETFL, flag) == 0);
+#elif defined(FIONBIO)
+ flag = 1;
+ assert (ioctl(fd, FIONBIO, &flag) == 0);
+#else
+# error O_NONBLOCK and FIONBIO are both undefined for this platform
+#endif
}
/* set a tcp socket to use TCP Keepalive */
@@ -203,9 +211,9 @@ static void settcpkeepalive(int fd) {
ERR("Error activating SO_KEEPALIVE on client socket: %s", strerror(errno));
}
+#ifdef TCP_KEEPIDLE
optval = CONFIG->TCP_KEEPALIVE_TIME;
optlen = sizeof(optval);
-#ifdef TCP_KEEPIDLE
if(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) {
ERR("Error setting TCP_KEEPIDLE on client socket: %s", strerror(errno));
}
@@ -598,16 +606,14 @@ SSL_CTX *make_ctx(const char *pemfile) {
#endif
if (CONFIG->ETYPE == ENC_TLS) {
- ctx = SSL_CTX_new((CONFIG->PMODE == SSL_CLIENT) ?
- TLSv1_client_method() : TLSv1_server_method());
- } else if (CONFIG->ETYPE == ENC_SSL) {
- ctx = SSL_CTX_new((CONFIG->PMODE == SSL_CLIENT) ?
- SSLv23_client_method() : SSLv23_server_method());
- } else {
+ ssloptions |= SSL_OP_NO_SSLv3;
+ } else if (CONFIG->ETYPE != ENC_SSL) {
assert(CONFIG->ETYPE == ENC_TLS || CONFIG->ETYPE == ENC_SSL);
return NULL; // Won't happen, but gcc was complaining
}
+ ctx = SSL_CTX_new((CONFIG->PMODE == SSL_CLIENT) ?
+ SSLv23_client_method() : SSLv23_server_method());
SSL_CTX_set_options(ctx, ssloptions);
SSL_CTX_set_info_callback(ctx, info_callback);
@@ -889,6 +895,13 @@ static void shutdown_proxy(proxystate *p
close(ps->fd_up);
close(ps->fd_down);
+ // Clear the SSL error queue - it might contain details
+ // of errors that we haven't consumed for whatever reason.
+ // If we don't, future calls to SSL_get_error will lead to
+ // weird/confusing results that can throw off the handling
+ // of normal conditions like SSL_ERROR_WANT_READ.
+ ERR_clear_error();
+
SSL_set_shutdown(ps->ssl, SSL_SENT_SHUTDOWN);
SSL_free(ps->ssl);
@@ -1197,7 +1210,15 @@ static void client_handshake(struct ev_l
shutdown_proxy(ps, SHUTDOWN_SSL);
}
else {
- LOG("{%s} Unexpected SSL error (in handshake): %d\n", w->fd == ps->fd_up ? "client" : "backend", err);
+
+ // Try and get more detail on the error from the SSL
+ // error queue. ERR_error_string requires a char buffer
+ // of 120 bytes.
+ unsigned long err_detail = ERR_get_error();
+ char err_msg[120];
+ ERR_error_string(err_detail, err_msg);
+
+ LOG("{client} Unexpected SSL error (in handshake): %d, %s\n", err, err_msg);
shutdown_proxy(ps, SHUTDOWN_SSL);
}
}
@@ -1312,7 +1333,7 @@ static void handle_accept(struct ev_loop
break;
default:
- assert(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN);
+ assert(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN || errno == ECONNABORTED);
break;
}
return;
@@ -1751,24 +1772,16 @@ void daemonize () {
exit(0);
}
- /* close standard streams */
- fclose(stdin);
- fclose(stdout);
- fclose(stderr);
-
/* reopen standard streams to null device */
- stdin = fopen(NULL_DEV, "r");
- if (stdin == NULL) {
+ if (freopen(NULL_DEV, "r", stdin) == NULL) {
ERR("Unable to reopen stdin to %s: %s\n", NULL_DEV, strerror(errno));
exit(1);
}
- stdout = fopen(NULL_DEV, "w");
- if (stdout == NULL) {
+ if (freopen(NULL_DEV, "w", stdout) == NULL) {
ERR("Unable to reopen stdout to %s: %s\n", NULL_DEV, strerror(errno));
exit(1);
}
- stderr = fopen(NULL_DEV, "w");
- if (stderr == NULL) {
+ if (freopen(NULL_DEV, "w", stderr) == NULL) {
ERR("Unable to reopen stderr to %s: %s\n", NULL_DEV, strerror(errno));
exit(1);
}