]> git.kaiwu.me - nginx.git/commitdiff
nginx-0.3.45-RELEASE import release-0.3.45
authorIgor Sysoev <igor@sysoev.ru>
Sat, 6 May 2006 16:28:56 +0000 (16:28 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Sat, 6 May 2006 16:28:56 +0000 (16:28 +0000)
    *) Feature: the "ssl_verify_client", "ssl_verify_depth", and
       "ssl_client_certificate" directives.

    *) Change: the $request_method variable now returns the main request
       method.

    *) Change: the &deg; symbol codes were changed in koi-win conversion
       table.

    *) Feature: the euro and N symbols were added to koi-win conversion
       table.

    *) Bugfix: if nginx distributed the requests among several backends and
       some backend failed, then requests intended for this backend was
       directed to one live backend only instead of being distributed among
       the rest.

12 files changed:
conf/koi-win
docs/xml/nginx/changes.xml
src/core/nginx.h
src/event/ngx_event_connect.c
src/event/ngx_event_openssl.c
src/event/ngx_event_openssl.h
src/http/modules/ngx_http_ssl_module.c
src/http/modules/ngx_http_ssl_module.h
src/http/ngx_http_request.c
src/http/ngx_http_request.h
src/http/ngx_http_special_response.c
src/http/ngx_http_variables.c

index 2b12b8da182ea340001a89326f85eaffe9a36443..99edb1b2b8202708dfccc1e3e2d6660e3cc0b4ab 100644 (file)
@@ -1,12 +1,12 @@
 
 charset_map  koi8-r  windows-1251 {
 
+    80  88 ; # euro
+
     95  95 ; # bullet
 
     9A  A0 ; # &nbsp;
 
-    9C  B0 ; # &deg;
-
     9E  B7 ; # &middot;
 
     A3  B8 ; # small yo
@@ -18,12 +18,16 @@ charset_map  koi8-r  windows-1251 {
     AD  B4 ; # small Ukrainian soft g
     AE  A2 ; # small Byelorussian short u
 
+    B0  B0 ; # &deg;
+
     B3  A8 ; # capital YO
     B4  AA ; # capital Ukrainian YE
 
     B6  B2 ; # capital Ukrainian I
     B7  AF ; # capital Ukrainian J
 
+    B9  B9 ; # No
+
     BD  A5 ; # capital Ukrainian soft G
     BE  A1 ; # capital Byelorussian short U
 
index 92fefa4dbfc4ef39040deb14c1e81ead28452c11..7657a5cc5cece930af0433c90a10197f5142d08c 100644 (file)
@@ -9,6 +9,61 @@
 <title lang="en">nginx changelog</title>
 
 
+<changes ver="0.3.45" date="06.05.2006">
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Ù ssl_verify_client, ssl_verify_depth É ssl_client_certificate.
+</para>
+<para lang="en">
+the "ssl_verify_client", "ssl_verify_depth", and "ssl_client_certificate"
+directives.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÔÅÐÅÒØ ÐÅÒÅÍÅÎÎÁÑ $request_method ×ÏÚ×ÒÁÝÁÅÔ ÍÅÔÏÄ ÔÏÌØËÏ ÏÓÎÏ×ÎÏÇÏ ÚÁÐÒÏÓÁ.
+</para>
+<para lang="en">
+the $request_method variable now returns the main request method.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+× ÔÁÂÌÉÃÅ ÐÅÒÅËÏÄÉÒÏ×ËÉ koi-win ÉÚÍÅÎÅÎÙ ËÏÄÙ ÓÉÍ×ÏÌÁ &amp;deg;.
+</para>
+<para lang="en">
+the &amp;deg; symbol codes were changed in koi-win conversion table.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+× ÔÁÂÌÉÃÕ ÐÅÒÅËÏÄÉÒÏ×ËÉ koi-win ÄÏÂÁ×ÌÅÎÙ ÓÉÍ×ÏÌÙ Å×ÒÏ É ÎÏÍÅÒÁ.
+</para>
+<para lang="en">
+the euro É N symbols were added to koi-win conversion table.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÅÓÌÉ nginx ÒÁÓÐÒÅÄÅÌÑÌ ÚÁÐÒÏÓÙ ÎÁ ÎÅÓËÏÌØËÏ ÍÁÛÉÎ, ÔÏ ÐÒÉ ÐÁÄÅÎÉÉ
+ÏÄÎÏÊ ÉÚ ÎÉÈ ÚÁÐÒÏÓÙ, ÐÒÅÄÎÁÚÎÁÞÅÎÎÙÅ ÄÌÑ ÜÔÏÊ ÍÁÛÉÎÙ, ÐÅÒÅÎÁÐÒÁ×ÌÑÌÉÓØ ÔÏÌØËÏ
+ÎÁ ÏÄÎÕ ÍÁÛÉÎÕ ×ÍÅÓÔÏ ÔÏÇÏ, ÞÔÏÂÙ ÒÁ×ÎÏÍÅÒÎÏ ÒÁÓÐÒÅÄÅÌÑÔØÓÑ ÍÅÖÄÕ ÏÓÔÁÌØÎÙÍÉ.
+</para>
+<para lang="en">
+if nginx distributed the requests among several backends and some backend
+failed, then requests intended for this backend was directed to one live
+backend only instead of being distributed among the rest.
+</para>
+</change>
+
+</changes>
+
+
 <changes ver="0.3.44" date="04.05.2006">
 
 <change type="feature">
index 7fd9d72864fad83ff71709ef413feb23b17b55a5..e49b91c91d6b814fd9d93eb17703e0e893c606f8 100644 (file)
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.3.44"
+#define NGINX_VER          "nginx/0.3.45"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_OLDPID_EXT     ".oldbin"
index e4ca23840e5dc028884a0b7e96e433db51ec8223..157c48002abd33f36948aec839387795e788b731 100644 (file)
@@ -61,54 +61,75 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
 
             /* it's a first try - get a current peer */
 
-            pc->cur_peer = pc->peers->current;
+            for ( ;; ) {
+                pc->cur_peer = pc->peers->current;
 
-            pc->peers->weight--;
+                peer = &pc->peers->peer[pc->cur_peer];
+
+                if (peer->max_fails == 0 || peer->fails <= peer->max_fails) {
+                    break;
+                }
+
+                if (now - peer->accessed > peer->fail_timeout) {
+                    peer->fails = 0;
+                    break;
+                }
 
-            if (pc->peers->weight == 0) {
                 pc->peers->current++;
-            }
 
-            if (pc->peers->current >= pc->peers->number) {
-                pc->peers->current = 0;
-            }
+                if (pc->peers->current >= pc->peers->number) {
+                    pc->peers->current = 0;
+                }
 
-            if (pc->peers->weight == 0) {
                 pc->peers->weight = pc->peers->peer[pc->peers->current].weight;
-            }
-        }
 
-        for ( ;; ) {
-            peer = &pc->peers->peer[pc->cur_peer];
+                pc->tries--;
 
-            if (peer->max_fails == 0 || peer->fails <= peer->max_fails) {
-                break;
-            }
+                if (pc->tries) {
+                    continue;
+                }
 
-            if (now - peer->accessed > peer->fail_timeout) {
-                peer->fails = 0;
-                break;
+                goto failed;
             }
 
-            pc->cur_peer++;
+            pc->peers->weight--;
 
-            if (pc->cur_peer >= pc->peers->number) {
-                pc->cur_peer = 0;
+            if (pc->peers->weight == 0) {
+                pc->peers->current++;
+
+                if (pc->peers->current >= pc->peers->number) {
+                    pc->peers->current = 0;
+                }
+
+                pc->peers->weight = pc->peers->peer[pc->peers->current].weight;
             }
 
-            pc->tries--;
+        } else {
+            for ( ;; ) {
+                peer = &pc->peers->peer[pc->cur_peer];
 
-            if (pc->tries == 0) {
+                if (peer->max_fails == 0 || peer->fails <= peer->max_fails) {
+                    break;
+                }
+
+                if (now - peer->accessed > peer->fail_timeout) {
+                    peer->fails = 0;
+                    break;
+                }
 
-                /* all peers failed, mark them as live for quick recovery */
+                pc->cur_peer++;
 
-                for (i = 0; i < pc->peers->number; i++) {
-                    pc->peers->peer[i].fails = 0;
+                if (pc->cur_peer >= pc->peers->number) {
+                    pc->cur_peer = 0;
                 }
 
-                /* ngx_unlock_mutex(pc->peers->mutex); */
+                pc->tries--;
+
+                if (pc->tries) {
+                    continue;
+                }
 
-                return NGX_BUSY;
+                goto failed;
             }
         }
     }
@@ -319,6 +340,18 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
     wev->ready = 1;
 
     return NGX_OK;
+
+failed:
+
+    /* all peers failed, mark them as live for quick recovery */
+
+    for (i = 0; i < pc->peers->number; i++) {
+        pc->peers->peer[i].fails = 0;
+    }
+
+    /* ngx_unlock_mutex(pc->peers->mutex); */
+
+    return NGX_BUSY;
 }
 
 
index 3a7835ef678b3f6bd1a0c2cf2e5e2027baf79f4d..0b217cffdff933f6a4c27623f4e92153bc1c8cf4 100644 (file)
@@ -164,7 +164,8 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
     }
 
     if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
-                                    SSL_FILETYPE_PEM) == 0)
+                                    SSL_FILETYPE_PEM)
+        == 0)
     {
         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                       "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
@@ -175,6 +176,26 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
 }
 
 
+ngx_int_t
+ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert)
+{
+    if (ngx_conf_full_name(cf->cycle, cert) == NGX_ERROR) {
+        return NGX_ERROR;
+    }
+
+    if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
+        == 0)
+    {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "SSL_CTX_load_verify_locations(\"%s\") failed",
+                      cert->data);
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
 ngx_int_t
 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
 {
@@ -1023,6 +1044,88 @@ ngx_ssl_get_cipher_name(ngx_connection_t *c)
 }
 
 
+ngx_int_t
+ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+    char       *p;
+    size_t      len;
+    X509       *cert;
+    X509_NAME  *name;
+
+    s->len = 0;
+
+    cert = SSL_get_peer_certificate(c->ssl->connection);
+
+    if (cert == NULL) {
+        return NGX_OK;
+    }
+
+    name = X509_get_subject_name(cert);
+
+    if (name == NULL) {
+        return NGX_ERROR;
+    }
+
+    p = X509_NAME_oneline(name, NULL, 0);
+
+    for (len = 0; p[len]; len++) { /* void */ }
+
+    s->len = len;
+    s->data = ngx_palloc(pool, len);
+    if (s->data == NULL) {
+        OPENSSL_free(p);
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(s->data, p, len);
+
+    OPENSSL_free(p);
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+    char       *p;
+    size_t      len;
+    X509       *cert;
+    X509_NAME  *name;
+
+    s->len = 0;
+
+    cert = SSL_get_peer_certificate(c->ssl->connection);
+
+    if (cert == NULL) {
+        return NGX_OK;
+    }
+
+    name = X509_get_issuer_name(cert);
+
+    if (name == NULL) {
+        return NGX_ERROR;
+    }
+
+    p = X509_NAME_oneline(name, NULL, 0);
+
+    for (len = 0; p[len]; len++) { /* void */ }
+
+    s->len = len;
+    s->data = ngx_palloc(pool, len);
+    if (s->data == NULL) {
+        OPENSSL_free(p);
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(s->data, p, len);
+
+    OPENSSL_free(p);
+
+    return NGX_OK;
+}
+
+
 static void *
 ngx_openssl_create_conf(ngx_cycle_t *cycle)
 {
index 82bfa139f66ce7bd6faa127c2ae7cb450b81c2c5..4af42190b78b890a79347e9720b8fa079f10378a 100644 (file)
@@ -31,6 +31,7 @@ typedef struct {
 
 typedef struct {
     SSL                        *connection;
+
     ngx_int_t                   last;
     ngx_buf_t                  *buf;
 
@@ -60,10 +61,15 @@ typedef struct {
 #define NGX_SSL_BUFSIZE  16384
 
 
+#define NGX_SSL_VERIFY   SSL_VERIFY_PEER
+
+
 ngx_int_t ngx_ssl_init(ngx_log_t *log);
 ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols);
 ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_str_t *cert, ngx_str_t *key);
+ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
+    ngx_str_t *cert);
 ngx_int_t ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl);
 ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
     ngx_uint_t flags);
@@ -75,6 +81,11 @@ ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session);
 
 u_char *ngx_ssl_get_protocol(ngx_connection_t *c);
 u_char *ngx_ssl_get_cipher_name(ngx_connection_t *c);
+ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool,
+    ngx_str_t *s);
+ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool,
+    ngx_str_t *s);
+
 
 
 ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
index e2191ef47a1f223b7d425646f8dcaa188d994659..a57fbfb6f9d6ea12517cdcfd890144bb022699af 100644 (file)
@@ -19,6 +19,10 @@ typedef u_char *(*ngx_ssl_variable_handler_pt)(ngx_connection_t *);
 
 static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_ssl_client_s_dn(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_ssl_client_i_dn(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 
 static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
 static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
@@ -43,7 +47,6 @@ static ngx_conf_bitmask_t  ngx_http_ssl_protocols[] = {
 };
 
 
-
 static ngx_command_t  ngx_http_ssl_commands[] = {
 
     { ngx_string("ssl"),
@@ -81,6 +84,27 @@ static ngx_command_t  ngx_http_ssl_commands[] = {
       offsetof(ngx_http_ssl_srv_conf_t, ciphers),
       NULL },
 
+    { ngx_string("ssl_verify_client"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_ssl_srv_conf_t, verify),
+      NULL },
+
+    { ngx_string("ssl_verify_depth"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
+      NULL },
+
+    { ngx_string("ssl_client_certificate"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
+      NULL },
+
     { ngx_string("ssl_prefer_server_ciphers"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
@@ -142,6 +166,12 @@ static ngx_http_variable_t  ngx_http_ssl_vars[] = {
     { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_variable,
       (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGABLE, 0 },
 
+    { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_client_s_dn,
+      0, NGX_HTTP_VAR_CHANGABLE, 0 },
+
+    { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_client_i_dn,
+      0, NGX_HTTP_VAR_CHANGABLE, 0 },
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -179,6 +209,58 @@ ngx_http_ssl_variable(ngx_http_request_t *r,
 }
 
 
+static ngx_int_t
+ngx_http_ssl_client_s_dn(ngx_http_request_t *r, ngx_http_variable_value_t *v,
+    uintptr_t data)
+{
+    if (r->connection->ssl) {
+        if (ngx_ssl_get_subject_dn(r->connection, r->pool, (ngx_str_t *) v)
+            != NGX_OK)
+        {
+            return NGX_ERROR;
+        }
+
+        if (v->len) {
+            v->valid = 1;
+            v->no_cachable = 0;
+            v->not_found = 0;
+
+            return NGX_OK;
+        }
+    }
+
+    v->not_found = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssl_client_i_dn(ngx_http_request_t *r, ngx_http_variable_value_t *v,
+    uintptr_t data)
+{
+    if (r->connection->ssl) {
+        if (ngx_ssl_get_issuer_dn(r->connection, r->pool, (ngx_str_t *) v)
+            != NGX_OK)
+        {
+            return NGX_ERROR;
+        }
+
+        if (v->len) {
+            v->valid = 1;
+            v->no_cachable = 0;
+            v->not_found = 0;
+
+            return NGX_OK;
+        }
+    }
+
+    v->not_found = 1;
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_http_ssl_add_variables(ngx_conf_t *cf)
 {
@@ -217,12 +299,16 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
      *     scf->certificate.data = NULL;
      *     scf->certificate_key.len = 0;
      *     scf->certificate_key.data = NULL;
+     *     scf->client_certificate.len = 0;
+     *     scf->client_certificate.data = NULL;
      *     scf->ciphers.len = 0;
      *     scf->ciphers.data = NULL;
      */
 
     scf->enable = NGX_CONF_UNSET;
     scf->session_timeout = NGX_CONF_UNSET;
+    scf->verify = NGX_CONF_UNSET;
+    scf->verify_depth = NGX_CONF_UNSET;
     scf->prefer_server_ciphers = NGX_CONF_UNSET;
 
     return scf;
@@ -253,12 +339,18 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
                          (NGX_CONF_BITMASK_SET
                           |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
 
+    ngx_conf_merge_value(conf->verify, prev->verify, 0);
+    ngx_conf_merge_value(conf->verify_depth, prev->verify_depth, 1);
+
     ngx_conf_merge_str_value(conf->certificate, prev->certificate,
                          NGX_DEFLAUT_CERTIFICATE);
 
     ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key,
                          NGX_DEFLAUT_CERTIFICATE_KEY);
 
+    ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
+                         "");
+
     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS);
 
 
@@ -291,6 +383,21 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
                       &conf->ciphers);
     }
 
+    if (conf->verify) {
+        SSL_CTX_set_verify(conf->ssl.ctx, NGX_SSL_VERIFY, NULL);
+
+        SSL_CTX_set_verify_depth(conf->ssl.ctx, conf->verify_depth);
+
+        if (conf->client_certificate.len) {
+            if (ngx_ssl_client_certificate(cf, &conf->ssl,
+                                           &conf->client_certificate)
+                != NGX_OK)
+            {
+                return NGX_CONF_ERROR;
+            }
+        }
+    }
+
 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
 
     if (conf->prefer_server_ciphers) {
index 4207cdfdb02432eeeccfc430e9b9964be30a9be7..85803096e3049011f7ec327cdadb9c4f5aeb01a6 100644 (file)
@@ -22,10 +22,14 @@ typedef struct {
 
     ngx_uint_t      protocols;
 
+    ngx_int_t       verify;
+    ngx_int_t       verify_depth;
+
     time_t          session_timeout;
 
     ngx_str_t       certificate;
     ngx_str_t       certificate_key;
+    ngx_str_t       client_certificate;
 
     ngx_str_t       ciphers;
 } ngx_http_ssl_srv_conf_t;
index 680b3bd4571b8a87903f74c7e710246acab1beea..5207fa1cca65ebbab512b191e8367b2818c57bb3 100644 (file)
@@ -1172,8 +1172,12 @@ ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
 static ngx_int_t
 ngx_http_process_request_header(ngx_http_request_t *r)
 {
-    size_t   len;
-    u_char  *ua, *user_agent, ch;
+    size_t                    len;
+    u_char                   *ua, *user_agent, ch;
+#if (NGX_HTTP_SSL)
+    long                      rc;
+    ngx_http_ssl_srv_conf_t  *sscf;
+#endif
 
     if (r->headers_in.host) {
         for (len = 0; len < r->headers_in.host->value.len; len++) {
@@ -1243,6 +1247,34 @@ ngx_http_process_request_header(ngx_http_request_t *r)
         return NGX_ERROR;
     }
 
+#if (NGX_HTTP_SSL)
+
+    if (r->connection->ssl) {
+        sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
+
+        if (sscf->verify) {
+            rc = SSL_get_verify_result(r->connection->ssl->connection);
+
+            if (rc != X509_V_OK) {
+                ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+                              "client SSL certificate verify error: %l ", rc);
+                ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
+                return NGX_ERROR;
+            }
+
+            if (SSL_get_peer_certificate(r->connection->ssl->connection)
+                == NULL)
+            {
+                ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+                              "client sent no required SSL certificate");
+                ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
+                return NGX_ERROR;
+            }
+        }
+    }
+
+#endif
+
     if (r->headers_in.connection) {
         if (r->headers_in.connection->value.len == 5
             && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
index cc40f449ac2300b3ab79545ffb0c650c1bcaf51f..e467dde177fdf3c317d5992e614408a4d8e63a33 100644 (file)
 /* The special code to close connection without any response */
 #define NGX_HTTP_CLOSE                     444
 
-#define NGX_HTTP_OWN_CODES                 NGX_HTTP_TO_HTTPS
+#define NGX_HTTP_OWN_CODES                 495
+
+#define NGX_HTTPS_CERT_ERROR               495
+#define NGX_HTTPS_NO_CERT                  496
 
 /*
  * We use the special code for the plain HTTP requests that are sent to
index d1072a9aff953b645dc6fd3888cf72b59ca71759..734ad694792080cc70b53118f88d6ce393eebcca 100644 (file)
@@ -163,6 +163,26 @@ static char error_416_page[] =
 ;
 
 
+static char error_495_page[] =
+"<html>" CRLF
+"<head><title>400 The SSL certificate error</title></head>"
+CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>400 Bad Request</h1></center>" CRLF
+"<center>The SSL certificate error</center>" CRLF
+;
+
+
+static char error_496_page[] =
+"<html>" CRLF
+"<head><title>400 No required SSL certificate was sent</title></head>"
+CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>400 Bad Request</h1></center>" CRLF
+"<center>No required SSL certificate was sent</center>" CRLF
+;
+
+
 static char error_497_page[] =
 "<html>" CRLF
 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>"
@@ -254,6 +274,8 @@ static ngx_str_t error_pages[] = {
 
 #define NGX_HTTP_LEVEL_400  17
 
+    ngx_string(error_495_page),  /* 495, https certificate error */
+    ngx_string(error_496_page),  /* 496, https no certificate */
     ngx_string(error_497_page),  /* 497, http to https */
     ngx_string(error_404_page),  /* 498, invalid host name */
     ngx_null_string,             /* 499, client had closed connection */
@@ -296,6 +318,8 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
             case NGX_HTTP_REQUEST_ENTITY_TOO_LARGE:
             case NGX_HTTP_REQUEST_URI_TOO_LARGE:
             case NGX_HTTP_TO_HTTPS:
+            case NGX_HTTPS_CERT_ERROR:
+            case NGX_HTTPS_NO_CERT:
             case NGX_HTTP_INTERNAL_SERVER_ERROR:
                 r->keepalive = 0;
         }
@@ -305,6 +329,8 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
         switch (error) {
             case NGX_HTTP_BAD_REQUEST:
             case NGX_HTTP_TO_HTTPS:
+            case NGX_HTTPS_CERT_ERROR:
+            case NGX_HTTPS_NO_CERT:
                 r->lingering_close = 0;
         }
     }
@@ -372,6 +398,8 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
                                          + NGX_HTTP_LEVEL_400;
         switch (error) {
             case NGX_HTTP_TO_HTTPS:
+            case NGX_HTTPS_CERT_ERROR:
+            case NGX_HTTPS_NO_CERT:
                 r->headers_out.status = NGX_HTTP_BAD_REQUEST;
                 error = NGX_HTTP_BAD_REQUEST;
                 break;
index 0f162a70e122205fbf83708058abd7bd3857f11f..83f2adc0b5487058c4251bc76b5043d26898eb09 100644 (file)
@@ -810,19 +810,12 @@ static ngx_int_t
 ngx_http_variable_request_method(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    if (r->method_name.data) {
-        if (r->upstream && r->upstream->method.len) {
-            v->len = r->upstream->method.len;
-            v->data = r->upstream->method.data;
-
-        } else {
-            v->len = r->method_name.len;
-            v->data = r->method_name.data;
-        }
-
+    if (r->main->method_name.data) {
+        v->len = r->main->method_name.len;
         v->valid = 1;
         v->no_cachable = 0;
         v->not_found = 0;
+        v->data = r->main->method_name.data;
 
     } else {
         v->not_found = 1;