diff src/event/ngx_event_openssl.c @ 364:a39aab45a53f NGINX_0_6_26

nginx 0.6.26 *) Bugfix: the "proxy_store" and "fastcgi_store" directives did not check a response length. *) Bugfix: a segmentation fault occurred in worker process, if big value was used in a "expires" directive. Thanks to Joaquin Cuenca Abela. *) Bugfix: nginx incorrectly detected cache line size on Pentium 4. Thanks to Gena Makhomed. *) Bugfix: in proxied or FastCGI subrequests a client original method was used instead of the GET method. *) Bugfix: socket leak in HTTPS mode if deferred accept was used. Thanks to Ben Maurer. *) Bugfix: nginx issued the bogus error message "SSL_shutdown() failed (SSL: )"; bug appeared in 0.6.23. *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" error; bug appeared in 0.6.23.
author Igor Sysoev <http://sysoev.ru>
date Mon, 11 Feb 2008 00:00:00 +0300
parents 2b41fbc2e39e
children babd3d9efb62
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -187,6 +187,13 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_
         SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
     }
 
+    /*
+     * we need this option because in ngx_ssl_send_chain()
+     * we may switch to a buffered write and may copy leftover part of
+     * previously unbuffered data to our internal buffer
+     */
+    SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
     return NGX_OK;
@@ -1035,19 +1042,16 @@ ngx_ssl_shutdown(ngx_connection_t *c)
 
     sslerr = 0;
 
-    /* SSL_shutdown() never return -1, on error it return 0 */
-
-    if (n != 1) {
+    /* SSL_shutdown() never returns -1, on error it returns 0 */
+
+    if (n != 1 && ERR_peek_error()) {
         sslerr = SSL_get_error(c->ssl->connection, n);
 
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "SSL_get_error: %d", sslerr);
     }
 
-    if (n == 1
-        || sslerr == SSL_ERROR_ZERO_RETURN
-        || (sslerr == 0 && c->timedout))
-    {
+    if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
         SSL_free(c->ssl->connection);
         c->ssl = NULL;
 
@@ -1111,6 +1115,7 @@ static void
 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
     char *text)
 {
+    int         n;
     ngx_uint_t  level;
 
     level = NGX_LOG_CRIT;
@@ -1124,6 +1129,9 @@ ngx_ssl_connection_error(ngx_connection_
             || err == NGX_ETIMEDOUT
 #endif
             || err == NGX_ECONNREFUSED
+            || err == NGX_ENETDOWN
+            || err == NGX_ENETUNREACH
+            || err == NGX_EHOSTDOWN
             || err == NGX_EHOSTUNREACH)
         {
             switch (c->log_error) {
@@ -1141,6 +1149,35 @@ ngx_ssl_connection_error(ngx_connection_
                 break;
             }
         }
+
+    } else if (sslerr == SSL_ERROR_SSL) {
+
+        n = ERR_GET_REASON(ERR_peek_error());
+
+            /* handshake failures */
+        if (n == SSL_R_NO_SHARED_CIPHER
+            || n == SSL_R_UNEXPECTED_MESSAGE
+            || n == SSL_R_WRONG_VERSION_NUMBER
+            || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
+            || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED
+            || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER
+            || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA)
+        {
+            switch (c->log_error) {
+
+            case NGX_ERROR_IGNORE_ECONNRESET:
+            case NGX_ERROR_INFO:
+                level = NGX_LOG_INFO;
+                break;
+
+            case NGX_ERROR_ERR:
+                level = NGX_LOG_ERR;
+                break;
+
+            default:
+                break;
+            }
+        }
     }
 
     ngx_ssl_error(level, c->log, err, text);
@@ -1150,18 +1187,21 @@ ngx_ssl_connection_error(ngx_connection_
 static void
 ngx_ssl_clear_error(ngx_log_t *log)
 {
-    if (ERR_peek_error()) {
+    while (ERR_peek_error()) {
         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
     }
+
+    ERR_clear_error();
 }
 
 
 void ngx_cdecl
 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
 {
-    u_long   n;
-    va_list  args;
-    u_char   errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
+    u_long    n;
+    va_list   args;
+    u_char   *p, *last;
+    u_char    errstr[NGX_MAX_CONF_ERRSTR];
 
     last = errstr + NGX_MAX_CONF_ERRSTR;
 
@@ -1171,7 +1211,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_
 
     p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
 
-    while (p < last) {
+    for ( ;; ) {
 
         n = ERR_get_error();
 
@@ -1179,6 +1219,10 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_
             break;
         }
 
+        if (p >= last) {
+            continue;
+        }
+
         *p++ = ' ';
 
         ERR_error_string_n(n, (char *) p, last - p);