summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2006-08-09 19:56:52 +0000
committerJonathan Kolb <jon@b0g.us>2006-08-09 19:56:52 +0000
commiteda133b7908937a859040c84e8704afd309206ee (patch)
treeec50ae060054101cd07f5fb227e7a29f3f3e8df3
parent90f18dca0931d69c64bd77be57c702de64991e24 (diff)
downloadnginx-eda133b7908937a859040c84e8704afd309206ee.tar.gz
Changes with nginx 0.3.57 09 Aug 2006v0.3.57
*) Feature: the $ssl_client_serial variable. *) Bugfix: in the "!-e" operator of the "if" directive. Thanks to Andrian Budanstov. *) Bugfix: while a client certificate verification nginx did not send to a client the required certificates information. *) Bugfix: the $document_root variable did not support the variables in the "root" directive.
-rw-r--r--CHANGES14
-rw-r--r--CHANGES.ru14
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/event/ngx_event_openssl.c149
-rw-r--r--src/event/ngx_event_openssl.h28
-rw-r--r--src/http/modules/ngx_http_ssl_module.c93
-rw-r--r--src/http/ngx_http_core_module.c2
-rw-r--r--src/http/ngx_http_request.c2
-rw-r--r--src/http/ngx_http_script.c3
-rw-r--r--src/http/ngx_http_upstream.c42
-rw-r--r--src/http/ngx_http_variables.c33
11 files changed, 268 insertions, 114 deletions
diff --git a/CHANGES b/CHANGES
index 462d8ee5e..6303da0d0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,18 @@
+Changes with nginx 0.3.57 09 Aug 2006
+
+ *) Feature: the $ssl_client_serial variable.
+
+ *) Bugfix: in the "!-e" operator of the "if" directive.
+ Thanks to Andrian Budanstov.
+
+ *) Bugfix: while a client certificate verification nginx did not send
+ to a client the required certificates information.
+
+ *) Bugfix: the $document_root variable did not support the variables in
+ the "root" directive.
+
+
Changes with nginx 0.3.56 04 Aug 2006
*) Feature: the "dav_access" directive.
diff --git a/CHANGES.ru b/CHANGES.ru
index 7ce2a25d7..d534a7227 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,18 @@
+Изменения в nginx 0.3.57 09.08.2006
+
+ *) Добавление: переменная $ssl_client_serial.
+
+ *) Исправление: в операторе "!-e" в директиве if.
+ Спасибо Андриану Буданцову.
+
+ *) Исправление: при проверке клиентского сертификата nginx не передавал
+ клиенту информацию о требуемых сертификатах.
+
+ *) Исправление: переменная $document_root не поддерживала переменные в
+ директиве root.
+
+
Изменения в nginx 0.3.56 04.08.2006
*) Добавление: директива dav_access.
diff --git a/src/core/nginx.h b/src/core/nginx.h
index c85e2a73a..051bd68f3 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.56"
+#define NGINX_VER "nginx/0.3.57"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 0b217cffd..3573dc850 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -14,6 +14,7 @@ typedef struct {
} ngx_openssl_conf_t;
+static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
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);
@@ -83,6 +84,9 @@ static long ngx_ssl_protocols[] = {
};
+int ngx_connection_index;
+
+
ngx_int_t
ngx_ssl_init(ngx_log_t *log)
{
@@ -93,6 +97,13 @@ ngx_ssl_init(ngx_log_t *log)
ENGINE_load_builtin_engines();
#endif
+ ngx_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+
+ if (ngx_connection_index == -1) {
+ ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
+ return NGX_ERROR;
+ }
+
return NGX_OK;
}
@@ -177,8 +188,19 @@ 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)
+ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
+ ngx_int_t depth)
{
+ STACK_OF(X509_NAME) *list;
+
+ SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
+
+ SSL_CTX_set_verify_depth(ssl->ctx, depth);
+
+ if (cert->len == 0) {
+ return NGX_OK;
+ }
+
if (ngx_conf_full_name(cf->cycle, cert) == NGX_ERROR) {
return NGX_ERROR;
}
@@ -192,21 +214,77 @@ ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert)
return NGX_ERROR;
}
+ list = SSL_load_client_CA_file((char *) cert->data);
+
+ if (list == NULL) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "SSL_load_client_CA_file(\"%s\") failed", cert->data);
+ return NGX_ERROR;
+ }
+
+ /*
+ * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
+ * always leaved an error in the error queue
+ */
+
+ ERR_clear_error();
+
+ SSL_CTX_set_client_CA_list(ssl->ctx, list);
+
return NGX_OK;
}
+static int
+ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
+{
+ char *subject, *issuer;
+ int err, depth;
+ X509 *cert;
+ X509_NAME *name;
+ ngx_connection_t *c;
+ ngx_ssl_conn_t *ssl_conn;
+
+ ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
+ SSL_get_ex_data_X509_STORE_CTX_idx());
+
+ c = ngx_ssl_get_connection(ssl_conn);
+
+ cert = X509_STORE_CTX_get_current_cert(x509_store);
+ err = X509_STORE_CTX_get_error(x509_store);
+ depth = X509_STORE_CTX_get_error_depth(x509_store);
+
+ name = X509_get_subject_name(cert);
+ subject = name ? X509_NAME_oneline(name, NULL, 0) : "(none)";
+
+ name = X509_get_issuer_name(cert);
+ issuer = name ? X509_NAME_oneline(name, NULL, 0) : "(none)";
+
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "verify:%d, error:%d, depth:%d, "
+ "subject:\"%s\",issuer: \"%s\"",
+ ok, err, depth, subject, issuer);
+
+ return 1;
+}
+
+
ngx_int_t
ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
{
+ RSA *key;
+
if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) {
return NGX_OK;
}
- ssl->rsa512_key = RSA_generate_key(512, RSA_F4, NULL, NULL);
+ key = RSA_generate_key(512, RSA_F4, NULL, NULL);
+
+ if (key) {
+ SSL_CTX_set_tmp_rsa(ssl->ctx, key);
+
+ RSA_free(key);
- if (ssl->rsa512_key) {
- SSL_CTX_set_tmp_rsa(ssl->ctx, ssl->rsa512_key);
return NGX_OK;
}
@@ -254,6 +332,11 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
SSL_set_accept_state(sc->connection);
}
+ if (SSL_set_ex_data(sc->connection, ngx_connection_index, c) == 0) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
+ return NGX_ERROR;
+ }
+
c->ssl = sc;
return NGX_OK;
@@ -1022,25 +1105,23 @@ ngx_ssl_cleanup_ctx(void *data)
{
ngx_ssl_t *ssl = data;
- if (ssl->rsa512_key) {
- RSA_free(ssl->rsa512_key);
- }
-
SSL_CTX_free(ssl->ctx);
}
-u_char *
-ngx_ssl_get_protocol(ngx_connection_t *c)
+ngx_int_t
+ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
- return (u_char *) SSL_get_version(c->ssl->connection);
+ s->data = (u_char *) SSL_get_version(c->ssl->connection);
+ return NGX_OK;
}
-u_char *
-ngx_ssl_get_cipher_name(ngx_connection_t *c)
+ngx_int_t
+ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
- return (u_char *) SSL_get_cipher_name(c->ssl->connection);
+ s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
+ return NGX_OK;
}
@@ -1055,13 +1136,11 @@ ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
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;
}
@@ -1096,13 +1175,11 @@ ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
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;
}
@@ -1126,6 +1203,42 @@ ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
}
+ngx_int_t
+ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ size_t len;
+ X509 *cert;
+ BIO *bio;
+
+ s->len = 0;
+
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+ if (cert == NULL) {
+ return NGX_OK;
+ }
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ return NGX_ERROR;
+ }
+
+ i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
+ len = BIO_pending(bio);
+
+ s->len = len;
+ s->data = ngx_palloc(pool, len);
+ if (s->data == NULL) {
+ BIO_free(bio);
+ return NGX_ERROR;
+ }
+
+ BIO_read(bio, s->data, len);
+ BIO_free(bio);
+
+ 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 4af42190b..9777fe3d9 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -22,15 +22,18 @@
#define NGX_SSL_NAME "OpenSSL"
+#define ngx_ssl_session_t SSL_SESSION
+#define ngx_ssl_conn_t SSL
+
+
typedef struct {
SSL_CTX *ctx;
- RSA *rsa512_key;
ngx_log_t *log;
} ngx_ssl_t;
typedef struct {
- SSL *connection;
+ ngx_ssl_conn_t *connection;
ngx_int_t last;
ngx_buf_t *buf;
@@ -47,9 +50,6 @@ typedef struct {
} ngx_ssl_connection_t;
-#define ngx_ssl_session_t SSL_SESSION
-
-
#define NGX_SSL_SSLv2 2
#define NGX_SSL_SSLv3 4
#define NGX_SSL_TLSv1 8
@@ -61,15 +61,12 @@ 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_str_t *cert, ngx_int_t depth);
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);
@@ -77,14 +74,20 @@ ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session);
#define ngx_ssl_get_session(c) SSL_get1_session(c->ssl->connection)
#define ngx_ssl_free_session SSL_SESSION_free
+#define ngx_ssl_get_connection(sc) SSL_get_ex_data(sc, ngx_connection_index)
-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_protocol(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
+ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
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_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
+
@@ -100,4 +103,7 @@ void ngx_cdecl ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
void ngx_ssl_cleanup_ctx(void *data);
+extern int ngx_connection_index;
+
+
#endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index 344f61361..30c2d11de 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -9,7 +9,8 @@
#include <ngx_http.h>
-typedef u_char *(*ngx_ssl_variable_handler_pt)(ngx_connection_t *);
+typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
+ ngx_pool_t *pool, ngx_str_t *s);
#define NGX_DEFLAUT_CERTIFICATE "cert.pem"
@@ -17,12 +18,9 @@ typedef u_char *(*ngx_ssl_variable_handler_pt)(ngx_connection_t *);
#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
-static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
-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,
+static ngx_int_t ngx_http_ssl_static_variable(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,
+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_add_variables(ngx_conf_t *cf);
@@ -161,17 +159,20 @@ ngx_module_t ngx_http_ssl_module = {
static ngx_http_variable_t ngx_http_ssl_vars[] = {
- { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_variable,
+ { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
(uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGABLE, 0 },
- { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_variable,
+ { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_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_s_dn"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_subject_dn, 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_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGABLE, 0 },
+
+ { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGABLE, 0 },
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -181,25 +182,23 @@ static u_char ngx_http_session_id_ctx[] = "HTTP";
static ngx_int_t
-ngx_http_ssl_variable(ngx_http_request_t *r,
+ngx_http_ssl_static_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
- ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
+ ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
- size_t len;
- u_char *name;
+ size_t len;
if (r->connection->ssl) {
- name = handler(r->connection);
+ (void) handler(r->connection, NULL, (ngx_str_t *) v);
- for (len = 0; name[len]; len++) { /* void */ }
+ for (len = 0; v->data[len]; len++) { /* void */ }
v->len = len;
v->valid = 1;
v->no_cachable = 0;
v->not_found = 0;
- v->data = name;
return NGX_OK;
}
@@ -211,39 +210,13 @@ 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,
+ngx_http_ssl_variable(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;
- }
- }
+ ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
- 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)
- {
+ if (handler(r->connection, r->pool, (ngx_str_t *) v) != NGX_OK) {
return NGX_ERROR;
}
@@ -385,18 +358,11 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
}
if (conf->verify) {
- SSL_CTX_set_verify(conf->ssl.ctx, NGX_SSL_VERIFY,
- ngx_http_ssl_verify_callback);
-
- 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;
- }
+ if (ngx_ssl_client_certificate(cf, &conf->ssl,
+ &conf->client_certificate, conf->verify_depth)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
}
}
@@ -424,13 +390,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
}
-static int
-ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
-{
- return 1;
-}
-
-
#if !defined (SSL_OP_CIPHER_SERVER_PREFERENCE)
static char *
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index eb4934e8e..9d33d3af6 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1072,7 +1072,7 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
} else {
if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
- clcf->root_values->elts)
+ clcf->root_values->elts)
== NULL)
{
return NULL;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 42933e8d2..417f3dfa7 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1344,7 +1344,7 @@ ngx_http_process_request_header(ngx_http_request_t *r)
if (rc != X509_V_OK) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client SSL certificate verify error: (%l:%s) ",
+ "client SSL certificate verify error: (%l:%s)",
rc, X509_verify_cert_error_string(rc));
ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
return NGX_ERROR;
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 947bce6d8..1918397fb 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -960,13 +960,16 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e)
}
switch (code->op) {
+
case ngx_http_script_file_plain:
case ngx_http_script_file_dir:
case ngx_http_script_file_exists:
case ngx_http_script_file_exec:
goto false;
+
case ngx_http_script_file_not_plain:
case ngx_http_script_file_not_dir:
+ case ngx_http_script_file_not_exists:
case ngx_http_script_file_not_exec:
goto true;
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 8ca24e2b1..5e22f2d83 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -769,7 +769,8 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
static void
ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
- int rc;
+ int rc, err;
+ socklen_t len;
ngx_connection_t *c;
c = u->peer.connection;
@@ -777,19 +778,42 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream send request");
+ if (!u->request_sent) {
+
#if (NGX_HAVE_KQUEUE)
- if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT)
- && !u->request_sent
- && c->write->pending_eof)
- {
- (void) ngx_connection_error(c, c->write->kq_errno,
+ if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
+ if (c->write->pending_eof) {
+ (void) ngx_connection_error(c, c->write->kq_errno,
"kevent() reported that connect() failed");
- ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
- return;
- }
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+ return;
+ }
+ } else
#endif
+ {
+ err = 0;
+ len = sizeof(int);
+
+ /*
+ * BSDs and Linux return 0 and set a pending error in err
+ * Solaris returns -1 and sets errno
+ */
+
+ if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
+ == -1)
+ {
+ err = ngx_errno;
+ }
+
+ if (err) {
+ (void) ngx_connection_error(c, err, "connect() failed");
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+ return;
+ }
+ }
+ }
c->log->action = "sending request to upstream";
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index f151f8789..d5fbfc9b7 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -137,7 +137,7 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
offsetof(ngx_http_request_t, request_line), 0, 0 },
{ ngx_string("document_root"), NULL,
- ngx_http_variable_document_root, 0, 0, 0 },
+ ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHABLE, 0 },
{ ngx_string("query_string"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, args),
@@ -775,15 +775,36 @@ static ngx_int_t
ngx_http_variable_document_root(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
+ ngx_str_t path;
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- v->len = clcf->root.len;
- v->valid = 1;
- v->no_cachable = 0;
- v->not_found = 0;
- v->data = clcf->root.data;
+ if (clcf->root_lengths == NULL) {
+ v->len = clcf->root.len;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = clcf->root.data;
+
+ } else {
+ if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
+ clcf->root_values->elts)
+ == NULL)
+ {
+ return NGX_ERROR;
+ }
+
+ if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ v->len = path.len;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = path.data;
+ }
return NGX_OK;
}