diff src/event/ngx_event_openssl.c @ 542:2b9e388c61f1 NGINX_0_8_23

nginx 0.8.23 *) Security: now SSL/TLS renegotiation is disabled. Thanks to Maxim Dounin. *) Bugfix: listen unix domain socket did not inherit while online upgrade. *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive did not without yet another directive with any IP address. *) Bugfix: segmentation fault and infinite looping in resolver. *) Bugfix: in resolver. Thanks to Artem Bokhan.
author Igor Sysoev <http://sysoev.ru>
date Wed, 11 Nov 2009 00:00:00 +0300
parents c04fa65fe604
children 43e02819c5cf
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -15,6 +15,8 @@ typedef struct {
 
 
 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
+static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
+    int ret);
 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
 static void ngx_ssl_write_handler(ngx_event_t *wev);
@@ -175,6 +177,8 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_
 
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
+    SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
+
     return NGX_OK;
 }
 
@@ -350,6 +354,22 @@ ngx_http_ssl_verify_callback(int ok, X50
 }
 
 
+static void
+ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
+{
+    ngx_connection_t  *c;
+
+    if (where & SSL_CB_HANDSHAKE_START) {
+        c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
+
+        if (c->ssl->handshaked) {
+            c->ssl->renegotiation = 1;
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
+        }
+    }
+}
+
+
 ngx_int_t
 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
 {
@@ -587,6 +607,11 @@ ngx_ssl_handshake(ngx_connection_t *c)
         c->recv_chain = ngx_ssl_recv_chain;
         c->send_chain = ngx_ssl_send_chain;
 
+        /* initial handshake done, disable renegotiation (CVE-2009-3555) */
+        if (c->ssl->connection->s3) {
+            c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+        }
+
         return NGX_OK;
     }
 
@@ -789,6 +814,21 @@ ngx_ssl_handle_recv(ngx_connection_t *c,
     int        sslerr;
     ngx_err_t  err;
 
+    if (c->ssl->renegotiation) {
+        /*
+         * disable renegotiation (CVE-2009-3555):
+         * OpenSSL (at least up to 0.9.8l) does not handle disabled
+         * renegotiation gracefully, so drop connection here
+         */
+
+        ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
+
+        c->ssl->no_wait_shutdown = 1;
+        c->ssl->no_send_shutdown = 1;
+
+        return NGX_ERROR;
+    }
+
     if (n > 0) {
 
         if (c->ssl->saved_write_handler) {