changeset 4245:8d39230df833 stable-1.0

Merging r4034, r4186, r4187, r4229, r4235, r4237: SSL related fixes: *) Better handling of various per-server ssl options with SNI. SSL_set_SSL_CTX() doesn't touch values cached within ssl connection structure, it only changes certificates (at least as of now, OpenSSL 1.0.0d and earlier). As a result settings like ssl_verify_client, ssl_verify_depth, ssl_prefer_server_ciphers are only configurable on per-socket basis while with SNI it should be possible to specify them different for two servers listening on the same socket. Workaround is to explicitly re-apply settings we care about from context to ssl connection in servername callback. Note that SSL_clear_options() is only available in OpenSSL 0.9.8m+. I.e. with older versions it is not possible to clear ssl_prefer_server_ciphers option if it's set in default server for a socket. *) Disabling SSL compression. This saves about 300K per SSL connection. The SSL_OP_NO_COMPRESSION option is available since OpenSSL 1.0.0. *) Releasing memory of idle SSL connection. This saves about 34K per SSL connection. The SSL_MODE_RELEASE_BUFFERS option is available since OpenSSL 1.0.0d. *) Decrease of log level of some SSL handshake errors. *) Fixed segfault on configuration testing with ssl (ticket #37). The following config caused segmentation fault due to conf->file not being properly set if "ssl on" was inherited from the http level: http { ssl on; server { } } *) Silently ignoring a stale global SSL error left after disabled renegotiation.
author Igor Sysoev <igor@sysoev.ru>
date Tue, 01 Nov 2011 13:00:30 +0000
parents df9d3dd8cfc0
children d3568507db51
files src/event/ngx_event_openssl.c src/http/modules/ngx_http_ssl_module.c src/http/ngx_http_request.c
diffstat 3 files changed, 62 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -175,6 +175,14 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_
         SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
     }
 
+#ifdef SSL_OP_NO_COMPRESSION
+    SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
+#endif
+
+#ifdef SSL_MODE_RELEASE_BUFFERS
+    SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
@@ -855,6 +863,13 @@ ngx_ssl_handle_recv(ngx_connection_t *c,
 
         ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
 
+        while (ERR_peek_error()) {
+            ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
+                          "ignoring stale global SSL error");
+        }
+
+        ERR_clear_error();
+
         c->ssl->no_wait_shutdown = 1;
         c->ssl->no_send_shutdown = 1;
 
@@ -1344,19 +1359,37 @@ ngx_ssl_connection_error(ngx_connection_
         n = ERR_GET_REASON(ERR_peek_error());
 
             /* handshake failures */
-        if (n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                     /*  129 */
+        if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC                        /*  103 */
+            || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  /*  129 */
             || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
+            || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              /*  151 */
+            || n == SSL_R_EXCESSIVE_MESSAGE_SIZE                     /*  152 */
             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
+            || n == SSL_R_NO_COMPRESSION_SPECIFIED                   /*  187 */
             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
             || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
+#ifdef SSL_R_PARSE_TLSEXT
+            || n == SSL_R_PARSE_TLSEXT                               /*  227 */
+#endif
             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
             || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
+#ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
+            || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG                   /*  335 */
+            || n == SSL_R_RENEGOTIATION_ENCODING_ERR                 /*  336 */
+            || n == SSL_R_RENEGOTIATION_MISMATCH                     /*  337 */
+#endif
+#ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
+            || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED       /*  338 */
+#endif
+#ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
+            || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING           /*  345 */
+#endif
             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -346,7 +346,16 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
 
     ngx_pool_cleanup_t  *cln;
 
-    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+    if (conf->enable == NGX_CONF_UNSET) {
+        if (prev->enable == NGX_CONF_UNSET) {
+            conf->enable = 0;
+
+        } else {
+            conf->enable = prev->enable;
+            conf->file = prev->file;
+            conf->line = prev->line;
+        }
+    }
 
     ngx_conf_merge_value(conf->session_timeout,
                          prev->session_timeout, 300);
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -673,6 +673,24 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *
 
     SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
 
+    /*
+     * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
+     * adjust other things we care about
+     */
+
+    SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
+                   SSL_CTX_get_verify_callback(sscf->ssl.ctx));
+
+    SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
+
+#ifdef SSL_CTRL_CLEAR_OPTIONS
+    /* only in 0.9.8m+ */
+    SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
+                                ~SSL_CTX_get_options(sscf->ssl.ctx));
+#endif
+
+    SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
+
     return SSL_TLSEXT_ERR_OK;
 }