Mercurial > hg > nginx-mail
diff src/event/ngx_event_openssl.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | ce857f6b74a7 |
children |
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -15,6 +15,8 @@ typedef struct { static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); +static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, + int ret); 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); @@ -104,6 +106,8 @@ ngx_ssl_init(ngx_log_t *log) ENGINE_load_builtin_engines(); + OpenSSL_add_all_algorithms(); + ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_connection_index == -1) { @@ -151,7 +155,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); - SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); /* server side options */ @@ -175,6 +178,8 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_read_ahead(ssl->ctx, 1); + SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); + return NGX_OK; } @@ -350,6 +355,22 @@ ngx_http_ssl_verify_callback(int ok, X50 } +static void +ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) +{ + ngx_connection_t *c; + + if (where & SSL_CB_HANDSHAKE_START) { + c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); + + if (c->ssl->handshaked) { + c->ssl->renegotiation = 1; + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation"); + } + } +} + + ngx_int_t ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl) { @@ -539,6 +560,9 @@ ngx_ssl_handshake(ngx_connection_t *c) #if (NGX_DEBUG) { char buf[129], *s, *d; +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + const +#endif SSL_CIPHER *cipher; cipher = SSL_get_current_cipher(c->ssl->connection); @@ -587,6 +611,11 @@ ngx_ssl_handshake(ngx_connection_t *c) c->recv_chain = ngx_ssl_recv_chain; c->send_chain = ngx_ssl_send_chain; + /* initial handshake done, disable renegotiation (CVE-2009-3555) */ + if (c->ssl->connection->s3) { + c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; + } + return NGX_OK; } @@ -789,6 +818,21 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int sslerr; ngx_err_t err; + if (c->ssl->renegotiation) { + /* + * disable renegotiation (CVE-2009-3555): + * OpenSSL (at least up to 0.9.8l) does not handle disabled + * renegotiation gracefully, so drop connection here + */ + + ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled"); + + c->ssl->no_wait_shutdown = 1; + c->ssl->no_send_shutdown = 1; + + return NGX_ERROR; + } + if (n > 0) { if (c->ssl->saved_write_handler) { @@ -946,7 +990,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, for ( ;; ) { - while (in && buf->last < buf->end) { + while (in && buf->last < buf->end && send < limit) { if (in->buf->last_buf || in->buf->flush) { flush = 1; } @@ -973,8 +1017,8 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_memcpy(buf->last, in->buf->pos, size); buf->last += size; - in->buf->pos += size; + send += size; if (in->buf->pos == in->buf->last) { in = in->next; @@ -999,7 +1043,6 @@ ngx_ssl_send_chain(ngx_connection_t *c, } buf->pos += n; - send += n; c->sent += n; if (n < size) { @@ -1268,11 +1311,17 @@ ngx_ssl_connection_error(ngx_connection_ n = ERR_GET_REASON(ERR_peek_error()); /* handshake failures */ - if (n == SSL_R_DIGEST_CHECK_FAILED /* 149 */ + if (n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */ + || n == SSL_R_DIGEST_CHECK_FAILED /* 149 */ + || n == SSL_R_LENGTH_MISMATCH /* 159 */ || n == SSL_R_NO_CIPHERS_PASSED /* 182 */ + || n == SSL_R_NO_CIPHERS_SPECIFIED /* 183 */ || n == SSL_R_NO_SHARED_CIPHER /* 193 */ + || n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */ || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */ || n == SSL_R_UNEXPECTED_RECORD /* 245 */ + || n == SSL_R_UNKNOWN_ALERT_TYPE /* 246 */ + || n == SSL_R_UNKNOWN_PROTOCOL /* 252 */ || n == SSL_R_WRONG_VERSION_NUMBER /* 267 */ || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */ || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ @@ -1384,6 +1433,8 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng return NGX_OK; } + SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); + if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { /* @@ -1415,8 +1466,6 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode); - SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); - if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) { if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) { @@ -1588,7 +1637,7 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_ hash = ngx_crc32_short(sess->session_id, sess->session_id_length); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "http ssl new session: %08XD:%d:%d", + "ssl new session: %08XD:%d:%d", hash, sess->session_id_length, len); sess_id->node.key = hash; @@ -1651,7 +1700,7 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ *copy = 0; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "http ssl get session: %08XD:%d", hash, len); + "ssl get session: %08XD:%d", hash, len); shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), ngx_ssl_session_cache_index); @@ -1765,7 +1814,7 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx hash = ngx_crc32_short(id, len); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, - "http ssl remove session: %08XD:%uz", hash, len); + "ssl remove session: %08XD:%uz", hash, len); shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; @@ -1929,6 +1978,40 @@ ngx_ssl_get_cipher_name(ngx_connection_t ngx_int_t +ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + int len; + u_char *p, *buf; + SSL_SESSION *sess; + + sess = SSL_get0_session(c->ssl->connection); + + len = i2d_SSL_SESSION(sess, NULL); + + buf = ngx_alloc(len, c->log); + if (buf == NULL) { + return NGX_ERROR; + } + + s->len = 2 * len; + s->data = ngx_pnalloc(pool, 2 * len); + if (s->data == NULL) { + ngx_free(buf); + return NGX_ERROR; + } + + p = buf; + i2d_SSL_SESSION(sess, &p); + + ngx_hex_dump(s->data, buf, len); + + ngx_free(buf); + + return NGX_OK; +} + + +ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { size_t len; @@ -2151,21 +2234,17 @@ ngx_ssl_get_client_verify(ngx_connection X509 *cert; if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) { - s->len = sizeof("FAILED") - 1; - s->data = (u_char *) "FAILED"; - + ngx_str_set(s, "FAILED"); return NGX_OK; } cert = SSL_get_peer_certificate(c->ssl->connection); if (cert) { - s->len = sizeof("SUCCESS") - 1; - s->data = (u_char *) "SUCCESS"; + ngx_str_set(s, "SUCCESS"); } else { - s->len = sizeof("NONE") - 1; - s->data = (u_char *) "NONE"; + ngx_str_set(s, "NONE"); } X509_free(cert); @@ -2237,5 +2316,6 @@ ngx_openssl_engine(ngx_conf_t *cf, ngx_c static void ngx_openssl_exit(ngx_cycle_t *cycle) { + EVP_cleanup(); ENGINE_cleanup(); }