Mercurial > hg > nginx-mail
comparison 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 |
comparison
equal
deleted
inserted
replaced
572:06419a2298a9 | 665:0b460e61bdcd |
---|---|
13 ngx_uint_t engine; /* unsigned engine:1; */ | 13 ngx_uint_t engine; /* unsigned engine:1; */ |
14 } ngx_openssl_conf_t; | 14 } ngx_openssl_conf_t; |
15 | 15 |
16 | 16 |
17 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); | 17 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); |
18 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, | |
19 int ret); | |
18 static void ngx_ssl_handshake_handler(ngx_event_t *ev); | 20 static void ngx_ssl_handshake_handler(ngx_event_t *ev); |
19 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); | 21 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); |
20 static void ngx_ssl_write_handler(ngx_event_t *wev); | 22 static void ngx_ssl_write_handler(ngx_event_t *wev); |
21 static void ngx_ssl_read_handler(ngx_event_t *rev); | 23 static void ngx_ssl_read_handler(ngx_event_t *rev); |
22 static void ngx_ssl_shutdown_handler(ngx_event_t *ev); | 24 static void ngx_ssl_shutdown_handler(ngx_event_t *ev); |
102 SSL_library_init(); | 104 SSL_library_init(); |
103 SSL_load_error_strings(); | 105 SSL_load_error_strings(); |
104 | 106 |
105 ENGINE_load_builtin_engines(); | 107 ENGINE_load_builtin_engines(); |
106 | 108 |
109 OpenSSL_add_all_algorithms(); | |
110 | |
107 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); | 111 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); |
108 | 112 |
109 if (ngx_ssl_connection_index == -1) { | 113 if (ngx_ssl_connection_index == -1) { |
110 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed"); | 114 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed"); |
111 return NGX_ERROR; | 115 return NGX_ERROR; |
149 | 153 |
150 /* client side options */ | 154 /* client side options */ |
151 | 155 |
152 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); | 156 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); |
153 SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); | 157 SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); |
154 SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); | |
155 | 158 |
156 /* server side options */ | 159 /* server side options */ |
157 | 160 |
158 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); | 161 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); |
159 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); | 162 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); |
172 if (ngx_ssl_protocols[protocols >> 1] != 0) { | 175 if (ngx_ssl_protocols[protocols >> 1] != 0) { |
173 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); | 176 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); |
174 } | 177 } |
175 | 178 |
176 SSL_CTX_set_read_ahead(ssl->ctx, 1); | 179 SSL_CTX_set_read_ahead(ssl->ctx, 1); |
180 | |
181 SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); | |
177 | 182 |
178 return NGX_OK; | 183 return NGX_OK; |
179 } | 184 } |
180 | 185 |
181 | 186 |
345 OPENSSL_free(issuer); | 350 OPENSSL_free(issuer); |
346 } | 351 } |
347 #endif | 352 #endif |
348 | 353 |
349 return 1; | 354 return 1; |
355 } | |
356 | |
357 | |
358 static void | |
359 ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) | |
360 { | |
361 ngx_connection_t *c; | |
362 | |
363 if (where & SSL_CB_HANDSHAKE_START) { | |
364 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); | |
365 | |
366 if (c->ssl->handshaked) { | |
367 c->ssl->renegotiation = 1; | |
368 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation"); | |
369 } | |
370 } | |
350 } | 371 } |
351 | 372 |
352 | 373 |
353 ngx_int_t | 374 ngx_int_t |
354 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl) | 375 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl) |
537 } | 558 } |
538 | 559 |
539 #if (NGX_DEBUG) | 560 #if (NGX_DEBUG) |
540 { | 561 { |
541 char buf[129], *s, *d; | 562 char buf[129], *s, *d; |
563 #if OPENSSL_VERSION_NUMBER >= 0x10000000L | |
564 const | |
565 #endif | |
542 SSL_CIPHER *cipher; | 566 SSL_CIPHER *cipher; |
543 | 567 |
544 cipher = SSL_get_current_cipher(c->ssl->connection); | 568 cipher = SSL_get_current_cipher(c->ssl->connection); |
545 | 569 |
546 if (cipher) { | 570 if (cipher) { |
585 c->recv = ngx_ssl_recv; | 609 c->recv = ngx_ssl_recv; |
586 c->send = ngx_ssl_write; | 610 c->send = ngx_ssl_write; |
587 c->recv_chain = ngx_ssl_recv_chain; | 611 c->recv_chain = ngx_ssl_recv_chain; |
588 c->send_chain = ngx_ssl_send_chain; | 612 c->send_chain = ngx_ssl_send_chain; |
589 | 613 |
614 /* initial handshake done, disable renegotiation (CVE-2009-3555) */ | |
615 if (c->ssl->connection->s3) { | |
616 c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; | |
617 } | |
618 | |
590 return NGX_OK; | 619 return NGX_OK; |
591 } | 620 } |
592 | 621 |
593 sslerr = SSL_get_error(c->ssl->connection, n); | 622 sslerr = SSL_get_error(c->ssl->connection, n); |
594 | 623 |
786 static ngx_int_t | 815 static ngx_int_t |
787 ngx_ssl_handle_recv(ngx_connection_t *c, int n) | 816 ngx_ssl_handle_recv(ngx_connection_t *c, int n) |
788 { | 817 { |
789 int sslerr; | 818 int sslerr; |
790 ngx_err_t err; | 819 ngx_err_t err; |
820 | |
821 if (c->ssl->renegotiation) { | |
822 /* | |
823 * disable renegotiation (CVE-2009-3555): | |
824 * OpenSSL (at least up to 0.9.8l) does not handle disabled | |
825 * renegotiation gracefully, so drop connection here | |
826 */ | |
827 | |
828 ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled"); | |
829 | |
830 c->ssl->no_wait_shutdown = 1; | |
831 c->ssl->no_send_shutdown = 1; | |
832 | |
833 return NGX_ERROR; | |
834 } | |
791 | 835 |
792 if (n > 0) { | 836 if (n > 0) { |
793 | 837 |
794 if (c->ssl->saved_write_handler) { | 838 if (c->ssl->saved_write_handler) { |
795 | 839 |
944 send = 0; | 988 send = 0; |
945 flush = (in == NULL) ? 1 : 0; | 989 flush = (in == NULL) ? 1 : 0; |
946 | 990 |
947 for ( ;; ) { | 991 for ( ;; ) { |
948 | 992 |
949 while (in && buf->last < buf->end) { | 993 while (in && buf->last < buf->end && send < limit) { |
950 if (in->buf->last_buf || in->buf->flush) { | 994 if (in->buf->last_buf || in->buf->flush) { |
951 flush = 1; | 995 flush = 1; |
952 } | 996 } |
953 | 997 |
954 if (ngx_buf_special(in->buf)) { | 998 if (ngx_buf_special(in->buf)) { |
971 "SSL buf copy: %d", size); | 1015 "SSL buf copy: %d", size); |
972 | 1016 |
973 ngx_memcpy(buf->last, in->buf->pos, size); | 1017 ngx_memcpy(buf->last, in->buf->pos, size); |
974 | 1018 |
975 buf->last += size; | 1019 buf->last += size; |
976 | |
977 in->buf->pos += size; | 1020 in->buf->pos += size; |
1021 send += size; | |
978 | 1022 |
979 if (in->buf->pos == in->buf->last) { | 1023 if (in->buf->pos == in->buf->last) { |
980 in = in->next; | 1024 in = in->next; |
981 } | 1025 } |
982 } | 1026 } |
997 c->buffered |= NGX_SSL_BUFFERED; | 1041 c->buffered |= NGX_SSL_BUFFERED; |
998 return in; | 1042 return in; |
999 } | 1043 } |
1000 | 1044 |
1001 buf->pos += n; | 1045 buf->pos += n; |
1002 send += n; | |
1003 c->sent += n; | 1046 c->sent += n; |
1004 | 1047 |
1005 if (n < size) { | 1048 if (n < size) { |
1006 break; | 1049 break; |
1007 } | 1050 } |
1266 } else if (sslerr == SSL_ERROR_SSL) { | 1309 } else if (sslerr == SSL_ERROR_SSL) { |
1267 | 1310 |
1268 n = ERR_GET_REASON(ERR_peek_error()); | 1311 n = ERR_GET_REASON(ERR_peek_error()); |
1269 | 1312 |
1270 /* handshake failures */ | 1313 /* handshake failures */ |
1271 if (n == SSL_R_DIGEST_CHECK_FAILED /* 149 */ | 1314 if (n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */ |
1315 || n == SSL_R_DIGEST_CHECK_FAILED /* 149 */ | |
1316 || n == SSL_R_LENGTH_MISMATCH /* 159 */ | |
1272 || n == SSL_R_NO_CIPHERS_PASSED /* 182 */ | 1317 || n == SSL_R_NO_CIPHERS_PASSED /* 182 */ |
1318 || n == SSL_R_NO_CIPHERS_SPECIFIED /* 183 */ | |
1273 || n == SSL_R_NO_SHARED_CIPHER /* 193 */ | 1319 || n == SSL_R_NO_SHARED_CIPHER /* 193 */ |
1320 || n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */ | |
1274 || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */ | 1321 || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */ |
1275 || n == SSL_R_UNEXPECTED_RECORD /* 245 */ | 1322 || n == SSL_R_UNEXPECTED_RECORD /* 245 */ |
1323 || n == SSL_R_UNKNOWN_ALERT_TYPE /* 246 */ | |
1324 || n == SSL_R_UNKNOWN_PROTOCOL /* 252 */ | |
1276 || n == SSL_R_WRONG_VERSION_NUMBER /* 267 */ | 1325 || n == SSL_R_WRONG_VERSION_NUMBER /* 267 */ |
1277 || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */ | 1326 || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */ |
1278 || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ | 1327 || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ |
1279 || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */ | 1328 || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */ |
1280 || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */ | 1329 || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */ |
1382 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { | 1431 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { |
1383 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); | 1432 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); |
1384 return NGX_OK; | 1433 return NGX_OK; |
1385 } | 1434 } |
1386 | 1435 |
1436 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); | |
1437 | |
1387 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { | 1438 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { |
1388 | 1439 |
1389 /* | 1440 /* |
1390 * If the server explicitly says that it does not support | 1441 * If the server explicitly says that it does not support |
1391 * session reuse (see SSL_SESS_CACHE_OFF above), then | 1442 * session reuse (see SSL_SESS_CACHE_OFF above), then |
1412 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) { | 1463 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) { |
1413 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL; | 1464 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL; |
1414 } | 1465 } |
1415 | 1466 |
1416 SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode); | 1467 SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode); |
1417 | |
1418 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); | |
1419 | 1468 |
1420 if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) { | 1469 if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) { |
1421 | 1470 |
1422 if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) { | 1471 if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) { |
1423 SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache); | 1472 SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache); |
1586 ngx_memcpy(id, sess->session_id, sess->session_id_length); | 1635 ngx_memcpy(id, sess->session_id, sess->session_id_length); |
1587 | 1636 |
1588 hash = ngx_crc32_short(sess->session_id, sess->session_id_length); | 1637 hash = ngx_crc32_short(sess->session_id, sess->session_id_length); |
1589 | 1638 |
1590 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1639 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1591 "http ssl new session: %08XD:%d:%d", | 1640 "ssl new session: %08XD:%d:%d", |
1592 hash, sess->session_id_length, len); | 1641 hash, sess->session_id_length, len); |
1593 | 1642 |
1594 sess_id->node.key = hash; | 1643 sess_id->node.key = hash; |
1595 sess_id->node.data = (u_char) sess->session_id_length; | 1644 sess_id->node.data = (u_char) sess->session_id_length; |
1596 sess_id->id = id; | 1645 sess_id->id = id; |
1649 | 1698 |
1650 hash = ngx_crc32_short(id, (size_t) len); | 1699 hash = ngx_crc32_short(id, (size_t) len); |
1651 *copy = 0; | 1700 *copy = 0; |
1652 | 1701 |
1653 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1702 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1654 "http ssl get session: %08XD:%d", hash, len); | 1703 "ssl get session: %08XD:%d", hash, len); |
1655 | 1704 |
1656 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), | 1705 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), |
1657 ngx_ssl_session_cache_index); | 1706 ngx_ssl_session_cache_index); |
1658 | 1707 |
1659 cache = shm_zone->data; | 1708 cache = shm_zone->data; |
1763 len = (size_t) sess->session_id_length; | 1812 len = (size_t) sess->session_id_length; |
1764 | 1813 |
1765 hash = ngx_crc32_short(id, len); | 1814 hash = ngx_crc32_short(id, len); |
1766 | 1815 |
1767 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, | 1816 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, |
1768 "http ssl remove session: %08XD:%uz", hash, len); | 1817 "ssl remove session: %08XD:%uz", hash, len); |
1769 | 1818 |
1770 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; | 1819 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
1771 | 1820 |
1772 ngx_shmtx_lock(&shpool->mutex); | 1821 ngx_shmtx_lock(&shpool->mutex); |
1773 | 1822 |
1927 return NGX_OK; | 1976 return NGX_OK; |
1928 } | 1977 } |
1929 | 1978 |
1930 | 1979 |
1931 ngx_int_t | 1980 ngx_int_t |
1981 ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) | |
1982 { | |
1983 int len; | |
1984 u_char *p, *buf; | |
1985 SSL_SESSION *sess; | |
1986 | |
1987 sess = SSL_get0_session(c->ssl->connection); | |
1988 | |
1989 len = i2d_SSL_SESSION(sess, NULL); | |
1990 | |
1991 buf = ngx_alloc(len, c->log); | |
1992 if (buf == NULL) { | |
1993 return NGX_ERROR; | |
1994 } | |
1995 | |
1996 s->len = 2 * len; | |
1997 s->data = ngx_pnalloc(pool, 2 * len); | |
1998 if (s->data == NULL) { | |
1999 ngx_free(buf); | |
2000 return NGX_ERROR; | |
2001 } | |
2002 | |
2003 p = buf; | |
2004 i2d_SSL_SESSION(sess, &p); | |
2005 | |
2006 ngx_hex_dump(s->data, buf, len); | |
2007 | |
2008 ngx_free(buf); | |
2009 | |
2010 return NGX_OK; | |
2011 } | |
2012 | |
2013 | |
2014 ngx_int_t | |
1932 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) | 2015 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) |
1933 { | 2016 { |
1934 size_t len; | 2017 size_t len; |
1935 BIO *bio; | 2018 BIO *bio; |
1936 X509 *cert; | 2019 X509 *cert; |
2149 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) | 2232 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) |
2150 { | 2233 { |
2151 X509 *cert; | 2234 X509 *cert; |
2152 | 2235 |
2153 if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) { | 2236 if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) { |
2154 s->len = sizeof("FAILED") - 1; | 2237 ngx_str_set(s, "FAILED"); |
2155 s->data = (u_char *) "FAILED"; | |
2156 | |
2157 return NGX_OK; | 2238 return NGX_OK; |
2158 } | 2239 } |
2159 | 2240 |
2160 cert = SSL_get_peer_certificate(c->ssl->connection); | 2241 cert = SSL_get_peer_certificate(c->ssl->connection); |
2161 | 2242 |
2162 if (cert) { | 2243 if (cert) { |
2163 s->len = sizeof("SUCCESS") - 1; | 2244 ngx_str_set(s, "SUCCESS"); |
2164 s->data = (u_char *) "SUCCESS"; | |
2165 | 2245 |
2166 } else { | 2246 } else { |
2167 s->len = sizeof("NONE") - 1; | 2247 ngx_str_set(s, "NONE"); |
2168 s->data = (u_char *) "NONE"; | |
2169 } | 2248 } |
2170 | 2249 |
2171 X509_free(cert); | 2250 X509_free(cert); |
2172 | 2251 |
2173 return NGX_OK; | 2252 return NGX_OK; |
2235 | 2314 |
2236 | 2315 |
2237 static void | 2316 static void |
2238 ngx_openssl_exit(ngx_cycle_t *cycle) | 2317 ngx_openssl_exit(ngx_cycle_t *cycle) |
2239 { | 2318 { |
2319 EVP_cleanup(); | |
2240 ENGINE_cleanup(); | 2320 ENGINE_cleanup(); |
2241 } | 2321 } |