# HG changeset patch # User Igor Sysoev # Date 1155067200 -14400 # Node ID 559bc7ec214e45cfcadb200932b3ae2c18b7d991 # Parent 8045828c37063e8cf84e93c08a61ab89333deea1 nginx 0.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. diff --git a/CHANGES b/CHANGES --- 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 --- 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 --- 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 --- 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_ 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 *c 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 (ssl->rsa512_key) { - SSL_CTX_set_tmp_rsa(ssl->ctx, ssl->rsa512_key); + if (key) { + SSL_CTX_set_tmp_rsa(ssl->ctx, key); + + RSA_free(key); + return NGX_OK; } @@ -254,6 +332,11 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl 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 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 * 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 * } +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 --- 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_ 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 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 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -9,7 +9,8 @@ #include -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_handl #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, +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_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, +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[] 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 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; + ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; - 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) - { + 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 * } 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 * } -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 --- 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_reques } 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 --- 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 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 --- 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_scrip } 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 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -769,7 +769,8 @@ ngx_http_upstream_reinit(ngx_http_reques 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,20 +778,43 @@ ngx_http_upstream_send_request(ngx_http_ 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; + } + } } -#endif - c->log->action = "sending request to upstream"; rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs); diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- 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_cor 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; }