summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2006-05-06 16:28:56 +0000
committerIgor Sysoev <igor@sysoev.ru>2006-05-06 16:28:56 +0000
commit44d872259c6f1a3aab86d2fbbba4525f12b3d878 (patch)
treecc791866bbd92587d2d2c8b9ed2b8e66c15db4d3
parent9a27196bd4dd2ac6c6c86aa786ae0b0aad84e610 (diff)
downloadnginx-44d872259c6f1a3aab86d2fbbba4525f12b3d878.tar.gz
nginx-0.3.45-RELEASE importrelease-0.3.45
*) 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.
-rw-r--r--conf/koi-win8
-rw-r--r--docs/xml/nginx/changes.xml55
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/event/ngx_event_connect.c89
-rw-r--r--src/event/ngx_event_openssl.c105
-rw-r--r--src/event/ngx_event_openssl.h11
-rw-r--r--src/http/modules/ngx_http_ssl_module.c109
-rw-r--r--src/http/modules/ngx_http_ssl_module.h4
-rw-r--r--src/http/ngx_http_request.c36
-rw-r--r--src/http/ngx_http_request.h5
-rw-r--r--src/http/ngx_http_special_response.c28
-rw-r--r--src/http/ngx_http_variables.c13
12 files changed, 419 insertions, 46 deletions
diff --git a/conf/koi-win b/conf/koi-win
index 2b12b8da1..99edb1b2b 100644
--- a/conf/koi-win
+++ b/conf/koi-win
@@ -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
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 92fefa4db..7657a5cc5 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -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">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 7fd9d7286..e49b91c91 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -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"
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index e4ca23840..157c48002 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -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;
}
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 3a7835ef6..0b217cffd 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -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);
@@ -176,6 +177,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)
{
if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) {
@@ -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)
{
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index 82bfa139f..4af42190b 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -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);
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index e2191ef47..a57fbfb6f 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -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 }
};
@@ -180,6 +210,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)
{
ngx_http_variable_t *var, *v;
@@ -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) {
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index 4207cdfdb..85803096e 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -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;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 680b3bd45..5207fa1cc 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -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")
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index cc40f449a..e467dde17 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -75,7 +75,10 @@
/* 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
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index d1072a9af..734ad6947 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -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;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 0f162a70e..83f2adc0b 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -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;