From: Thierry Fournier Date: Thu, 24 Jan 2013 13:15:43 +0000 (+0100) Subject: BUG/MEDIUM: ssl: openssl 0.9.8 doesn't open /dev/random before chroot X-Git-Tag: v1.5-dev18~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=383085f6c0823069afd84411be28d5d5a3fe8e4e;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: ssl: openssl 0.9.8 doesn't open /dev/random before chroot Openssl needs to access /dev/urandom to initialize its internal random number generator. It does so when it needs a random for the first time, which fails if it is a handshake performed after the chroot(), causing all SSL incoming connections to fail. This fix consists in calling RAND_bytes() to produce a random before the chroot, which will in turn open /dev/urandom before it's too late, and avoid the issue. If the random generator fails to work while processing the config, haproxy now fails with an error instead of causing SSL connections to fail at runtime. --- diff --git a/src/ssl_sock.c b/src/ssl_sock.c index f814276064..3aeba744a7 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -478,6 +479,22 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *cu return cfgerr; } +/* Make sure openssl opens /dev/urandom before the chroot. The work is only + * done once. Zero is returned if the operation fails. No error is returned + * if the random is said as not implemented, because we expect that openssl + * will use another method once needed. + */ +static int ssl_initialize_random() +{ + unsigned char random; + static int random_initialized = 0; + + if (!random_initialized && RAND_bytes(&random, 1) != 0) + random_initialized = 1; + + return random_initialized; +} + #ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */ #define SSL_OP_CIPHER_SERVER_PREFERENCE 0 #endif @@ -526,6 +543,12 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_RELEASE_BUFFERS; + /* Make sure openssl opens /dev/urandom before the chroot */ + if (!ssl_initialize_random()) { + Alert("OpenSSL random data generator initialization failed.\n"); + cfgerr++; + } + if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3) ssloptions |= SSL_OP_NO_SSLv3; if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10) @@ -635,6 +658,12 @@ int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy) SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_RELEASE_BUFFERS; + /* Make sure openssl opens /dev/urandom before the chroot */ + if (!ssl_initialize_random()) { + Alert("OpenSSL random data generator initialization failed.\n"); + cfgerr++; + } + /* Initiate SSL context for current server */ srv->ssl_ctx.reused_sess = NULL; if (srv->use_ssl)