3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
14 ngx_uint_t engine
; /* unsigned engine:1; */
18 static int ngx_http_ssl_verify_callback(int ok
, X509_STORE_CTX
*x509_store
);
19 static void ngx_ssl_info_callback(const ngx_ssl_conn_t
*ssl_conn
, int where
,
21 static void ngx_ssl_handshake_handler(ngx_event_t
*ev
);
22 static ngx_int_t
ngx_ssl_handle_recv(ngx_connection_t
*c
, int n
);
23 static void ngx_ssl_write_handler(ngx_event_t
*wev
);
24 static void ngx_ssl_read_handler(ngx_event_t
*rev
);
25 static void ngx_ssl_shutdown_handler(ngx_event_t
*ev
);
26 static void ngx_ssl_connection_error(ngx_connection_t
*c
, int sslerr
,
27 ngx_err_t err
, char *text
);
28 static void ngx_ssl_clear_error(ngx_log_t
*log
);
30 ngx_int_t
ngx_ssl_session_cache_init(ngx_shm_zone_t
*shm_zone
, void *data
);
31 static int ngx_ssl_new_session(ngx_ssl_conn_t
*ssl_conn
,
32 ngx_ssl_session_t
*sess
);
33 static ngx_ssl_session_t
*ngx_ssl_get_cached_session(ngx_ssl_conn_t
*ssl_conn
,
34 u_char
*id
, int len
, int *copy
);
35 static void ngx_ssl_remove_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
);
36 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t
*cache
,
37 ngx_slab_pool_t
*shpool
, ngx_uint_t n
);
38 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
39 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
);
41 static void *ngx_openssl_create_conf(ngx_cycle_t
*cycle
);
42 static char *ngx_openssl_engine(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
);
43 static void ngx_openssl_exit(ngx_cycle_t
*cycle
);
46 static ngx_command_t ngx_openssl_commands
[] = {
48 { ngx_string("ssl_engine"),
49 NGX_MAIN_CONF
|NGX_DIRECT_CONF
|NGX_CONF_TAKE1
,
59 static ngx_core_module_t ngx_openssl_module_ctx
= {
60 ngx_string("openssl"),
61 ngx_openssl_create_conf
,
66 ngx_module_t ngx_openssl_module
= {
68 &ngx_openssl_module_ctx
, /* module context */
69 ngx_openssl_commands
, /* module directives */
70 NGX_CORE_MODULE
, /* module type */
71 NULL
, /* init master */
72 NULL
, /* init module */
73 NULL
, /* init process */
74 NULL
, /* init thread */
75 NULL
, /* exit thread */
76 NULL
, /* exit process */
77 ngx_openssl_exit
, /* exit master */
82 int ngx_ssl_connection_index
;
83 int ngx_ssl_server_conf_index
;
84 int ngx_ssl_session_cache_index
;
85 int ngx_ssl_certificate_index
;
86 int ngx_ssl_stapling_index
;
90 ngx_ssl_init(ngx_log_t
*log
)
95 SSL_load_error_strings();
97 OpenSSL_add_all_algorithms();
99 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
100 #ifndef SSL_OP_NO_COMPRESSION
103 * Disable gzip compression in OpenSSL prior to 1.0.0 version,
104 * this saves about 522K per connection.
107 STACK_OF(SSL_COMP
) *ssl_comp_methods
;
109 ssl_comp_methods
= SSL_COMP_get_compression_methods();
110 n
= sk_SSL_COMP_num(ssl_comp_methods
);
113 (void) sk_SSL_COMP_pop(ssl_comp_methods
);
119 ngx_ssl_connection_index
= SSL_get_ex_new_index(0, NULL
, NULL
, NULL
, NULL
);
121 if (ngx_ssl_connection_index
== -1) {
122 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0, "SSL_get_ex_new_index() failed");
126 ngx_ssl_server_conf_index
= SSL_CTX_get_ex_new_index(0, NULL
, NULL
, NULL
,
128 if (ngx_ssl_server_conf_index
== -1) {
129 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0,
130 "SSL_CTX_get_ex_new_index() failed");
134 ngx_ssl_session_cache_index
= SSL_CTX_get_ex_new_index(0, NULL
, NULL
, NULL
,
136 if (ngx_ssl_session_cache_index
== -1) {
137 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0,
138 "SSL_CTX_get_ex_new_index() failed");
142 ngx_ssl_certificate_index
= SSL_CTX_get_ex_new_index(0, NULL
, NULL
, NULL
,
144 if (ngx_ssl_certificate_index
== -1) {
145 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0,
146 "SSL_CTX_get_ex_new_index() failed");
150 ngx_ssl_stapling_index
= SSL_CTX_get_ex_new_index(0, NULL
, NULL
, NULL
,
152 if (ngx_ssl_stapling_index
== -1) {
153 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0,
154 "SSL_CTX_get_ex_new_index() failed");
163 ngx_ssl_create(ngx_ssl_t
*ssl
, ngx_uint_t protocols
, void *data
)
165 ssl
->ctx
= SSL_CTX_new(SSLv23_method());
167 if (ssl
->ctx
== NULL
) {
168 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "SSL_CTX_new() failed");
172 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_server_conf_index
, data
) == 0) {
173 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
174 "SSL_CTX_set_ex_data() failed");
178 /* client side options */
180 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MICROSOFT_SESS_ID_BUG
);
181 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NETSCAPE_CHALLENGE_BUG
);
183 /* server side options */
185 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
);
186 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
);
188 /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
189 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MSIE_SSLV2_RSA_PADDING
);
191 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SSLEAY_080_CLIENT_DH_BUG
);
192 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_TLS_D5_BUG
);
193 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_TLS_BLOCK_PADDING_BUG
);
195 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
);
197 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SINGLE_DH_USE
);
199 if (!(protocols
& NGX_SSL_SSLv2
)) {
200 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NO_SSLv2
);
202 if (!(protocols
& NGX_SSL_SSLv3
)) {
203 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NO_SSLv3
);
205 if (!(protocols
& NGX_SSL_TLSv1
)) {
206 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NO_TLSv1
);
208 #ifdef SSL_OP_NO_TLSv1_1
209 if (!(protocols
& NGX_SSL_TLSv1_1
)) {
210 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NO_TLSv1_1
);
213 #ifdef SSL_OP_NO_TLSv1_2
214 if (!(protocols
& NGX_SSL_TLSv1_2
)) {
215 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NO_TLSv1_2
);
219 #ifdef SSL_OP_NO_COMPRESSION
220 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NO_COMPRESSION
);
223 #ifdef SSL_MODE_RELEASE_BUFFERS
224 SSL_CTX_set_mode(ssl
->ctx
, SSL_MODE_RELEASE_BUFFERS
);
227 SSL_CTX_set_read_ahead(ssl
->ctx
, 1);
229 SSL_CTX_set_info_callback(ssl
->ctx
, ngx_ssl_info_callback
);
236 ngx_ssl_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
243 if (ngx_conf_full_name(cf
->cycle
, cert
, 1) != NGX_OK
) {
248 * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
249 * allow to access certificate later from SSL_CTX, so we reimplement
253 bio
= BIO_new_file((char *) cert
->data
, "r");
255 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
256 "BIO_new_file(\"%s\") failed", cert
->data
);
260 x509
= PEM_read_bio_X509_AUX(bio
, NULL
, NULL
, NULL
);
262 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
263 "PEM_read_bio_X509_AUX(\"%s\") failed", cert
->data
);
268 if (SSL_CTX_use_certificate(ssl
->ctx
, x509
) == 0) {
269 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
270 "SSL_CTX_use_certificate(\"%s\") failed", cert
->data
);
276 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_certificate_index
, x509
)
279 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
280 "SSL_CTX_set_ex_data() failed");
286 /* read rest of the chain */
290 x509
= PEM_read_bio_X509(bio
, NULL
, NULL
, NULL
);
292 n
= ERR_peek_last_error();
294 if (ERR_GET_LIB(n
) == ERR_LIB_PEM
295 && ERR_GET_REASON(n
) == PEM_R_NO_START_LINE
)
302 /* some real error */
304 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
305 "PEM_read_bio_X509(\"%s\") failed", cert
->data
);
310 if (SSL_CTX_add_extra_chain_cert(ssl
->ctx
, x509
) == 0) {
311 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
312 "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
322 if (ngx_conf_full_name(cf
->cycle
, key
, 1) != NGX_OK
) {
326 if (SSL_CTX_use_PrivateKey_file(ssl
->ctx
, (char *) key
->data
,
330 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
331 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key
->data
);
340 ngx_ssl_client_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
343 STACK_OF(X509_NAME
) *list
;
345 SSL_CTX_set_verify(ssl
->ctx
, SSL_VERIFY_PEER
, ngx_http_ssl_verify_callback
);
347 SSL_CTX_set_verify_depth(ssl
->ctx
, depth
);
349 if (cert
->len
== 0) {
353 if (ngx_conf_full_name(cf
->cycle
, cert
, 1) != NGX_OK
) {
357 if (SSL_CTX_load_verify_locations(ssl
->ctx
, (char *) cert
->data
, NULL
)
360 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
361 "SSL_CTX_load_verify_locations(\"%s\") failed",
366 list
= SSL_load_client_CA_file((char *) cert
->data
);
369 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
370 "SSL_load_client_CA_file(\"%s\") failed", cert
->data
);
375 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
376 * always leaved an error in the error queue
381 SSL_CTX_set_client_CA_list(ssl
->ctx
, list
);
388 ngx_ssl_trusted_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
391 SSL_CTX_set_verify_depth(ssl
->ctx
, depth
);
393 if (cert
->len
== 0) {
397 if (ngx_conf_full_name(cf
->cycle
, cert
, 1) != NGX_OK
) {
401 if (SSL_CTX_load_verify_locations(ssl
->ctx
, (char *) cert
->data
, NULL
)
404 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
405 "SSL_CTX_load_verify_locations(\"%s\") failed",
415 ngx_ssl_crl(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*crl
)
424 if (ngx_conf_full_name(cf
->cycle
, crl
, 1) != NGX_OK
) {
428 store
= SSL_CTX_get_cert_store(ssl
->ctx
);
431 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
432 "SSL_CTX_get_cert_store() failed");
436 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file());
438 if (lookup
== NULL
) {
439 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
440 "X509_STORE_add_lookup() failed");
444 if (X509_LOOKUP_load_file(lookup
, (char *) crl
->data
, X509_FILETYPE_PEM
)
447 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
448 "X509_LOOKUP_load_file(\"%s\") failed", crl
->data
);
452 X509_STORE_set_flags(store
,
453 X509_V_FLAG_CRL_CHECK
|X509_V_FLAG_CRL_CHECK_ALL
);
460 ngx_http_ssl_verify_callback(int ok
, X509_STORE_CTX
*x509_store
)
463 char *subject
, *issuer
;
466 X509_NAME
*sname
, *iname
;
468 ngx_ssl_conn_t
*ssl_conn
;
470 ssl_conn
= X509_STORE_CTX_get_ex_data(x509_store
,
471 SSL_get_ex_data_X509_STORE_CTX_idx());
473 c
= ngx_ssl_get_connection(ssl_conn
);
475 cert
= X509_STORE_CTX_get_current_cert(x509_store
);
476 err
= X509_STORE_CTX_get_error(x509_store
);
477 depth
= X509_STORE_CTX_get_error_depth(x509_store
);
479 sname
= X509_get_subject_name(cert
);
480 subject
= sname
? X509_NAME_oneline(sname
, NULL
, 0) : "(none)";
482 iname
= X509_get_issuer_name(cert
);
483 issuer
= iname
? X509_NAME_oneline(iname
, NULL
, 0) : "(none)";
485 ngx_log_debug5(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
486 "verify:%d, error:%d, depth:%d, "
487 "subject:\"%s\",issuer: \"%s\"",
488 ok
, err
, depth
, subject
, issuer
);
491 OPENSSL_free(subject
);
495 OPENSSL_free(issuer
);
504 ngx_ssl_info_callback(const ngx_ssl_conn_t
*ssl_conn
, int where
, int ret
)
508 if (where
& SSL_CB_HANDSHAKE_START
) {
509 c
= ngx_ssl_get_connection((ngx_ssl_conn_t
*) ssl_conn
);
511 if (c
->ssl
->handshaked
) {
512 c
->ssl
->renegotiation
= 1;
513 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL renegotiation");
520 ngx_ssl_rsa512_key_callback(SSL
*ssl
, int is_export
, int key_length
)
524 if (key_length
== 512) {
526 key
= RSA_generate_key(512, RSA_F4
, NULL
, NULL
);
535 ngx_ssl_dhparam(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*file
)
541 * -----BEGIN DH PARAMETERS-----
542 * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
543 * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
544 * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
545 * -----END DH PARAMETERS-----
548 static unsigned char dh1024_p
[] = {
549 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
550 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
551 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
552 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
553 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
554 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
555 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
556 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
557 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
558 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
559 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
562 static unsigned char dh1024_g
[] = { 0x02 };
565 if (file
->len
== 0) {
569 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "DH_new() failed");
573 dh
->p
= BN_bin2bn(dh1024_p
, sizeof(dh1024_p
), NULL
);
574 dh
->g
= BN_bin2bn(dh1024_g
, sizeof(dh1024_g
), NULL
);
576 if (dh
->p
== NULL
|| dh
->g
== NULL
) {
577 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "BN_bin2bn() failed");
582 SSL_CTX_set_tmp_dh(ssl
->ctx
, dh
);
589 if (ngx_conf_full_name(cf
->cycle
, file
, 1) != NGX_OK
) {
593 bio
= BIO_new_file((char *) file
->data
, "r");
595 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
596 "BIO_new_file(\"%s\") failed", file
->data
);
600 dh
= PEM_read_bio_DHparams(bio
, NULL
, NULL
, NULL
);
602 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
603 "PEM_read_bio_DHparams(\"%s\") failed", file
->data
);
608 SSL_CTX_set_tmp_dh(ssl
->ctx
, dh
);
618 ngx_ssl_ecdh_curve(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*name
)
620 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
621 #ifndef OPENSSL_NO_ECDH
626 * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
627 * from RFC 4492 section 5.1.1, or explicitly described curves over
628 * binary fields. OpenSSL only supports the "named curves", which provide
629 * maximum interoperability.
632 nid
= OBJ_sn2nid((const char *) name
->data
);
634 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
635 "Unknown curve name \"%s\"", name
->data
);
639 ecdh
= EC_KEY_new_by_curve_name(nid
);
641 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
642 "Unable to create curve \"%s\"", name
->data
);
646 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SINGLE_ECDH_USE
);
648 SSL_CTX_set_tmp_ecdh(ssl
->ctx
, ecdh
);
659 ngx_ssl_create_connection(ngx_ssl_t
*ssl
, ngx_connection_t
*c
, ngx_uint_t flags
)
661 ngx_ssl_connection_t
*sc
;
663 sc
= ngx_pcalloc(c
->pool
, sizeof(ngx_ssl_connection_t
));
668 sc
->buffer
= ((flags
& NGX_SSL_BUFFER
) != 0);
670 sc
->connection
= SSL_new(ssl
->ctx
);
672 if (sc
->connection
== NULL
) {
673 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_new() failed");
677 if (SSL_set_fd(sc
->connection
, c
->fd
) == 0) {
678 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_fd() failed");
682 if (flags
& NGX_SSL_CLIENT
) {
683 SSL_set_connect_state(sc
->connection
);
686 SSL_set_accept_state(sc
->connection
);
689 if (SSL_set_ex_data(sc
->connection
, ngx_ssl_connection_index
, c
) == 0) {
690 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_ex_data() failed");
701 ngx_ssl_set_session(ngx_connection_t
*c
, ngx_ssl_session_t
*session
)
704 if (SSL_set_session(c
->ssl
->connection
, session
) == 0) {
705 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_session() failed");
715 ngx_ssl_handshake(ngx_connection_t
*c
)
720 ngx_ssl_clear_error(c
->log
);
722 n
= SSL_do_handshake(c
->ssl
->connection
);
724 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_do_handshake: %d", n
);
728 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
732 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
738 char buf
[129], *s
, *d
;
739 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
744 cipher
= SSL_get_current_cipher(c
->ssl
->connection
);
747 SSL_CIPHER_description(cipher
, &buf
[1], 128);
749 for (s
= &buf
[1], d
= buf
; *s
; s
++) {
750 if (*s
== ' ' && *d
== ' ') {
754 if (*s
== LF
|| *s
== CR
) {
767 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
768 "SSL: %s, cipher: \"%s\"",
769 SSL_get_version(c
->ssl
->connection
), &buf
[1]);
771 if (SSL_session_reused(c
->ssl
->connection
)) {
772 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
773 "SSL reused session");
777 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
778 "SSL no shared ciphers");
783 c
->ssl
->handshaked
= 1;
785 c
->recv
= ngx_ssl_recv
;
786 c
->send
= ngx_ssl_write
;
787 c
->recv_chain
= ngx_ssl_recv_chain
;
788 c
->send_chain
= ngx_ssl_send_chain
;
790 /* initial handshake done, disable renegotiation (CVE-2009-3555) */
791 if (c
->ssl
->connection
->s3
) {
792 c
->ssl
->connection
->s3
->flags
|= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
;
798 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
800 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
802 if (sslerr
== SSL_ERROR_WANT_READ
) {
804 c
->read
->handler
= ngx_ssl_handshake_handler
;
805 c
->write
->handler
= ngx_ssl_handshake_handler
;
807 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
811 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
818 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
820 c
->read
->handler
= ngx_ssl_handshake_handler
;
821 c
->write
->handler
= ngx_ssl_handshake_handler
;
823 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
827 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
834 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
836 c
->ssl
->no_wait_shutdown
= 1;
837 c
->ssl
->no_send_shutdown
= 1;
840 if (sslerr
== SSL_ERROR_ZERO_RETURN
|| ERR_peek_error() == 0) {
841 ngx_log_error(NGX_LOG_INFO
, c
->log
, err
,
842 "peer closed connection in SSL handshake");
849 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_do_handshake() failed");
856 ngx_ssl_handshake_handler(ngx_event_t
*ev
)
862 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
863 "SSL handshake handler: %d", ev
->write
);
870 if (ngx_ssl_handshake(c
) == NGX_AGAIN
) {
879 ngx_ssl_recv_chain(ngx_connection_t
*c
, ngx_chain_t
*cl
)
892 n
= ngx_ssl_recv(c
, last
, b
->end
- last
);
898 if (last
== b
->end
) {
914 if (n
== 0 || n
== NGX_ERROR
) {
927 ngx_ssl_recv(ngx_connection_t
*c
, u_char
*buf
, size_t size
)
931 if (c
->ssl
->last
== NGX_ERROR
) {
936 if (c
->ssl
->last
== NGX_DONE
) {
944 ngx_ssl_clear_error(c
->log
);
947 * SSL_read() may return data in parts, so try to read
948 * until SSL_read() would return no data
953 n
= SSL_read(c
->ssl
->connection
, buf
, size
);
955 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_read: %d", n
);
961 c
->ssl
->last
= ngx_ssl_handle_recv(c
, n
);
963 if (c
->ssl
->last
== NGX_OK
) {
980 switch (c
->ssl
->last
) {
1000 ngx_ssl_handle_recv(ngx_connection_t
*c
, int n
)
1005 if (c
->ssl
->renegotiation
) {
1007 * disable renegotiation (CVE-2009-3555):
1008 * OpenSSL (at least up to 0.9.8l) does not handle disabled
1009 * renegotiation gracefully, so drop connection here
1012 ngx_log_error(NGX_LOG_NOTICE
, c
->log
, 0, "SSL renegotiation disabled");
1014 while (ERR_peek_error()) {
1015 ngx_ssl_error(NGX_LOG_DEBUG
, c
->log
, 0,
1016 "ignoring stale global SSL error");
1021 c
->ssl
->no_wait_shutdown
= 1;
1022 c
->ssl
->no_send_shutdown
= 1;
1029 if (c
->ssl
->saved_write_handler
) {
1031 c
->write
->handler
= c
->ssl
->saved_write_handler
;
1032 c
->ssl
->saved_write_handler
= NULL
;
1033 c
->write
->ready
= 1;
1035 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
1039 ngx_post_event(c
->write
, &ngx_posted_events
);
1045 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
1047 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
1049 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
1051 if (sslerr
== SSL_ERROR_WANT_READ
) {
1056 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
1058 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1059 "peer started SSL renegotiation");
1061 c
->write
->ready
= 0;
1063 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
1068 * we do not set the timer because there is already the read event timer
1071 if (c
->ssl
->saved_write_handler
== NULL
) {
1072 c
->ssl
->saved_write_handler
= c
->write
->handler
;
1073 c
->write
->handler
= ngx_ssl_write_handler
;
1079 c
->ssl
->no_wait_shutdown
= 1;
1080 c
->ssl
->no_send_shutdown
= 1;
1082 if (sslerr
== SSL_ERROR_ZERO_RETURN
|| ERR_peek_error() == 0) {
1083 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1084 "peer shutdown SSL cleanly");
1088 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_read() failed");
1095 ngx_ssl_write_handler(ngx_event_t
*wev
)
1097 ngx_connection_t
*c
;
1101 c
->read
->handler(c
->read
);
1106 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
1107 * before the SSL_write() call to decrease a SSL overhead.
1109 * Besides for protocols such as HTTP it is possible to always buffer
1110 * the output to decrease a SSL overhead some more.
1114 ngx_ssl_send_chain(ngx_connection_t
*c
, ngx_chain_t
*in
, off_t limit
)
1121 if (!c
->ssl
->buffer
) {
1124 if (ngx_buf_special(in
->buf
)) {
1129 n
= ngx_ssl_write(c
, in
->buf
->pos
, in
->buf
->last
- in
->buf
->pos
);
1131 if (n
== NGX_ERROR
) {
1132 return NGX_CHAIN_ERROR
;
1135 if (n
== NGX_AGAIN
) {
1142 if (in
->buf
->pos
== in
->buf
->last
) {
1151 /* the maximum limit size is the maximum int32_t value - the page size */
1153 if (limit
== 0 || limit
> (off_t
) (NGX_MAX_INT32_VALUE
- ngx_pagesize
)) {
1154 limit
= NGX_MAX_INT32_VALUE
- ngx_pagesize
;
1160 buf
= ngx_create_temp_buf(c
->pool
, NGX_SSL_BUFSIZE
);
1162 return NGX_CHAIN_ERROR
;
1168 if (buf
->start
== NULL
) {
1169 buf
->start
= ngx_palloc(c
->pool
, NGX_SSL_BUFSIZE
);
1170 if (buf
->start
== NULL
) {
1171 return NGX_CHAIN_ERROR
;
1174 buf
->pos
= buf
->start
;
1175 buf
->last
= buf
->start
;
1176 buf
->end
= buf
->start
+ NGX_SSL_BUFSIZE
;
1179 send
= buf
->last
- buf
->pos
;
1180 flush
= (in
== NULL
) ? 1 : buf
->flush
;
1184 while (in
&& buf
->last
< buf
->end
&& send
< limit
) {
1185 if (in
->buf
->last_buf
|| in
->buf
->flush
) {
1189 if (ngx_buf_special(in
->buf
)) {
1194 size
= in
->buf
->last
- in
->buf
->pos
;
1196 if (size
> buf
->end
- buf
->last
) {
1197 size
= buf
->end
- buf
->last
;
1200 if (send
+ size
> limit
) {
1201 size
= (ssize_t
) (limit
- send
);
1204 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1205 "SSL buf copy: %d", size
);
1207 ngx_memcpy(buf
->last
, in
->buf
->pos
, size
);
1210 in
->buf
->pos
+= size
;
1213 if (in
->buf
->pos
== in
->buf
->last
) {
1218 if (!flush
&& send
< limit
&& buf
->last
< buf
->end
) {
1222 size
= buf
->last
- buf
->pos
;
1226 c
->buffered
&= ~NGX_SSL_BUFFERED
;
1230 n
= ngx_ssl_write(c
, buf
->pos
, size
);
1232 if (n
== NGX_ERROR
) {
1233 return NGX_CHAIN_ERROR
;
1236 if (n
== NGX_AGAIN
) {
1249 buf
->pos
= buf
->start
;
1250 buf
->last
= buf
->start
;
1252 if (in
== NULL
|| send
== limit
) {
1259 if (buf
->pos
< buf
->last
) {
1260 c
->buffered
|= NGX_SSL_BUFFERED
;
1263 c
->buffered
&= ~NGX_SSL_BUFFERED
;
1271 ngx_ssl_write(ngx_connection_t
*c
, u_char
*data
, size_t size
)
1276 ngx_ssl_clear_error(c
->log
);
1278 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL to write: %d", size
);
1280 n
= SSL_write(c
->ssl
->connection
, data
, size
);
1282 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_write: %d", n
);
1286 if (c
->ssl
->saved_read_handler
) {
1288 c
->read
->handler
= c
->ssl
->saved_read_handler
;
1289 c
->ssl
->saved_read_handler
= NULL
;
1292 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1296 ngx_post_event(c
->read
, &ngx_posted_events
);
1302 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
1304 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
1306 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
1308 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
1309 c
->write
->ready
= 0;
1313 if (sslerr
== SSL_ERROR_WANT_READ
) {
1315 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1316 "peer started SSL renegotiation");
1320 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1325 * we do not set the timer because there is already
1326 * the write event timer
1329 if (c
->ssl
->saved_read_handler
== NULL
) {
1330 c
->ssl
->saved_read_handler
= c
->read
->handler
;
1331 c
->read
->handler
= ngx_ssl_read_handler
;
1337 c
->ssl
->no_wait_shutdown
= 1;
1338 c
->ssl
->no_send_shutdown
= 1;
1339 c
->write
->error
= 1;
1341 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_write() failed");
1348 ngx_ssl_read_handler(ngx_event_t
*rev
)
1350 ngx_connection_t
*c
;
1354 c
->write
->handler(c
->write
);
1359 ngx_ssl_free_buffer(ngx_connection_t
*c
)
1361 if (c
->ssl
->buf
&& c
->ssl
->buf
->start
) {
1362 if (ngx_pfree(c
->pool
, c
->ssl
->buf
->start
) == NGX_OK
) {
1363 c
->ssl
->buf
->start
= NULL
;
1370 ngx_ssl_shutdown(ngx_connection_t
*c
)
1372 int n
, sslerr
, mode
;
1376 mode
= SSL_RECEIVED_SHUTDOWN
|SSL_SENT_SHUTDOWN
;
1377 SSL_set_quiet_shutdown(c
->ssl
->connection
, 1);
1380 mode
= SSL_get_shutdown(c
->ssl
->connection
);
1382 if (c
->ssl
->no_wait_shutdown
) {
1383 mode
|= SSL_RECEIVED_SHUTDOWN
;
1386 if (c
->ssl
->no_send_shutdown
) {
1387 mode
|= SSL_SENT_SHUTDOWN
;
1390 if (c
->ssl
->no_wait_shutdown
&& c
->ssl
->no_send_shutdown
) {
1391 SSL_set_quiet_shutdown(c
->ssl
->connection
, 1);
1395 SSL_set_shutdown(c
->ssl
->connection
, mode
);
1397 ngx_ssl_clear_error(c
->log
);
1399 n
= SSL_shutdown(c
->ssl
->connection
);
1401 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_shutdown: %d", n
);
1405 /* SSL_shutdown() never returns -1, on error it returns 0 */
1407 if (n
!= 1 && ERR_peek_error()) {
1408 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
1410 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1411 "SSL_get_error: %d", sslerr
);
1414 if (n
== 1 || sslerr
== 0 || sslerr
== SSL_ERROR_ZERO_RETURN
) {
1415 SSL_free(c
->ssl
->connection
);
1421 if (sslerr
== SSL_ERROR_WANT_READ
|| sslerr
== SSL_ERROR_WANT_WRITE
) {
1422 c
->read
->handler
= ngx_ssl_shutdown_handler
;
1423 c
->write
->handler
= ngx_ssl_shutdown_handler
;
1425 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1429 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
1433 if (sslerr
== SSL_ERROR_WANT_READ
) {
1434 ngx_add_timer(c
->read
, 30000);
1440 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
1442 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_shutdown() failed");
1444 SSL_free(c
->ssl
->connection
);
1452 ngx_ssl_shutdown_handler(ngx_event_t
*ev
)
1454 ngx_connection_t
*c
;
1455 ngx_connection_handler_pt handler
;
1458 handler
= c
->ssl
->handler
;
1464 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0, "SSL shutdown handler");
1466 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
1475 ngx_ssl_connection_error(ngx_connection_t
*c
, int sslerr
, ngx_err_t err
,
1481 level
= NGX_LOG_CRIT
;
1483 if (sslerr
== SSL_ERROR_SYSCALL
) {
1485 if (err
== NGX_ECONNRESET
1487 || err
== NGX_ENOTCONN
1488 || err
== NGX_ETIMEDOUT
1489 || err
== NGX_ECONNREFUSED
1490 || err
== NGX_ENETDOWN
1491 || err
== NGX_ENETUNREACH
1492 || err
== NGX_EHOSTDOWN
1493 || err
== NGX_EHOSTUNREACH
)
1495 switch (c
->log_error
) {
1497 case NGX_ERROR_IGNORE_ECONNRESET
:
1498 case NGX_ERROR_INFO
:
1499 level
= NGX_LOG_INFO
;
1503 level
= NGX_LOG_ERR
;
1511 } else if (sslerr
== SSL_ERROR_SSL
) {
1513 n
= ERR_GET_REASON(ERR_peek_error());
1515 /* handshake failures */
1516 if (n
== SSL_R_BAD_CHANGE_CIPHER_SPEC
/* 103 */
1517 || n
== SSL_R_BLOCK_CIPHER_PAD_IS_WRONG
/* 129 */
1518 || n
== SSL_R_DIGEST_CHECK_FAILED
/* 149 */
1519 || n
== SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST
/* 151 */
1520 || n
== SSL_R_EXCESSIVE_MESSAGE_SIZE
/* 152 */
1521 || n
== SSL_R_LENGTH_MISMATCH
/* 159 */
1522 || n
== SSL_R_NO_CIPHERS_PASSED
/* 182 */
1523 || n
== SSL_R_NO_CIPHERS_SPECIFIED
/* 183 */
1524 || n
== SSL_R_NO_COMPRESSION_SPECIFIED
/* 187 */
1525 || n
== SSL_R_NO_SHARED_CIPHER
/* 193 */
1526 || n
== SSL_R_RECORD_LENGTH_MISMATCH
/* 213 */
1527 #ifdef SSL_R_PARSE_TLSEXT
1528 || n
== SSL_R_PARSE_TLSEXT
/* 227 */
1530 || n
== SSL_R_UNEXPECTED_MESSAGE
/* 244 */
1531 || n
== SSL_R_UNEXPECTED_RECORD
/* 245 */
1532 || n
== SSL_R_UNKNOWN_ALERT_TYPE
/* 246 */
1533 || n
== SSL_R_UNKNOWN_PROTOCOL
/* 252 */
1534 || n
== SSL_R_WRONG_VERSION_NUMBER
/* 267 */
1535 || n
== SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC
/* 281 */
1536 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
1537 || n
== SSL_R_RENEGOTIATE_EXT_TOO_LONG
/* 335 */
1538 || n
== SSL_R_RENEGOTIATION_ENCODING_ERR
/* 336 */
1539 || n
== SSL_R_RENEGOTIATION_MISMATCH
/* 337 */
1541 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
1542 || n
== SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
/* 338 */
1544 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
1545 || n
== SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
/* 345 */
1547 || n
== 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
1548 || n
== SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE
/* 1010 */
1549 || n
== SSL_R_SSLV3_ALERT_BAD_RECORD_MAC
/* 1020 */
1550 || n
== SSL_R_TLSV1_ALERT_DECRYPTION_FAILED
/* 1021 */
1551 || n
== SSL_R_TLSV1_ALERT_RECORD_OVERFLOW
/* 1022 */
1552 || n
== SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE
/* 1030 */
1553 || n
== SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE
/* 1040 */
1554 || n
== SSL_R_SSLV3_ALERT_NO_CERTIFICATE
/* 1041 */
1555 || n
== SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
/* 1042 */
1556 || n
== SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE
/* 1043 */
1557 || n
== SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED
/* 1044 */
1558 || n
== SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED
/* 1045 */
1559 || n
== SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
/* 1046 */
1560 || n
== SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER
/* 1047 */
1561 || n
== SSL_R_TLSV1_ALERT_UNKNOWN_CA
/* 1048 */
1562 || n
== SSL_R_TLSV1_ALERT_ACCESS_DENIED
/* 1049 */
1563 || n
== SSL_R_TLSV1_ALERT_DECODE_ERROR
/* 1050 */
1564 || n
== SSL_R_TLSV1_ALERT_DECRYPT_ERROR
/* 1051 */
1565 || n
== SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION
/* 1060 */
1566 || n
== SSL_R_TLSV1_ALERT_PROTOCOL_VERSION
/* 1070 */
1567 || n
== SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY
/* 1071 */
1568 || n
== SSL_R_TLSV1_ALERT_INTERNAL_ERROR
/* 1080 */
1569 || n
== SSL_R_TLSV1_ALERT_USER_CANCELLED
/* 1090 */
1570 || n
== SSL_R_TLSV1_ALERT_NO_RENEGOTIATION
) /* 1100 */
1572 switch (c
->log_error
) {
1574 case NGX_ERROR_IGNORE_ECONNRESET
:
1575 case NGX_ERROR_INFO
:
1576 level
= NGX_LOG_INFO
;
1580 level
= NGX_LOG_ERR
;
1589 ngx_ssl_error(level
, c
->log
, err
, text
);
1594 ngx_ssl_clear_error(ngx_log_t
*log
)
1596 while (ERR_peek_error()) {
1597 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0, "ignoring stale global SSL error");
1605 ngx_ssl_error(ngx_uint_t level
, ngx_log_t
*log
, ngx_err_t err
, char *fmt
, ...)
1611 u_char errstr
[NGX_MAX_CONF_ERRSTR
];
1614 last
= errstr
+ NGX_MAX_CONF_ERRSTR
;
1616 va_start(args
, fmt
);
1617 p
= ngx_vslprintf(errstr
, last
- 1, fmt
, args
);
1620 p
= ngx_cpystrn(p
, (u_char
*) " (SSL:", last
- p
);
1624 n
= ERR_peek_error_line_data(NULL
, NULL
, &data
, &flags
);
1636 ERR_error_string_n(n
, (char *) p
, last
- p
);
1638 while (p
< last
&& *p
) {
1642 if (p
< last
&& *data
&& (flags
& ERR_TXT_STRING
)) {
1644 p
= ngx_cpystrn(p
, (u_char
*) data
, last
- p
);
1649 (void) ERR_get_error();
1652 ngx_log_error(level
, log
, err
, "%s)", errstr
);
1657 ngx_ssl_session_cache(ngx_ssl_t
*ssl
, ngx_str_t
*sess_ctx
,
1658 ssize_t builtin_session_cache
, ngx_shm_zone_t
*shm_zone
, time_t timeout
)
1662 if (builtin_session_cache
== NGX_SSL_NO_SCACHE
) {
1663 SSL_CTX_set_session_cache_mode(ssl
->ctx
, SSL_SESS_CACHE_OFF
);
1667 SSL_CTX_set_session_id_context(ssl
->ctx
, sess_ctx
->data
, sess_ctx
->len
);
1669 if (builtin_session_cache
== NGX_SSL_NONE_SCACHE
) {
1672 * If the server explicitly says that it does not support
1673 * session reuse (see SSL_SESS_CACHE_OFF above), then
1674 * Outlook Express fails to upload a sent email to
1675 * the Sent Items folder on the IMAP server via a separate IMAP
1676 * connection in the background. Therefore we have a special
1677 * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
1678 * where the server pretends that it supports session reuse,
1679 * but it does not actually store any session.
1682 SSL_CTX_set_session_cache_mode(ssl
->ctx
,
1683 SSL_SESS_CACHE_SERVER
1684 |SSL_SESS_CACHE_NO_AUTO_CLEAR
1685 |SSL_SESS_CACHE_NO_INTERNAL_STORE
);
1687 SSL_CTX_sess_set_cache_size(ssl
->ctx
, 1);
1692 cache_mode
= SSL_SESS_CACHE_SERVER
;
1694 if (shm_zone
&& builtin_session_cache
== NGX_SSL_NO_BUILTIN_SCACHE
) {
1695 cache_mode
|= SSL_SESS_CACHE_NO_INTERNAL
;
1698 SSL_CTX_set_session_cache_mode(ssl
->ctx
, cache_mode
);
1700 if (builtin_session_cache
!= NGX_SSL_NO_BUILTIN_SCACHE
) {
1702 if (builtin_session_cache
!= NGX_SSL_DFLT_BUILTIN_SCACHE
) {
1703 SSL_CTX_sess_set_cache_size(ssl
->ctx
, builtin_session_cache
);
1707 SSL_CTX_set_timeout(ssl
->ctx
, (long) timeout
);
1710 SSL_CTX_sess_set_new_cb(ssl
->ctx
, ngx_ssl_new_session
);
1711 SSL_CTX_sess_set_get_cb(ssl
->ctx
, ngx_ssl_get_cached_session
);
1712 SSL_CTX_sess_set_remove_cb(ssl
->ctx
, ngx_ssl_remove_session
);
1714 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_session_cache_index
, shm_zone
)
1717 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
1718 "SSL_CTX_set_ex_data() failed");
1728 ngx_ssl_session_cache_init(ngx_shm_zone_t
*shm_zone
, void *data
)
1731 ngx_slab_pool_t
*shpool
;
1732 ngx_ssl_session_cache_t
*cache
;
1735 shm_zone
->data
= data
;
1739 if (shm_zone
->shm
.exists
) {
1740 shm_zone
->data
= data
;
1744 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1746 cache
= ngx_slab_alloc(shpool
, sizeof(ngx_ssl_session_cache_t
));
1747 if (cache
== NULL
) {
1751 shpool
->data
= cache
;
1752 shm_zone
->data
= cache
;
1754 ngx_rbtree_init(&cache
->session_rbtree
, &cache
->sentinel
,
1755 ngx_ssl_session_rbtree_insert_value
);
1757 ngx_queue_init(&cache
->expire_queue
);
1759 len
= sizeof(" in SSL session shared cache \"\"") + shm_zone
->shm
.name
.len
;
1761 shpool
->log_ctx
= ngx_slab_alloc(shpool
, len
);
1762 if (shpool
->log_ctx
== NULL
) {
1766 ngx_sprintf(shpool
->log_ctx
, " in SSL session shared cache \"%V\"%Z",
1767 &shm_zone
->shm
.name
);
1774 * The length of the session id is 16 bytes for SSLv2 sessions and
1775 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1776 * It seems that the typical length of the external ASN1 representation
1777 * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1779 * Thus on 32-bit platforms we allocate separately an rbtree node,
1780 * a session id, and an ASN1 representation, they take accordingly
1781 * 64, 32, and 128 bytes.
1783 * On 64-bit platforms we allocate separately an rbtree node + session_id,
1784 * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1786 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1787 * so they are outside the code locked by shared pool mutex
1791 ngx_ssl_new_session(ngx_ssl_conn_t
*ssl_conn
, ngx_ssl_session_t
*sess
)
1794 u_char
*p
, *id
, *cached_sess
;
1797 ngx_shm_zone_t
*shm_zone
;
1798 ngx_connection_t
*c
;
1799 ngx_slab_pool_t
*shpool
;
1800 ngx_ssl_sess_id_t
*sess_id
;
1801 ngx_ssl_session_cache_t
*cache
;
1802 u_char buf
[NGX_SSL_MAX_SESSION_SIZE
];
1804 len
= i2d_SSL_SESSION(sess
, NULL
);
1806 /* do not cache too big session */
1808 if (len
> (int) NGX_SSL_MAX_SESSION_SIZE
) {
1813 i2d_SSL_SESSION(sess
, &p
);
1815 c
= ngx_ssl_get_connection(ssl_conn
);
1817 ssl_ctx
= SSL_get_SSL_CTX(ssl_conn
);
1818 shm_zone
= SSL_CTX_get_ex_data(ssl_ctx
, ngx_ssl_session_cache_index
);
1820 cache
= shm_zone
->data
;
1821 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1823 ngx_shmtx_lock(&shpool
->mutex
);
1825 /* drop one or two expired sessions */
1826 ngx_ssl_expire_sessions(cache
, shpool
, 1);
1828 cached_sess
= ngx_slab_alloc_locked(shpool
, len
);
1830 if (cached_sess
== NULL
) {
1832 /* drop the oldest non-expired session and try once more */
1834 ngx_ssl_expire_sessions(cache
, shpool
, 0);
1836 cached_sess
= ngx_slab_alloc_locked(shpool
, len
);
1838 if (cached_sess
== NULL
) {
1844 sess_id
= ngx_slab_alloc_locked(shpool
, sizeof(ngx_ssl_sess_id_t
));
1846 if (sess_id
== NULL
) {
1848 /* drop the oldest non-expired session and try once more */
1850 ngx_ssl_expire_sessions(cache
, shpool
, 0);
1852 sess_id
= ngx_slab_alloc_locked(shpool
, sizeof(ngx_ssl_sess_id_t
));
1854 if (sess_id
== NULL
) {
1859 #if (NGX_PTR_SIZE == 8)
1861 id
= sess_id
->sess_id
;
1865 id
= ngx_slab_alloc_locked(shpool
, sess
->session_id_length
);
1869 /* drop the oldest non-expired session and try once more */
1871 ngx_ssl_expire_sessions(cache
, shpool
, 0);
1873 id
= ngx_slab_alloc_locked(shpool
, sess
->session_id_length
);
1882 ngx_memcpy(cached_sess
, buf
, len
);
1884 ngx_memcpy(id
, sess
->session_id
, sess
->session_id_length
);
1886 hash
= ngx_crc32_short(sess
->session_id
, sess
->session_id_length
);
1888 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1889 "ssl new session: %08XD:%d:%d",
1890 hash
, sess
->session_id_length
, len
);
1892 sess_id
->node
.key
= hash
;
1893 sess_id
->node
.data
= (u_char
) sess
->session_id_length
;
1896 sess_id
->session
= cached_sess
;
1898 sess_id
->expire
= ngx_time() + SSL_CTX_get_timeout(ssl_ctx
);
1900 ngx_queue_insert_head(&cache
->expire_queue
, &sess_id
->queue
);
1902 ngx_rbtree_insert(&cache
->session_rbtree
, &sess_id
->node
);
1904 ngx_shmtx_unlock(&shpool
->mutex
);
1911 ngx_slab_free_locked(shpool
, cached_sess
);
1915 ngx_slab_free_locked(shpool
, sess_id
);
1918 ngx_shmtx_unlock(&shpool
->mutex
);
1920 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
1921 "could not add new SSL session to the session cache");
1927 static ngx_ssl_session_t
*
1928 ngx_ssl_get_cached_session(ngx_ssl_conn_t
*ssl_conn
, u_char
*id
, int len
,
1931 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1937 ngx_shm_zone_t
*shm_zone
;
1938 ngx_slab_pool_t
*shpool
;
1939 ngx_rbtree_node_t
*node
, *sentinel
;
1940 ngx_ssl_session_t
*sess
;
1941 ngx_ssl_sess_id_t
*sess_id
;
1942 ngx_ssl_session_cache_t
*cache
;
1943 u_char buf
[NGX_SSL_MAX_SESSION_SIZE
];
1945 ngx_connection_t
*c
;
1948 hash
= ngx_crc32_short(id
, (size_t) len
);
1952 c
= ngx_ssl_get_connection(ssl_conn
);
1954 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1955 "ssl get session: %08XD:%d", hash
, len
);
1958 shm_zone
= SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn
),
1959 ngx_ssl_session_cache_index
);
1961 cache
= shm_zone
->data
;
1965 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1967 ngx_shmtx_lock(&shpool
->mutex
);
1969 node
= cache
->session_rbtree
.root
;
1970 sentinel
= cache
->session_rbtree
.sentinel
;
1972 while (node
!= sentinel
) {
1974 if (hash
< node
->key
) {
1979 if (hash
> node
->key
) {
1984 /* hash == node->key */
1986 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1988 rc
= ngx_memn2cmp(id
, sess_id
->id
, (size_t) len
, (size_t) node
->data
);
1992 if (sess_id
->expire
> ngx_time()) {
1993 ngx_memcpy(buf
, sess_id
->session
, sess_id
->len
);
1995 ngx_shmtx_unlock(&shpool
->mutex
);
1998 sess
= d2i_SSL_SESSION(NULL
, &p
, sess_id
->len
);
2003 ngx_queue_remove(&sess_id
->queue
);
2005 ngx_rbtree_delete(&cache
->session_rbtree
, node
);
2007 ngx_slab_free_locked(shpool
, sess_id
->session
);
2008 #if (NGX_PTR_SIZE == 4)
2009 ngx_slab_free_locked(shpool
, sess_id
->id
);
2011 ngx_slab_free_locked(shpool
, sess_id
);
2018 node
= (rc
< 0) ? node
->left
: node
->right
;
2023 ngx_shmtx_unlock(&shpool
->mutex
);
2030 ngx_ssl_remove_cached_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
)
2032 SSL_CTX_remove_session(ssl
, sess
);
2034 ngx_ssl_remove_session(ssl
, sess
);
2039 ngx_ssl_remove_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
)
2045 ngx_shm_zone_t
*shm_zone
;
2046 ngx_slab_pool_t
*shpool
;
2047 ngx_rbtree_node_t
*node
, *sentinel
;
2048 ngx_ssl_sess_id_t
*sess_id
;
2049 ngx_ssl_session_cache_t
*cache
;
2051 shm_zone
= SSL_CTX_get_ex_data(ssl
, ngx_ssl_session_cache_index
);
2053 if (shm_zone
== NULL
) {
2057 cache
= shm_zone
->data
;
2059 id
= sess
->session_id
;
2060 len
= (size_t) sess
->session_id_length
;
2062 hash
= ngx_crc32_short(id
, len
);
2064 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ngx_cycle
->log
, 0,
2065 "ssl remove session: %08XD:%uz", hash
, len
);
2067 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
2069 ngx_shmtx_lock(&shpool
->mutex
);
2071 node
= cache
->session_rbtree
.root
;
2072 sentinel
= cache
->session_rbtree
.sentinel
;
2074 while (node
!= sentinel
) {
2076 if (hash
< node
->key
) {
2081 if (hash
> node
->key
) {
2086 /* hash == node->key */
2088 sess_id
= (ngx_ssl_sess_id_t
*) node
;
2090 rc
= ngx_memn2cmp(id
, sess_id
->id
, len
, (size_t) node
->data
);
2094 ngx_queue_remove(&sess_id
->queue
);
2096 ngx_rbtree_delete(&cache
->session_rbtree
, node
);
2098 ngx_slab_free_locked(shpool
, sess_id
->session
);
2099 #if (NGX_PTR_SIZE == 4)
2100 ngx_slab_free_locked(shpool
, sess_id
->id
);
2102 ngx_slab_free_locked(shpool
, sess_id
);
2107 node
= (rc
< 0) ? node
->left
: node
->right
;
2112 ngx_shmtx_unlock(&shpool
->mutex
);
2117 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t
*cache
,
2118 ngx_slab_pool_t
*shpool
, ngx_uint_t n
)
2122 ngx_ssl_sess_id_t
*sess_id
;
2128 if (ngx_queue_empty(&cache
->expire_queue
)) {
2132 q
= ngx_queue_last(&cache
->expire_queue
);
2134 sess_id
= ngx_queue_data(q
, ngx_ssl_sess_id_t
, queue
);
2136 if (n
++ != 0 && sess_id
->expire
> now
) {
2140 ngx_queue_remove(q
);
2142 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ngx_cycle
->log
, 0,
2143 "expire session: %08Xi", sess_id
->node
.key
);
2145 ngx_rbtree_delete(&cache
->session_rbtree
, &sess_id
->node
);
2147 ngx_slab_free_locked(shpool
, sess_id
->session
);
2148 #if (NGX_PTR_SIZE == 4)
2149 ngx_slab_free_locked(shpool
, sess_id
->id
);
2151 ngx_slab_free_locked(shpool
, sess_id
);
2157 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
2158 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
)
2160 ngx_rbtree_node_t
**p
;
2161 ngx_ssl_sess_id_t
*sess_id
, *sess_id_temp
;
2165 if (node
->key
< temp
->key
) {
2169 } else if (node
->key
> temp
->key
) {
2173 } else { /* node->key == temp->key */
2175 sess_id
= (ngx_ssl_sess_id_t
*) node
;
2176 sess_id_temp
= (ngx_ssl_sess_id_t
*) temp
;
2178 p
= (ngx_memn2cmp(sess_id
->id
, sess_id_temp
->id
,
2179 (size_t) node
->data
, (size_t) temp
->data
)
2180 < 0) ? &temp
->left
: &temp
->right
;
2183 if (*p
== sentinel
) {
2191 node
->parent
= temp
;
2192 node
->left
= sentinel
;
2193 node
->right
= sentinel
;
2199 ngx_ssl_cleanup_ctx(void *data
)
2201 ngx_ssl_t
*ssl
= data
;
2203 SSL_CTX_free(ssl
->ctx
);
2208 ngx_ssl_get_protocol(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2210 s
->data
= (u_char
*) SSL_get_version(c
->ssl
->connection
);
2216 ngx_ssl_get_cipher_name(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2218 s
->data
= (u_char
*) SSL_get_cipher_name(c
->ssl
->connection
);
2224 ngx_ssl_get_session_id(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2230 sess
= SSL_get0_session(c
->ssl
->connection
);
2232 len
= i2d_SSL_SESSION(sess
, NULL
);
2234 buf
= ngx_alloc(len
, c
->log
);
2240 s
->data
= ngx_pnalloc(pool
, 2 * len
);
2241 if (s
->data
== NULL
) {
2247 i2d_SSL_SESSION(sess
, &p
);
2249 ngx_hex_dump(s
->data
, buf
, len
);
2258 ngx_ssl_get_raw_certificate(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2266 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2271 bio
= BIO_new(BIO_s_mem());
2273 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "BIO_new() failed");
2278 if (PEM_write_bio_X509(bio
, cert
) == 0) {
2279 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "PEM_write_bio_X509() failed");
2283 len
= BIO_pending(bio
);
2286 s
->data
= ngx_pnalloc(pool
, len
);
2287 if (s
->data
== NULL
) {
2291 BIO_read(bio
, s
->data
, len
);
2308 ngx_ssl_get_certificate(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2315 if (ngx_ssl_get_raw_certificate(c
, pool
, &cert
) != NGX_OK
) {
2319 if (cert
.len
== 0) {
2326 for (i
= 0; i
< cert
.len
- 1; i
++) {
2327 if (cert
.data
[i
] == LF
) {
2333 s
->data
= ngx_pnalloc(pool
, len
);
2334 if (s
->data
== NULL
) {
2340 for (i
= 0; i
< cert
.len
- 1; i
++) {
2341 *p
++ = cert
.data
[i
];
2342 if (cert
.data
[i
] == LF
) {
2352 ngx_ssl_get_subject_dn(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2361 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2366 name
= X509_get_subject_name(cert
);
2372 p
= X509_NAME_oneline(name
, NULL
, 0);
2374 for (len
= 0; p
[len
]; len
++) { /* void */ }
2377 s
->data
= ngx_pnalloc(pool
, len
);
2378 if (s
->data
== NULL
) {
2384 ngx_memcpy(s
->data
, p
, len
);
2394 ngx_ssl_get_issuer_dn(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2403 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2408 name
= X509_get_issuer_name(cert
);
2414 p
= X509_NAME_oneline(name
, NULL
, 0);
2416 for (len
= 0; p
[len
]; len
++) { /* void */ }
2419 s
->data
= ngx_pnalloc(pool
, len
);
2420 if (s
->data
== NULL
) {
2426 ngx_memcpy(s
->data
, p
, len
);
2436 ngx_ssl_get_serial_number(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2444 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2449 bio
= BIO_new(BIO_s_mem());
2455 i2a_ASN1_INTEGER(bio
, X509_get_serialNumber(cert
));
2456 len
= BIO_pending(bio
);
2459 s
->data
= ngx_pnalloc(pool
, len
);
2460 if (s
->data
== NULL
) {
2466 BIO_read(bio
, s
->data
, len
);
2475 ngx_ssl_get_client_verify(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2479 if (SSL_get_verify_result(c
->ssl
->connection
) != X509_V_OK
) {
2480 ngx_str_set(s
, "FAILED");
2484 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2487 ngx_str_set(s
, "SUCCESS");
2490 ngx_str_set(s
, "NONE");
2500 ngx_openssl_create_conf(ngx_cycle_t
*cycle
)
2502 ngx_openssl_conf_t
*oscf
;
2504 oscf
= ngx_pcalloc(cycle
->pool
, sizeof(ngx_openssl_conf_t
));
2510 * set by ngx_pcalloc():
2520 ngx_openssl_engine(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2522 ngx_openssl_conf_t
*oscf
= conf
;
2528 return "is duplicate";
2533 value
= cf
->args
->elts
;
2535 engine
= ENGINE_by_id((const char *) value
[1].data
);
2537 if (engine
== NULL
) {
2538 ngx_ssl_error(NGX_LOG_WARN
, cf
->log
, 0,
2539 "ENGINE_by_id(\"%V\") failed", &value
[1]);
2540 return NGX_CONF_ERROR
;
2543 if (ENGINE_set_default(engine
, ENGINE_METHOD_ALL
) == 0) {
2544 ngx_ssl_error(NGX_LOG_WARN
, cf
->log
, 0,
2545 "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
2548 ENGINE_free(engine
);
2550 return NGX_CONF_ERROR
;
2553 ENGINE_free(engine
);
2560 ngx_openssl_exit(ngx_cycle_t
*cycle
)