diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-09-30 14:41:25 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-09-30 14:41:25 +0000 |
commit | 9fa5a823c467c8ba13f8edff3c7d3c6dc75ea1d4 (patch) | |
tree | 7db278ad5da26db878ba05453ac96404fa2df556 | |
parent | bdf4a89a20b9b2cb91c7c97941a2cb36534e2f9d (diff) | |
download | nginx-9fa5a823c467c8ba13f8edff3c7d3c6dc75ea1d4.tar.gz nginx-9fa5a823c467c8ba13f8edff3c7d3c6dc75ea1d4.zip |
nginx-0.2.2-RELEASE importrelease-0.2.2
*) Feature: the "config errmsg" command of the ngx_http_ssi_module.
*) Change: the ngx_http_geo_module variables can be overridden by the
"set" directive.
*) Feature: the "ssl_protocols" and "ssl_prefer_server_ciphers"
directives of the ngx_http_ssl_module and ngx_imap_ssl_module.
*) Bugfix: the ngx_http_autoindex_module did not show correctly the
long file names;
*) Bugfix: the ngx_http_autoindex_module now do not show the files
starting by dot.
*) Bugfix: if the SSL handshake failed then another connection may be
closed too.
Thanks to Rob Mueller.
*) Bugfix: the export versions of MSIE 5.x could not connect via HTTPS.
23 files changed, 753 insertions, 486 deletions
diff --git a/docs/dtd/changes.dtd b/docs/dtd/changes.dtd index 5b229d5eb..4dea2c7af 100644 --- a/docs/dtd/changes.dtd +++ b/docs/dtd/changes.dtd @@ -1,5 +1,6 @@ <!ENTITY nbsp " " > +<!ENTITY mdash " - " > <!ELEMENT change_log (changes)* > diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index a6acb66ab..73016a3ae 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -9,6 +9,80 @@ <title lang="en">nginx changelog</title> +<changes ver="0.2.2" date="30.09.2005"> + +<change type="feature"> +<para lang="ru"> +команда config errmsg в модуле ngx_http_ssi_module. +</para> +<para lang="en"> +the "config errmsg" command of the ngx_http_ssi_module. +</para> +</change> + +<change type="change"> +<para lang="ru"> +переменные модуля ngx_http_geo_module можно переопределять директивой set. +</para> +<para lang="en"> +the ngx_http_geo_module variables can be overridden by the "set" directive. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +директивы ssl_protocols и ssl_prefer_server_ciphers модулей +ngx_http_ssl_module и ngx_imap_ssl_module. +</para> +<para lang="en"> +the "ssl_protocols" and "ssl_prefer_server_ciphers" directives +of the ngx_http_ssl_module and ngx_imap_ssl_module. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +ошибка в модуле ngx_http_autoindex_module при показе длинных имён файлов; +</para> +<para lang="en"> +the ngx_http_autoindex_module did not show correctly the long file names; +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +модуль ngx_http_autoindex_module теперь не показывает файлы, +начинающиеся на точку. +</para> +<para lang="en"> +the ngx_http_autoindex_module now do not show the files starting by dot. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +если SSL handshake завершался с ошибкой, то это могло привести также +в закрытию другого соединения. +Спасибо Rob Mueller. +</para> +<para lang="en"> +if the SSL handshake failed then another connection may be closed too. +Thanks to Rob Mueller. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +экспортные версии MSIE 5.x не могли соединиться по HTTPS. +</para> +<para lang="en"> +the export versions of MSIE 5.x could not connect via HTTPS. +</para> +</change> + +</changes> + + <changes ver="0.2.1" date="23.09.2005"> <change type="bugfix"> @@ -38,8 +112,9 @@ bug appeared in 0.2.0. Новый основной процесс создаёт обычный pid-файл без суффикса ".newbin". Если новый основной процесс выходит, то старый процесс переименовывает свой pid-файл c суффиксом ".oldbin" в pid-файл без суффикса. -При обновлении с версии 0.1.х до 0.2.0 нужно учитывать, что старый процесс -0.1.x и новый процесс 0.2.0 оба используют pid-файл без суффиксов. +При обновлении с версии 0.1.х до 0.2.0 нужно учитывать, что оба +процесса—старый 0.1.x и новый 0.2.0—используют pid-файл +без суффиксов. </para> <para lang="en"> The pid-file names used during online upgrade was changed and now is not @@ -122,6 +197,7 @@ nginx did not try do connect to them during 60 seconds. </para> <para lang="en"> in IMAP/POP3 command argument parsing. +Thanks to Rob Mueller. </para> </change> diff --git a/src/core/nginx.h b/src/core/nginx.h index 6468b9479..d4c1cd680 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.2.1" +#define NGINX_VER "nginx/0.2.2" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index e13f2857f..e5df4372f 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -28,7 +28,7 @@ struct ngx_listening_s { int backlog; /* handler of accepted connection */ - void (*handler)(ngx_connection_t *c); + ngx_connection_handler_pt handler; void *ctx; /* ngx_http_conf_ctx_t, for example */ void *servers; /* array of ngx_http_in_addr_t, for example */ @@ -118,7 +118,7 @@ struct ngx_connection_s { ngx_str_t addr_text; #if (NGX_OPENSSL) - ngx_ssl_t *ssl; + ngx_ssl_connection_t *ssl; #endif #if (NGX_HAVE_IOCP) diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index 9646f6c06..a32733996 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -23,7 +23,7 @@ typedef struct ngx_peers_s ngx_peers_t; typedef struct ngx_connection_s ngx_connection_t; typedef void (*ngx_event_handler_pt)(ngx_event_t *ev); - +typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #define NGX_OK 0 diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index b7e072571..246047869 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -14,9 +14,12 @@ typedef struct { } ngx_openssl_conf_t; +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); static void ngx_ssl_read_handler(ngx_event_t *rev); +static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, + ngx_err_t err, char *text); static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf); @@ -63,7 +66,19 @@ ngx_module_t ngx_openssl_module = { NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING -}; +}; + + +static long ngx_ssl_protocols[] = { + SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1, + SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1, + SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1, + SSL_OP_NO_TLSv1, + SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3, + SSL_OP_NO_SSLv3, + SSL_OP_NO_SSLv2, + 0, +}; ngx_int_t @@ -81,118 +96,265 @@ ngx_ssl_init(ngx_log_t *log) ngx_int_t -ngx_ssl_create_connection(ngx_ssl_ctx_t *ssl_ctx, ngx_connection_t *c, - ngx_uint_t flags) +ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols) +{ + ssl->ctx = SSL_CTX_new(SSLv23_server_method()); + + if (ssl->ctx == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed"); + return NGX_ERROR; + } + + SSL_CTX_set_options(ssl->ctx, SSL_OP_ALL); + + if (ngx_ssl_protocols[protocols >> 1] != 0) { + SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); + } + + SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + SSL_CTX_set_read_ahead(ssl->ctx, 1); + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_certificate(ngx_ssl_t *ssl, u_char *cert, u_char *key) +{ + if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_certificate_chain_file(\"%s\") failed", + cert); + return NGX_ERROR; + } + + if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key, SSL_FILETYPE_PEM) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key); + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl) +{ + ssl->rsa512_key = RSA_generate_key(512, RSA_F4, NULL, NULL); + + if (ssl->rsa512_key) { + SSL_CTX_set_tmp_rsa(ssl->ctx, ssl->rsa512_key); + return NGX_OK; + } + + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed"); + + return NGX_ERROR; +} + + +ngx_int_t +ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags) { - ngx_ssl_t *ssl; + ngx_ssl_connection_t *sc; - ssl = ngx_pcalloc(c->pool, sizeof(ngx_ssl_t)); - if (ssl == NULL) { + sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t)); + if (sc == NULL) { return NGX_ERROR; } if (flags & NGX_SSL_BUFFER) { - ssl->buffer = 1; + sc->buffer = 1; - ssl->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE); - if (ssl->buf == NULL) { + sc->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE); + if (sc->buf == NULL) { return NGX_ERROR; } } - ssl->connection = SSL_new(ssl_ctx); + sc->connection = SSL_new(ssl->ctx); - if (ssl->connection == NULL) { + if (sc->connection == NULL) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed"); return NGX_ERROR; } - if (SSL_set_fd(ssl->connection, c->fd) == 0) { + if (SSL_set_fd(sc->connection, c->fd) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed"); return NGX_ERROR; } - SSL_set_accept_state(ssl->connection); + SSL_set_accept_state(sc->connection); - c->ssl = ssl; + c->ssl = sc; return NGX_OK; } -ssize_t -ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) +ngx_int_t +ngx_ssl_handshake(ngx_connection_t *c) { - int n, bytes; + int n, sslerr; + ngx_err_t err; - if (c->ssl->last == NGX_ERROR) { - return NGX_ERROR; + n = SSL_do_handshake(c->ssl->connection); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); + + if (n == 1) { + + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + return NGX_ERROR; + } + +#if (NGX_DEBUG) + { + char buf[129], *s, *d; + SSL_CIPHER *cipher; + + cipher = SSL_get_current_cipher(c->ssl->connection); + + if (cipher) { + SSL_CIPHER_description(cipher, &buf[1], 128); + + for (s = &buf[1], d = buf; *s; s++) { + if (*s == ' ' && *d == ' ') { + continue; + } + + if (*s == LF || *s == CR) { + continue; + } + + *++d = *s; + } + + if (*d != ' ') { + d++; + } + + *d = '\0'; + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL: %s, cipher: \"%s\"", + SSL_get_version(c->ssl->connection), &buf[1]); + + if (SSL_session_reused(c->ssl->connection)) { + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL reused session"); + } + + } else { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL no shared ciphers"); + } + } +#endif + + c->ssl->handshaked = 1; + + c->recv = ngx_ssl_recv; + c->send = ngx_ssl_write; + c->send_chain = ngx_ssl_send_chain; + + return NGX_OK; } - bytes = 0; + sslerr = SSL_get_error(c->ssl->connection, n); - /* - * SSL_read() may return data in parts, so try to read - * until SSL_read() would return no data - */ + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); - for ( ;; ) { + if (sslerr == SSL_ERROR_WANT_READ) { + c->read->ready = 0; + c->read->handler = ngx_ssl_handshake_handler; - n = SSL_read(c->ssl->connection, buf, size); + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_ERROR; + } - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); + return NGX_AGAIN; + } - if (n > 0) { + if (sslerr == SSL_ERROR_WANT_WRITE) { + c->write->ready = 0; + c->write->handler = ngx_ssl_handshake_handler; - bytes += n; + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + return NGX_ERROR; + } -#if (NGX_DEBUG) + return NGX_AGAIN; + } - if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->connection)) - { - char buf[129], *s, *d; - SSL_CIPHER *cipher; + err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; - c->ssl->handshaked = 1; + c->ssl->no_wait_shutdown = 1; + c->ssl->no_send_shutdown = 1; - cipher = SSL_get_current_cipher(c->ssl->connection); + if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { + ngx_log_error(NGX_LOG_INFO, c->log, err, + "client closed connection in SSL handshake"); - if (cipher) { - SSL_CIPHER_description(cipher, &buf[1], 128); + return NGX_ERROR; + } - for (s = &buf[1], d = buf; *s; s++) { - if (*s == ' ' && *d == ' ') { - continue; - } + ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed"); - if (*s == LF || *s == CR) { - continue; - } + return NGX_ERROR; +} - *++d = *s; - } - if (*d != ' ') { - d++; - } +static void +ngx_ssl_handshake_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; - *d = '\0'; + c = ev->data; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL cipher: \"%s\"", &buf[1]); + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "ssl handshake handler: %d", ev->write); - if (SSL_session_reused(c->ssl->connection)) { - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL reused session"); - } + if (ngx_ssl_handshake(c) == NGX_AGAIN) { + return; + } - } else { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL no shared ciphers"); - } - } -#endif + c->ssl->handler(c); +} + + +ssize_t +ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) +{ + int n, bytes; + + if (c->ssl->last == NGX_ERROR) { + return NGX_ERROR; + } + + bytes = 0; + /* + * SSL_read() may return data in parts, so try to read + * until SSL_read() would return no data + */ + + for ( ;; ) { + + n = SSL_read(c->ssl->connection, buf, size); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); + + if (n > 0) { + bytes += n; } c->ssl->last = ngx_ssl_handle_recv(c, n); @@ -221,10 +383,8 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n) { - int sslerr; - char *handshake; - ngx_err_t err; - ngx_uint_t level; + int sslerr; + ngx_err_t err; if (n > 0) { @@ -250,13 +410,6 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n) return NGX_OK; } - if (!SSL_is_init_finished(c->ssl->connection)) { - handshake = " in SSL handshake"; - - } else { - handshake = ""; - } - sslerr = SSL_get_error(c->ssl->connection, n); err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; @@ -270,9 +423,8 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n) if (sslerr == SSL_ERROR_WANT_WRITE) { - ngx_log_error(NGX_LOG_INFO, c->log, err, - "client does SSL %shandshake", - SSL_is_init_finished(c->ssl->connection) ? "re" : ""); + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client started SSL renegotiation"); c->write->ready = 0; @@ -292,44 +444,16 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n) return NGX_AGAIN; } - c->ssl->no_rcv_shut = 1; - c->ssl->no_send_shut = 1; + c->ssl->no_wait_shutdown = 1; + c->ssl->no_send_shutdown = 1; if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { - ngx_log_error(NGX_LOG_INFO, c->log, err, - "client closed connection%s", handshake); + ngx_log_error(NGX_LOG_INFO, c->log, err, "client closed connection"); return NGX_ERROR; } - level = NGX_LOG_CRIT; - - if (sslerr == SSL_ERROR_SYSCALL) { - - if (err == NGX_ECONNRESET - || err == NGX_EPIPE - || err == NGX_ENOTCONN - || err == NGX_ECONNREFUSED - || err == NGX_EHOSTUNREACH) - { - 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, "SSL_read() failed%s", handshake); + ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed"); return NGX_ERROR; } @@ -341,6 +465,7 @@ ngx_ssl_write_handler(ngx_event_t *wev) ngx_connection_t *c; c = wev->data; + c->read->handler(c->read); } @@ -482,9 +607,8 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) { - int n, sslerr; - ngx_err_t err; - ngx_uint_t level; + int n, sslerr; + ngx_err_t err; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size); @@ -494,52 +618,6 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) if (n > 0) { -#if (NGX_DEBUG) - - if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->connection)) { - char buf[129], *s, *d; - SSL_CIPHER *cipher; - - c->ssl->handshaked = 1; - - cipher = SSL_get_current_cipher(c->ssl->connection); - - if (cipher) { - SSL_CIPHER_description(cipher, &buf[1], 128); - - for (s = &buf[1], d = buf; *s; s++) { - if (*s == ' ' && *d == ' ') { - continue; - } - - if (*s == LF || *s == CR) { - continue; - } - - *++d = *s; - } - - if (*d != ' ') { - d++; - } - - *d = '\0'; - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL cipher: \"%s\"", &buf[1]); - - if (SSL_session_reused(c->ssl->connection)) { - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL reused session"); - } - - } else { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL no shared ciphers"); - } - } -#endif - if (c->ssl->saved_read_handler) { c->read->handler = c->ssl->saved_read_handler; @@ -575,9 +653,8 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) if (sslerr == SSL_ERROR_WANT_READ) { - ngx_log_error(NGX_LOG_INFO, c->log, err, - "client does SSL %shandshake", - SSL_is_init_finished(c->ssl->connection) ? "re" : ""); + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client started SSL renegotiation"); c->read->ready = 0; @@ -598,37 +675,10 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) return NGX_AGAIN; } - c->ssl->no_rcv_shut = 1; - c->ssl->no_send_shut = 1; - - level = NGX_LOG_CRIT; - - if (sslerr == SSL_ERROR_SYSCALL) { - - if (err == NGX_ECONNRESET - || err == NGX_EPIPE - || err == NGX_ENOTCONN - || err == NGX_ECONNREFUSED - || err == NGX_EHOSTUNREACH) - { - 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; - } - } - } + c->ssl->no_wait_shutdown = 1; + c->ssl->no_send_shutdown = 1; - ngx_ssl_error(level, c->log, err, "SSL_write() failed"); + ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed"); return NGX_ERROR; } @@ -640,6 +690,7 @@ ngx_ssl_read_handler(ngx_event_t *rev) ngx_connection_t *c; c = rev->data; + c->write->handler(c->write); } @@ -650,31 +701,23 @@ ngx_ssl_shutdown(ngx_connection_t *c) int n, sslerr, mode; ngx_uint_t again; - if (!c->ssl->shutdown_set) { - - /* it seems that SSL_set_shutdown() could be called once only */ - - if (c->read->timedout) { - mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; - - } else { - mode = 0; + if (c->read->timedout) { + mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; - if (c->ssl->no_rcv_shut) { - mode = SSL_RECEIVED_SHUTDOWN; - } + } else { + mode = SSL_get_shutdown(c->ssl->connection); - if (c->ssl->no_send_shut) { - mode |= SSL_SENT_SHUTDOWN; - } + if (c->ssl->no_wait_shutdown) { + mode |= SSL_RECEIVED_SHUTDOWN; } - if (mode) { - SSL_set_shutdown(c->ssl->connection, mode); - c->ssl->shutdown_set = 1; + if (c->ssl->no_send_shutdown) { + mode |= SSL_SENT_SHUTDOWN; } } + SSL_set_shutdown(c->ssl->connection, mode); + again = 0; #if (NGX_SUPPRESS_WARN) sslerr = 0; @@ -736,11 +779,49 @@ ngx_ssl_shutdown(ngx_connection_t *c) } +static void +ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, + char *text) +{ + ngx_uint_t level; + + level = NGX_LOG_CRIT; + + if (sslerr == SSL_ERROR_SYSCALL) { + + if (err == NGX_ECONNRESET + || err == NGX_EPIPE + || err == NGX_ENOTCONN + || err == NGX_ECONNREFUSED + || err == NGX_EHOSTUNREACH) + { + 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); +} + + void ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) { - u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last; + u_long n; va_list args; + u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last; last = errstr + NGX_MAX_CONF_ERRSTR; @@ -748,9 +829,18 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args); va_end(args); - p = ngx_cpystrn(p, (u_char *) " (SSL: ", last - p); + p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); + + while (p < last && (n = ERR_get_error())) { - ERR_error_string_n(ERR_get_error(), (char *) p, last - p); + *p++ = ' '; + + ERR_error_string_n(n, (char *) p, last - p); + + while (p < last && *p) { + p++; + } + } ngx_log_error(level, log, err, "%s)", errstr); } @@ -759,9 +849,10 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) void ngx_ssl_cleanup_ctx(void *data) { - SSL_CTX *ctx = data; + ngx_ssl_t *ssl = data; - SSL_CTX_free(ctx); + RSA_free(ssl->rsa512_key); + SSL_CTX_free(ssl->ctx); } diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index fa7f27e61..cd3898c73 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -16,44 +16,53 @@ #if OPENSSL_VERSION_NUMBER >= 0x00907000 #include <openssl/engine.h> -#define NGX_SSL_ENGINE 1 +#define NGX_SSL_ENGINE 1 #endif -#define NGX_SSL_NAME "OpenSSL" +#define NGX_SSL_NAME "OpenSSL" typedef struct { - SSL *connection; - ngx_int_t last; - ngx_buf_t *buf; - ngx_event_handler_pt saved_read_handler; - ngx_event_handler_pt saved_write_handler; - - unsigned buffer:1; - unsigned no_rcv_shut:1; - unsigned no_send_shut:1; - unsigned shutdown_set:1; - -#if (NGX_DEBUG) - unsigned handshaked:1; -#endif + SSL_CTX *ctx; + RSA *rsa512_key; + ngx_log_t *log; } ngx_ssl_t; -typedef SSL_CTX ngx_ssl_ctx_t; +typedef struct { + SSL *connection; + ngx_int_t last; + ngx_buf_t *buf; + ngx_connection_handler_pt handler; -#define NGX_SSL_BUFFER 1 + ngx_event_handler_pt saved_read_handler; + ngx_event_handler_pt saved_write_handler; -#define NGX_SSL_BUFSIZE 16384 + unsigned handshaked:1; + unsigned buffer:1; + unsigned no_wait_shutdown:1; + unsigned no_send_shutdown:1; +} ngx_ssl_connection_t; -ngx_int_t ngx_ssl_init(ngx_log_t *log); -ngx_int_t ngx_ssl_create_connection(ngx_ssl_ctx_t *ctx, ngx_connection_t *c, - ngx_uint_t flags); +#define NGX_SSL_SSLv2 2 +#define NGX_SSL_SSLv3 4 +#define NGX_SSL_TLSv1 8 + -#define ngx_ssl_handshake(c) NGX_OK +#define NGX_SSL_BUFFER 1 +#define NGX_SSL_BUFSIZE 16384 + + +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_ssl_t *ssl, u_char *cert, u_char *key); +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); +ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c index fb40669ba..d5a6b69ba 100644 --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -271,21 +271,14 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) len = ngx_de_namelen(&dir); - if (len == 1 && ngx_de_name(&dir)[0] == '.') { - continue; - } - - if (len == 2 - && ngx_de_name(&dir)[0] == '.' - && ngx_de_name(&dir)[1] == '.') - { + if (ngx_de_name(&dir)[0] == '.') { continue; } if (!dir.valid_info) { - if (dname.len + 1 + len > fname.len) { - fname.len = dname.len + 1 + len + 32; + if (dname.len + 1 + len + 1 > fname.len) { + fname.len = dname.len + 1 + len + 1 + 32; fname.data = ngx_palloc(pool, fname.len); if (fname.data == NULL) { @@ -468,7 +461,8 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) } else { if (entry[i].dir) { - b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); + b->last = ngx_cpymem(b->last, " -", + sizeof(" -") - 1); } else { length = entry[i].size; @@ -498,13 +492,14 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) } else { size = (ngx_int_t) length; - scale = ' '; + scale = '\0'; } - b->last = ngx_sprintf(b->last, "%6i", size); + if (scale) { + b->last = ngx_sprintf(b->last, "%6i%c", size, scale); - if (scale != ' ') { - *b->last++ = scale; + } else { + b->last = ngx_sprintf(b->last, " %6i", size); } } } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 6efac3df6..9b317f9d9 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -293,7 +293,7 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { NULL }, { ngx_string("fastcgi_next_upstream"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream), diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c index 834282b16..2031a4c0b 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -117,7 +117,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) name.data++; } - var = ngx_http_add_variable(cf, &name, 0); + var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGABLE); if (var == NULL) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index c37f79cb7..012ea4581 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -181,7 +181,7 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = { &ngx_http_gzip_http_version }, { ngx_string("gzip_proxied"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_gzip_conf_t, proxied), diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index c807df94d..a7fd74172 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -244,7 +244,7 @@ static ngx_command_t ngx_http_proxy_commands[] = { NULL }, { ngx_string("proxy_next_upstream"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream), diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 0f3829594..f3eb093d3 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -59,6 +59,7 @@ typedef struct { ngx_uint_t output; /* unsigned output:1; */ ngx_str_t timefmt; + ngx_str_t errmsg; } ngx_http_ssi_ctx_t; @@ -217,8 +218,6 @@ static ngx_int_t (*ngx_http_next_body_filter) (ngx_http_request_t *r, static u_char ngx_http_ssi_string[] = "<!--"; -static u_char ngx_http_ssi_error_string[] = - "[an error occurred while processing the directive]"; static ngx_str_t ngx_http_ssi_none = ngx_string("(none)"); @@ -226,7 +225,8 @@ static ngx_str_t ngx_http_ssi_none = ngx_string("(none)"); #define NGX_HTTP_SSI_ECHO_VAR 0 #define NGX_HTTP_SSI_ECHO_DEFAULT 1 -#define NGX_HTTP_SSI_CONFIG_TIMEFMT 0 +#define NGX_HTTP_SSI_CONFIG_ERRMSG 0 +#define NGX_HTTP_SSI_CONFIG_TIMEFMT 1 #define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0 #define NGX_HTTP_SSI_INCLUDE_FILE 1 @@ -250,6 +250,7 @@ static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = { static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = { + { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0 }, { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0 }, { ngx_null_string, 0, 0 } }; @@ -347,6 +348,11 @@ found: ctx->timefmt.len = sizeof("%A, %d-%b-%Y %H:%M:%S %Z") - 1; ctx->timefmt.data = (u_char *) "%A, %d-%b-%Y %H:%M:%S %Z"; + ctx->errmsg.len = + sizeof("[an error occurred while processing the directive]") - 1; + ctx->errmsg.data = (u_char *) + "[an error occurred while processing the directive]"; + r->filter_need_in_memory = 1; if (r->main == NULL) { @@ -653,9 +659,8 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) } b->memory = 1; - b->pos = ngx_http_ssi_error_string; - b->last = ngx_http_ssi_error_string - + sizeof(ngx_http_ssi_error_string) - 1; + b->pos = ctx->errmsg.data; + b->last = ctx->errmsg.data + ctx->errmsg.len; cl->next = NULL; *ctx->last_out = cl; @@ -1371,6 +1376,12 @@ ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ctx->timefmt = *value; } + value = params[NGX_HTTP_SSI_CONFIG_ERRMSG]; + + if (value) { + ctx->errmsg = *value; + } + return NGX_OK; } diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 130f2b305..bb9a55f49 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -8,9 +8,9 @@ #include <ngx_core.h> #include <ngx_http.h> - #define NGX_DEFLAUT_CERTIFICATE "cert.pem" #define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem" +#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP" static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf); @@ -18,6 +18,14 @@ static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_null_string, 0 } +}; + + static ngx_command_t ngx_http_ssl_commands[] = { { ngx_string("ssl"), @@ -41,13 +49,27 @@ static ngx_command_t ngx_http_ssl_commands[] = { offsetof(ngx_http_ssl_srv_conf_t, certificate_key), NULL }, + { ngx_string("ssl_protocols"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_bitmask_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, protocols), + &ngx_http_ssl_protocols }, + { ngx_string("ssl_ciphers"), - NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE, ngx_conf_set_str_slot, NGX_HTTP_SRV_CONF_OFFSET, offsetof(ngx_http_ssl_srv_conf_t, ciphers), NULL }, + { ngx_string("ssl_prefer_server_ciphers"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers), + NULL }, + ngx_null_command }; @@ -99,6 +121,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * + * scf->protocols = 0; + * scf->certificate.len = 0; * scf->certificate.data = NULL; * scf->certificate_key.len = 0; @@ -108,6 +132,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) */ scf->enable = NGX_CONF_UNSET; + scf->prefer_server_ciphers = NGX_CONF_UNSET; return scf; } @@ -125,101 +150,60 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + ngx_conf_merge_value(conf->prefer_server_ciphers, + prev->prefer_server_ciphers, 0); + + ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, + (NGX_CONF_BITMASK_SET + |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); + ngx_conf_merge_str_value(conf->certificate, prev->certificate, - NGX_DEFLAUT_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->ciphers, prev->ciphers, ""); + NGX_DEFLAUT_CERTIFICATE_KEY); + ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS); - /* TODO: configure methods */ - conf->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + conf->ssl.log = cf->log; - if (conf->ssl_ctx == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_new() failed"); + if (ngx_ssl_create(&conf->ssl, conf->protocols) != NGX_OK) { return NGX_CONF_ERROR; } - if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, conf->ssl_ctx) - == NULL) + if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, &conf->ssl) == NULL) { return NGX_CONF_ERROR; } - - if (conf->ciphers.len) { - if (SSL_CTX_set_cipher_list(conf->ssl_ctx, - (const char *) conf->ciphers.data) == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &conf->ciphers); - } - } - - if (SSL_CTX_use_certificate_chain_file(conf->ssl_ctx, - (char *) conf->certificate.data) == 0) + if (ngx_ssl_certificate(&conf->ssl, conf->certificate.data, + conf->certificate_key.data) != NGX_OK) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_use_certificate_chain_file(\"%s\") failed", - conf->certificate.data); return NGX_CONF_ERROR; } - if (SSL_CTX_use_PrivateKey_file(conf->ssl_ctx, - (char *) conf->certificate_key.data, - SSL_FILETYPE_PEM) == 0) + if (SSL_CTX_set_cipher_list(conf->ssl.ctx, + (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_use_PrivateKey_file(\"%s\") failed", - conf->certificate_key.data); - return NGX_CONF_ERROR; + "SSL_CTX_set_cipher_list(\"%V\") failed", + &conf->ciphers); } - SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL); - - SSL_CTX_set_mode(conf->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + if (conf->prefer_server_ciphers) { + SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } - SSL_CTX_set_read_ahead(conf->ssl_ctx, 1); + /* a temporary 512-bit RSA key is required for export versions of MSIE */ + if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { + return NGX_CONF_ERROR; + } - SSL_CTX_set_session_cache_mode(conf->ssl_ctx, SSL_SESS_CACHE_SERVER); + SSL_CTX_set_session_cache_mode(conf->ssl.ctx, SSL_SESS_CACHE_SERVER); - SSL_CTX_set_session_id_context(conf->ssl_ctx, ngx_http_session_id_ctx, + SSL_CTX_set_session_id_context(conf->ssl.ctx, ngx_http_session_id_ctx, sizeof(ngx_http_session_id_ctx) - 1); return NGX_CONF_OK; } - - -#if 0 - -/* how to enumrate server' configs */ - -static ngx_int_t -ngx_http_ssl_init_process(ngx_cycle_t *cycle) -{ - ngx_uint_t i; - ngx_http_ssl_srv_conf_t *sscf; - ngx_http_core_srv_conf_t **cscfp; - ngx_http_core_main_conf_t *cmcf; - - cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); - - cscfp = cmcf->servers.elts; - - for (i = 0; i < cmcf->servers.nelts; i++) { - sscf = cscfp[i]->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; - - if (sscf->enable) { - cscfp[i]->recv = ngx_ssl_recv; - cscfp[i]->send_chain = ngx_ssl_send_chain; - } - } - - return NGX_OK; -} - -#endif diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index acb0aeeb5..a705635ff 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -15,12 +15,17 @@ typedef struct { ngx_flag_t enable; + + ngx_ssl_t ssl; + + ngx_flag_t prefer_server_ciphers; + + ngx_uint_t protocols; + ngx_str_t certificate; ngx_str_t certificate_key; ngx_str_t ciphers; - - ngx_ssl_ctx_t *ssl_ctx; } ngx_http_ssl_srv_conf_t; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index cb3937c0a..0e6613b51 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -49,6 +49,7 @@ static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, #if (NGX_HTTP_SSL) static void ngx_http_ssl_handshake(ngx_event_t *rev); +static void ngx_http_ssl_handshake_handler(ngx_connection_t *c); static void ngx_http_ssl_close_handler(ngx_event_t *ev); #endif @@ -359,7 +360,7 @@ void ngx_http_init_request(ngx_event_t *rev) if (sscf->enable) { if (c->ssl == NULL) { - if (ngx_ssl_create_connection(sscf->ssl_ctx, c, NGX_SSL_BUFFER) + if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) == NGX_ERROR) { ngx_http_close_connection(c); @@ -367,16 +368,6 @@ void ngx_http_init_request(ngx_event_t *rev) } rev->handler = ngx_http_ssl_handshake; - - /* - * The majority of browsers do not send the "close notify" alert. - * Among them are MSIE, Mozilla, Netscape 4, Konqueror, and Links. - * And what is more, MSIE ignores the server's alert. - * - * Opera always sends the alert. - */ - - c->ssl->no_rcv_shut = 1; } r->main_filter_need_in_memory = 1; @@ -491,21 +482,16 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "https ssl handshake: 0x%02Xd", buf[0]); - c->recv = ngx_ssl_recv; - c->send = ngx_ssl_write; - c->send_chain = ngx_ssl_send_chain; - rc = ngx_ssl_handshake(c); - if (rc == NGX_ERROR) { - ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); - ngx_http_close_connection(r->connection); + if (rc == NGX_AGAIN) { + c->ssl->handler = ngx_http_ssl_handshake_handler; return; } - if (rc != NGX_OK) { - return; - } + ngx_http_ssl_handshake_handler(c); + + return; } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, @@ -519,6 +505,41 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_http_process_request_line(rev); } + +static void +ngx_http_ssl_handshake_handler(ngx_connection_t *c) +{ + ngx_http_request_t *r; + + if (c->ssl->handshaked) { + + /* + * The majority of browsers do not send the "close notify" alert. + * Among them are MSIE, old Mozilla, Netscape 4, Konqueror, + * and Links. And what is more, MSIE ignores the server's alert. + * + * Opera and recent Mozilla send the alert. + */ + + c->ssl->no_wait_shutdown = 1; + + c->read->handler = ngx_http_process_request_line; + /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler; + + ngx_http_process_request_line(c->read); + + return; + } + + r = c->data; + + ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + ngx_http_close_connection(r->connection); + + return; +} + + #endif @@ -1290,7 +1311,7 @@ ngx_http_process_request_header(ngx_http_request_t *r) #if 0 /* MSIE ignores the SSL "close notify" alert */ if (c->ssl) { - r->connection->ssl->no_send_shut = 1; + c->ssl->no_send_shutdown = 1; } #endif } @@ -2126,7 +2147,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev) "keepalive connection", &c->addr_text); #if (NGX_HTTP_SSL) if (c->ssl) { - c->ssl->no_send_shut = 1; + c->ssl->no_send_shutdown = 1; } #endif ngx_http_close_connection(c); diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c index 616222755..571cd270d 100644 --- a/src/imap/ngx_imap_auth_http_module.c +++ b/src/imap/ngx_imap_auth_http_module.c @@ -45,9 +45,9 @@ struct ngx_imap_auth_http_ctx_s { ngx_str_t port; ngx_str_t err; - ngx_msec_t sleep; + time_t sleep; - ngx_peers_t *peers; + ngx_pool_t *pool; }; @@ -63,7 +63,7 @@ static ngx_int_t ngx_imap_auth_http_parse_header_line(ngx_imap_session_t *s, static void ngx_imap_auth_http_block_read(ngx_event_t *rev); static void ngx_imap_auth_http_dummy_handler(ngx_event_t *ev); static ngx_buf_t *ngx_imap_auth_http_create_request(ngx_imap_session_t *s, - ngx_imap_auth_http_conf_t *ahcf); + ngx_pool_t *pool, ngx_imap_auth_http_conf_t *ahcf); static void *ngx_imap_auth_http_create_conf(ngx_conf_t *cf); static char *ngx_imap_auth_http_merge_conf(ngx_conf_t *cf, void *parent, @@ -123,21 +123,32 @@ void ngx_imap_auth_http_init(ngx_imap_session_t *s) { ngx_int_t rc; + ngx_pool_t *pool; ngx_imap_auth_http_ctx_t *ctx; ngx_imap_auth_http_conf_t *ahcf; s->connection->log->action = "in http auth state"; - ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_imap_auth_http_ctx_t)); + pool = ngx_create_pool(2048, s->connection->log); + if (pool == NULL) { + ngx_imap_session_internal_server_error(s); + return; + } + + ctx = ngx_pcalloc(pool, sizeof(ngx_imap_auth_http_ctx_t)); if (ctx == NULL) { + ngx_destroy_pool(pool); ngx_imap_session_internal_server_error(s); return; } + ctx->pool = pool; + ahcf = ngx_imap_get_module_srv_conf(s, ngx_imap_auth_http_module); - ctx->request = ngx_imap_auth_http_create_request(s, ahcf); + ctx->request = ngx_imap_auth_http_create_request(s, pool, ahcf); if (ctx->request == NULL) { + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -152,6 +163,7 @@ ngx_imap_auth_http_init(ngx_imap_session_t *s) if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -197,6 +209,7 @@ ngx_imap_auth_http_write_handler(ngx_event_t *wev) "auth http server %V timed out", &ctx->peer.peers->peer[0].name); ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -207,6 +220,7 @@ ngx_imap_auth_http_write_handler(ngx_event_t *wev) if (n == NGX_ERROR) { ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -253,14 +267,16 @@ ngx_imap_auth_http_read_handler(ngx_event_t *rev) "auth http server %V timed out", &ctx->peer.peers->peer[0].name); ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } if (ctx->response == NULL) { - ctx->response = ngx_create_temp_buf(s->connection->pool, 1024); + ctx->response = ngx_create_temp_buf(ctx->pool, 1024); if (ctx->response == NULL) { ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -282,6 +298,7 @@ ngx_imap_auth_http_read_handler(ngx_event_t *rev) } ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); } @@ -369,6 +386,7 @@ ngx_imap_auth_http_ignore_status_line(ngx_imap_session_t *s, "auth http server &V sent invalid response", &ctx->peer.peers->peer[0].name); ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -397,8 +415,10 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, ngx_imap_auth_http_ctx_t *ctx) { u_char *p; + time_t timer; size_t len, size; ngx_int_t rc, port, n; + ngx_peers_t *peers; struct sockaddr_in *sin; ngx_log_debug0(NGX_LOG_DEBUG_IMAP, s->connection->log, 0, @@ -450,6 +470,7 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, p = ngx_pcalloc(s->connection->pool, size); if (p == NULL) { ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -530,16 +551,20 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, if (ctx->err.len) { s->out = ctx->err; + timer = ctx->sleep; - if (ctx->sleep == 0) { - s->quit = 1; + ngx_destroy_pool(ctx->pool); - ngx_imap_send(s->connection->write); + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client login failed"); + if (timer == 0) { + s->quit = 1; + ngx_imap_send(s->connection->write); return; } - ngx_add_timer(s->connection->read, ctx->sleep * 1000); + ngx_add_timer(s->connection->read, timer * 1000); s->connection->read->handler = ngx_imap_auth_sleep_handler; @@ -550,18 +575,21 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server %V did not send server or port", &ctx->peer.peers->peer[0].name); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } - ctx->peers = ngx_pcalloc(s->connection->pool, sizeof(ngx_peers_t)); - if (ctx->peers == NULL) { + peers = ngx_pcalloc(s->connection->pool, sizeof(ngx_peers_t)); + if (peers == NULL) { + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in)); if (sin == NULL) { + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -574,6 +602,7 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, "auth http server %V sent invalid server " "port:\"%V\"", &ctx->peer.peers->peer[0].name, &ctx->port); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } @@ -587,38 +616,40 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, "auth http server %V sent invalid server " "address:\"%V\"", &ctx->peer.peers->peer[0].name, &ctx->addr); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } - ctx->peers->number = 1; + peers->number = 1; - ctx->peers->peer[0].sockaddr = (struct sockaddr *) sin; - ctx->peers->peer[0].socklen = sizeof(struct sockaddr_in); + peers->peer[0].sockaddr = (struct sockaddr *) sin; + peers->peer[0].socklen = sizeof(struct sockaddr_in); len = ctx->addr.len + 1 + ctx->port.len; - ctx->peers->peer[0].name.len = len; + peers->peer[0].name.len = len; - ctx->peers->peer[0].name.data = ngx_palloc(s->connection->pool, - len); - if (ctx->peers->peer[0].name.data == NULL) { + peers->peer[0].name.data = ngx_palloc(s->connection->pool, len); + if (peers->peer[0].name.data == NULL) { + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; } len = ctx->addr.len; - ngx_memcpy(ctx->peers->peer[0].name.data, ctx->addr.data, len); + ngx_memcpy(peers->peer[0].name.data, ctx->addr.data, len); - ctx->peers->peer[0].name.data[len++] = ':'; + peers->peer[0].name.data[len++] = ':'; - ngx_memcpy(ctx->peers->peer[0].name.data + len, + ngx_memcpy(peers->peer[0].name.data + len, ctx->port.data, ctx->port.len); - ctx->peers->peer[0].uri_separator = ""; + peers->peer[0].uri_separator = ""; - ngx_imap_proxy_init(s, ctx->peers); + ngx_destroy_pool(ctx->pool); + ngx_imap_proxy_init(s, peers); return; } @@ -633,6 +664,7 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, "auth http server %V sent invalid header in response", &ctx->peer.peers->peer[0].name); ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); return; @@ -906,6 +938,7 @@ ngx_imap_auth_http_block_read(ngx_event_t *rev) ctx = ngx_imap_get_module_ctx(s, ngx_imap_auth_http_module); ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); ngx_imap_session_internal_server_error(s); } } @@ -920,7 +953,7 @@ ngx_imap_auth_http_dummy_handler(ngx_event_t *ev) static ngx_buf_t * -ngx_imap_auth_http_create_request(ngx_imap_session_t *s, +ngx_imap_auth_http_create_request(ngx_imap_session_t *s, ngx_pool_t *pool, ngx_imap_auth_http_conf_t *ahcf) { size_t len; @@ -938,7 +971,7 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, + sizeof(CRLF) - 1 + sizeof(CRLF) - 1; - b = ngx_create_temp_buf(s->connection->pool, len); + b = ngx_create_temp_buf(pool, len); if (b == NULL) { return NULL; } @@ -981,7 +1014,7 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, /* add "\r\n" at the header end */ *b->last++ = CR; *b->last++ = LF; -#if (NGX_DEBUG) +#if (NGX_DEBUG_IMAP_PASSWD) { ngx_str_t l; diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c index 6497ced0b..4fe124871 100644 --- a/src/imap/ngx_imap_handler.c +++ b/src/imap/ngx_imap_handler.c @@ -10,12 +10,13 @@ #include <ngx_imap.h> -static void ngx_imap_init_session(ngx_event_t *rev); +static void ngx_imap_init_session(ngx_connection_t *c); static void ngx_imap_init_protocol(ngx_event_t *rev); static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s); static u_char *ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len); #if (NGX_IMAP_SSL) +static void ngx_imap_ssl_handshake_handler(ngx_connection_t *c); static void ngx_imap_ssl_close_handler(ngx_event_t *ev); #endif @@ -43,13 +44,15 @@ static u_char imap_invalid_command[] = "BAD invalid command" CRLF; void ngx_imap_init_connection(ngx_connection_t *c) { - ngx_imap_log_ctx_t *lctx; + ngx_imap_log_ctx_t *lctx; #if (NGX_IMAP_SSL) - ngx_imap_conf_ctx_t *ctx; - ngx_imap_ssl_conf_t *sslcf; + ngx_imap_conf_ctx_t *ctx; + ngx_imap_ssl_conf_t *sslcf; + ngx_imap_core_srv_conf_t *cscf; #endif - ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap init connection"); + ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", + c->number, &c->addr_text, &c->listening->addr_text); lctx = ngx_palloc(c->pool, sizeof(ngx_imap_log_ctx_t)); if (lctx == NULL) { @@ -73,63 +76,59 @@ ngx_imap_init_connection(ngx_connection_t *c) sslcf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_ssl_module); if (sslcf->enable) { - if (ngx_ssl_create_connection(sslcf->ssl_ctx, c, 0) == NGX_ERROR) { + if (ngx_ssl_create_connection(&sslcf->ssl, c, 0) == NGX_ERROR) { ngx_imap_close_connection(c); return; } - c->recv = ngx_ssl_recv; - c->send = ngx_ssl_write; - c->send_chain = ngx_ssl_send_chain; - } + if (ngx_ssl_handshake(c) == NGX_AGAIN) { -#endif + cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); - ngx_imap_init_session(c->read); -} + ngx_add_timer(c->read, cscf->timeout); + c->ssl->handler = ngx_imap_ssl_handshake_handler; -static void -ngx_imap_init_session(ngx_event_t *rev) -{ - ngx_connection_t *c; - ngx_imap_session_t *s; - ngx_imap_log_ctx_t *lctx; - ngx_imap_conf_ctx_t *ctx; - ngx_imap_core_srv_conf_t *cscf; -#if (NGX_IMAP_SSL) - ngx_int_t rc; -#endif + return; + } - c = rev->data; - ctx = c->ctx; - cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); + ngx_imap_ssl_handshake_handler(c); + return; + } -#if (NGX_IMAP_SSL) +#endif - if (c->ssl) { + ngx_imap_init_session(c); +} - rc = ngx_ssl_handshake(c); - if (rc == NGX_ERROR) { - ngx_imap_close_connection(c); - return; - } +#if (NGX_IMAP_SSL) - if (rc == NGX_AGAIN) { - ngx_add_timer(rev, cscf->timeout); - c->read->handler = ngx_imap_init_session; +static void +ngx_imap_ssl_handshake_handler(ngx_connection_t *c) +{ + if (c->ssl->handshaked) { + ngx_imap_init_session(c); + return; + } - if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { - ngx_imap_close_connection(c); - } + ngx_imap_close_connection(c); + return; +} - return; - } +#endif - } -#endif +static void +ngx_imap_init_session(ngx_connection_t *c) +{ + ngx_imap_session_t *s; + ngx_imap_log_ctx_t *lctx; + ngx_imap_conf_ctx_t *ctx; + ngx_imap_core_srv_conf_t *cscf; + + c->read->handler = ngx_imap_init_protocol; + c->write->handler = ngx_imap_send; s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t)); if (s == NULL) { @@ -137,6 +136,9 @@ ngx_imap_init_session(ngx_event_t *rev) return; } + ctx = c->ctx; + cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); + c->data = s; s->connection = c; @@ -156,12 +158,9 @@ ngx_imap_init_session(ngx_event_t *rev) lctx = c->log->data; lctx->session = s; - c->read->handler = ngx_imap_init_protocol; - c->write->handler = ngx_imap_send; + ngx_add_timer(c->read, cscf->timeout); - ngx_add_timer(rev, cscf->timeout); - - if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { ngx_imap_close_connection(c); } @@ -378,9 +377,14 @@ ngx_imap_auth_state(ngx_event_t *rev) ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len); +#if (NGX_DEBUG_IMAP_PASSWD) ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap login:\"%V\" passwd:\"%V\"", &s->login, &s->passwd); +#else + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "imap login:\"%V\"", &s->login); +#endif s->args.nelts = 0; s->buffer->pos = s->buffer->start; @@ -584,8 +588,10 @@ ngx_pop3_auth_state(ngx_event_t *rev) ngx_memcpy(s->passwd.data, arg[0].data, s->passwd.len); +#if (NGX_DEBUG_IMAP_PASSWD) ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "pop3 passwd: \"%V\"", &s->passwd); +#endif s->args.nelts = 0; s->buffer->pos = s->buffer->start; diff --git a/src/imap/ngx_imap_proxy_module.c b/src/imap/ngx_imap_proxy_module.c index 86a4ff8a9..bfbcc1cbe 100644 --- a/src/imap/ngx_imap_proxy_module.c +++ b/src/imap/ngx_imap_proxy_module.c @@ -156,6 +156,7 @@ ngx_imap_proxy_block_read(ngx_event_t *rev) static void ngx_imap_proxy_imap_handler(ngx_event_t *rev) { + char *action; u_char *p; ngx_int_t rc; ngx_str_t line; @@ -293,6 +294,11 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) ngx_add_timer(s->connection->read, pcf->timeout); ngx_del_timer(c->read); + action = c->log->action; + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + c->log->action = action; + c->log->action = "proxying"; } } @@ -301,6 +307,7 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) static void ngx_imap_proxy_pop3_handler(ngx_event_t *rev) { + char *action; u_char *p; ngx_int_t rc; ngx_str_t line; @@ -418,6 +425,11 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev) ngx_add_timer(s->connection->read, pcf->timeout); ngx_del_timer(c->read); + action = c->log->action; + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + c->log->action = action; + c->log->action = "proxying"; } } @@ -507,6 +519,7 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what) static void ngx_imap_proxy_handler(ngx_event_t *ev) { + char *action; size_t size; ssize_t n; ngx_buf_t *b; @@ -603,7 +616,17 @@ ngx_imap_proxy_handler(ngx_event_t *ev) if (size && src->read->ready) { n = src->recv(src, b->last, size); - if (n == NGX_ERROR || n == 0) { + if (n == NGX_ERROR) { + ngx_imap_proxy_close_session(s); + return; + } + + if (n == 0) { + action = c->log->action; + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxied session done"); + c->log->action = action; + ngx_imap_proxy_close_session(s); return; } diff --git a/src/imap/ngx_imap_ssl_module.c b/src/imap/ngx_imap_ssl_module.c index bd4579e68..be6fca93b 100644 --- a/src/imap/ngx_imap_ssl_module.c +++ b/src/imap/ngx_imap_ssl_module.c @@ -11,12 +11,21 @@ #define NGX_DEFLAUT_CERTIFICATE "cert.pem" #define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem" +#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP" static void *ngx_imap_ssl_create_conf(ngx_conf_t *cf); static char *ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_conf_bitmask_t ngx_imap_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_null_string, 0 } +}; + + static ngx_command_t ngx_imap_ssl_commands[] = { { ngx_string("ssl"), @@ -40,6 +49,13 @@ static ngx_command_t ngx_imap_ssl_commands[] = { offsetof(ngx_imap_ssl_conf_t, certificate_key), NULL }, + { ngx_string("ssl_protocols"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_bitmask_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, protocols), + &ngx_imap_ssl_protocols }, + { ngx_string("ssl_ciphers"), NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -47,6 +63,13 @@ static ngx_command_t ngx_imap_ssl_commands[] = { offsetof(ngx_imap_ssl_conf_t, ciphers), NULL }, + { ngx_string("ssl_prefer_server_ciphers"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, prefer_server_ciphers), + NULL }, + ngx_null_command }; @@ -92,6 +115,8 @@ ngx_imap_ssl_create_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * + * scf->protocols = 0; + * * scf->certificate.len = 0; * scf->certificate.data = NULL; * scf->certificate_key.len = 0; @@ -101,6 +126,7 @@ ngx_imap_ssl_create_conf(ngx_conf_t *cf) */ scf->enable = NGX_CONF_UNSET; + scf->prefer_server_ciphers = NGX_CONF_UNSET; return scf; } @@ -118,39 +144,41 @@ ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + ngx_conf_merge_value(conf->prefer_server_ciphers, + prev->prefer_server_ciphers, 0); + + ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, + (NGX_CONF_BITMASK_SET + |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); + 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->ciphers, prev->ciphers, ""); + ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS); - /* TODO: configure methods */ + conf->ssl.log = cf->log; - conf->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); - - if (conf->ssl_ctx == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_new() failed"); + if (ngx_ssl_create(&conf->ssl, conf->protocols) != NGX_OK) { return NGX_CONF_ERROR; } - if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, conf->ssl_ctx) - == NULL) + if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, &conf->ssl) == NULL) { return NGX_CONF_ERROR; } - -#if 0 - SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL); - SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_NO_SSLv3); - SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_SINGLE_DH_USE); -#endif + if (ngx_ssl_certificate(&conf->ssl, conf->certificate.data, + conf->certificate_key.data) != NGX_OK) + { + return NGX_CONF_ERROR; + } if (conf->ciphers.len) { - if (SSL_CTX_set_cipher_list(conf->ssl_ctx, + if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, @@ -159,35 +187,13 @@ ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) } } - if (SSL_CTX_use_certificate_chain_file(conf->ssl_ctx, - (char *) conf->certificate.data) == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_use_certificate_chain_file(\"%s\") failed", - conf->certificate.data); - return NGX_CONF_ERROR; - } - - - if (SSL_CTX_use_PrivateKey_file(conf->ssl_ctx, - (char *) conf->certificate_key.data, - SSL_FILETYPE_PEM) == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_use_PrivateKey_file(\"%s\") failed", - conf->certificate_key.data); + if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { return NGX_CONF_ERROR; } - SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL); - - SSL_CTX_set_mode(conf->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - - SSL_CTX_set_read_ahead(conf->ssl_ctx, 1); - - SSL_CTX_set_session_cache_mode(conf->ssl_ctx, SSL_SESS_CACHE_SERVER); + SSL_CTX_set_session_cache_mode(conf->ssl.ctx, SSL_SESS_CACHE_SERVER); - SSL_CTX_set_session_id_context(conf->ssl_ctx, ngx_imap_session_id_ctx, + SSL_CTX_set_session_id_context(conf->ssl.ctx, ngx_imap_session_id_ctx, sizeof(ngx_imap_session_id_ctx) - 1); return NGX_CONF_OK; diff --git a/src/imap/ngx_imap_ssl_module.h b/src/imap/ngx_imap_ssl_module.h index 150a61755..fd0ccada4 100644 --- a/src/imap/ngx_imap_ssl_module.h +++ b/src/imap/ngx_imap_ssl_module.h @@ -15,12 +15,18 @@ typedef struct { ngx_flag_t enable; + + ngx_ssl_t ssl; + + ngx_flag_t prefer_server_ciphers; + + ngx_uint_t protocols; + ngx_str_t certificate; ngx_str_t certificate_key; ngx_str_t ciphers; - ngx_ssl_ctx_t *ssl_ctx; } ngx_imap_ssl_conf_t; diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h index 746a71515..9710855aa 100644 --- a/src/os/unix/ngx_atomic.h +++ b/src/os/unix/ngx_atomic.h @@ -12,7 +12,7 @@ #include <ngx_core.h> -#if ( __i386__ ) +#if ( __i386__ || __i386 ) #define NGX_HAVE_ATOMIC_OPS 1 @@ -109,7 +109,7 @@ ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, } -#elif ( __amd64__ ) +#elif ( __amd64__ || __amd64 ) #define NGX_HAVE_ATOMIC_OPS 1 @@ -183,7 +183,7 @@ ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, } -#elif ( __sparc__ ) +#elif ( __sparc__ || __sparcv9 ) #define NGX_HAVE_ATOMIC_OPS 1 diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c index 8610a5638..f82a6ac20 100644 --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -77,7 +77,7 @@ sysctl_t sysctls[] = { void ngx_debug_init() { -#if (NGX_DEBUG && !NGX_NO_DEBUG_MALLOC) +#if (NGX_DEBUG_MALLOC) #if __FreeBSD_version >= 500014 _malloc_options = "J"; |