3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
13 ngx_uint_t engine
; /* unsigned engine:1; */
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
,
20 static void ngx_ssl_handshake_handler(ngx_event_t
*ev
);
21 static ngx_int_t
ngx_ssl_handle_recv(ngx_connection_t
*c
, int n
);
22 static void ngx_ssl_write_handler(ngx_event_t
*wev
);
23 static void ngx_ssl_read_handler(ngx_event_t
*rev
);
24 static void ngx_ssl_shutdown_handler(ngx_event_t
*ev
);
25 static void ngx_ssl_connection_error(ngx_connection_t
*c
, int sslerr
,
26 ngx_err_t err
, char *text
);
27 static void ngx_ssl_clear_error(ngx_log_t
*log
);
29 static ngx_int_t
ngx_ssl_session_cache_init(ngx_shm_zone_t
*shm_zone
,
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 static long ngx_ssl_protocols
[] = {
83 SSL_OP_NO_SSLv2
|SSL_OP_NO_SSLv3
|SSL_OP_NO_TLSv1
,
84 SSL_OP_NO_SSLv3
|SSL_OP_NO_TLSv1
,
85 SSL_OP_NO_SSLv2
|SSL_OP_NO_TLSv1
,
87 SSL_OP_NO_SSLv2
|SSL_OP_NO_SSLv3
,
94 int ngx_ssl_connection_index
;
95 int ngx_ssl_server_conf_index
;
96 int ngx_ssl_session_cache_index
;
100 ngx_ssl_init(ngx_log_t
*log
)
102 OPENSSL_config(NULL
);
105 SSL_load_error_strings();
107 ENGINE_load_builtin_engines();
109 OpenSSL_add_all_algorithms();
111 ngx_ssl_connection_index
= SSL_get_ex_new_index(0, NULL
, NULL
, NULL
, NULL
);
113 if (ngx_ssl_connection_index
== -1) {
114 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0, "SSL_get_ex_new_index() failed");
118 ngx_ssl_server_conf_index
= SSL_CTX_get_ex_new_index(0, NULL
, NULL
, NULL
,
120 if (ngx_ssl_server_conf_index
== -1) {
121 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0,
122 "SSL_CTX_get_ex_new_index() failed");
126 ngx_ssl_session_cache_index
= SSL_CTX_get_ex_new_index(0, NULL
, NULL
, NULL
,
128 if (ngx_ssl_session_cache_index
== -1) {
129 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0,
130 "SSL_CTX_get_ex_new_index() failed");
139 ngx_ssl_create(ngx_ssl_t
*ssl
, ngx_uint_t protocols
, void *data
)
141 ssl
->ctx
= SSL_CTX_new(SSLv23_method());
143 if (ssl
->ctx
== NULL
) {
144 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "SSL_CTX_new() failed");
148 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_server_conf_index
, data
) == 0) {
149 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
150 "SSL_CTX_set_ex_data() failed");
154 /* client side options */
156 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MICROSOFT_SESS_ID_BUG
);
157 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NETSCAPE_CHALLENGE_BUG
);
158 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
);
160 /* server side options */
162 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
);
163 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
);
165 /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
166 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MSIE_SSLV2_RSA_PADDING
);
168 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SSLEAY_080_CLIENT_DH_BUG
);
169 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_TLS_D5_BUG
);
170 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_TLS_BLOCK_PADDING_BUG
);
172 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
);
174 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SINGLE_DH_USE
);
176 if (ngx_ssl_protocols
[protocols
>> 1] != 0) {
177 SSL_CTX_set_options(ssl
->ctx
, ngx_ssl_protocols
[protocols
>> 1]);
180 SSL_CTX_set_read_ahead(ssl
->ctx
, 1);
182 SSL_CTX_set_info_callback(ssl
->ctx
, ngx_ssl_info_callback
);
189 ngx_ssl_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
192 if (ngx_conf_full_name(cf
->cycle
, cert
, 1) != NGX_OK
) {
196 if (SSL_CTX_use_certificate_chain_file(ssl
->ctx
, (char *) cert
->data
)
199 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
200 "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
205 if (ngx_conf_full_name(cf
->cycle
, key
, 1) != NGX_OK
) {
209 if (SSL_CTX_use_PrivateKey_file(ssl
->ctx
, (char *) key
->data
,
213 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
214 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key
->data
);
223 ngx_ssl_client_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
226 STACK_OF(X509_NAME
) *list
;
228 SSL_CTX_set_verify(ssl
->ctx
, SSL_VERIFY_PEER
, ngx_http_ssl_verify_callback
);
230 SSL_CTX_set_verify_depth(ssl
->ctx
, depth
);
232 if (cert
->len
== 0) {
236 if (ngx_conf_full_name(cf
->cycle
, cert
, 1) != NGX_OK
) {
240 if (SSL_CTX_load_verify_locations(ssl
->ctx
, (char *) cert
->data
, NULL
)
243 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
244 "SSL_CTX_load_verify_locations(\"%s\") failed",
249 list
= SSL_load_client_CA_file((char *) cert
->data
);
252 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
253 "SSL_load_client_CA_file(\"%s\") failed", cert
->data
);
258 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
259 * always leaved an error in the error queue
264 SSL_CTX_set_client_CA_list(ssl
->ctx
, list
);
271 ngx_ssl_crl(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*crl
)
280 if (ngx_conf_full_name(cf
->cycle
, crl
, 1) != NGX_OK
) {
284 store
= SSL_CTX_get_cert_store(ssl
->ctx
);
287 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
288 "SSL_CTX_get_cert_store() failed");
292 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file());
294 if (lookup
== NULL
) {
295 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
296 "X509_STORE_add_lookup() failed");
300 if (X509_LOOKUP_load_file(lookup
, (char *) crl
->data
, X509_FILETYPE_PEM
)
303 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
304 "X509_LOOKUP_load_file(\"%s\") failed", crl
->data
);
308 X509_STORE_set_flags(store
,
309 X509_V_FLAG_CRL_CHECK
|X509_V_FLAG_CRL_CHECK_ALL
);
316 ngx_http_ssl_verify_callback(int ok
, X509_STORE_CTX
*x509_store
)
319 char *subject
, *issuer
;
322 X509_NAME
*sname
, *iname
;
324 ngx_ssl_conn_t
*ssl_conn
;
326 ssl_conn
= X509_STORE_CTX_get_ex_data(x509_store
,
327 SSL_get_ex_data_X509_STORE_CTX_idx());
329 c
= ngx_ssl_get_connection(ssl_conn
);
331 cert
= X509_STORE_CTX_get_current_cert(x509_store
);
332 err
= X509_STORE_CTX_get_error(x509_store
);
333 depth
= X509_STORE_CTX_get_error_depth(x509_store
);
335 sname
= X509_get_subject_name(cert
);
336 subject
= sname
? X509_NAME_oneline(sname
, NULL
, 0) : "(none)";
338 iname
= X509_get_issuer_name(cert
);
339 issuer
= iname
? X509_NAME_oneline(iname
, NULL
, 0) : "(none)";
341 ngx_log_debug5(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
342 "verify:%d, error:%d, depth:%d, "
343 "subject:\"%s\",issuer: \"%s\"",
344 ok
, err
, depth
, subject
, issuer
);
347 OPENSSL_free(subject
);
351 OPENSSL_free(issuer
);
360 ngx_ssl_info_callback(const ngx_ssl_conn_t
*ssl_conn
, int where
, int ret
)
364 if (where
& SSL_CB_HANDSHAKE_START
) {
365 c
= ngx_ssl_get_connection((ngx_ssl_conn_t
*) ssl_conn
);
367 if (c
->ssl
->handshaked
) {
368 c
->ssl
->renegotiation
= 1;
369 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL renegotiation");
376 ngx_ssl_generate_rsa512_key(ngx_ssl_t
*ssl
)
380 if (SSL_CTX_need_tmp_RSA(ssl
->ctx
) == 0) {
384 key
= RSA_generate_key(512, RSA_F4
, NULL
, NULL
);
387 SSL_CTX_set_tmp_rsa(ssl
->ctx
, key
);
394 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "RSA_generate_key(512) failed");
401 ngx_ssl_dhparam(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*file
)
407 * -----BEGIN DH PARAMETERS-----
408 * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
409 * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
410 * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
411 * -----END DH PARAMETERS-----
414 static unsigned char dh1024_p
[] = {
415 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
416 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
417 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
418 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
419 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
420 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
421 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
422 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
423 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
424 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
425 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
428 static unsigned char dh1024_g
[] = { 0x02 };
431 if (file
->len
== 0) {
435 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "DH_new() failed");
439 dh
->p
= BN_bin2bn(dh1024_p
, sizeof(dh1024_p
), NULL
);
440 dh
->g
= BN_bin2bn(dh1024_g
, sizeof(dh1024_g
), NULL
);
442 if (dh
->p
== NULL
|| dh
->g
== NULL
) {
443 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "BN_bin2bn() failed");
448 SSL_CTX_set_tmp_dh(ssl
->ctx
, dh
);
455 if (ngx_conf_full_name(cf
->cycle
, file
, 1) != NGX_OK
) {
459 bio
= BIO_new_file((char *) file
->data
, "r");
461 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
462 "BIO_new_file(\"%s\") failed", file
->data
);
466 dh
= PEM_read_bio_DHparams(bio
, NULL
, NULL
, NULL
);
468 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
469 "PEM_read_bio_DHparams(\"%s\") failed", file
->data
);
474 SSL_CTX_set_tmp_dh(ssl
->ctx
, dh
);
484 ngx_ssl_create_connection(ngx_ssl_t
*ssl
, ngx_connection_t
*c
, ngx_uint_t flags
)
486 ngx_ssl_connection_t
*sc
;
488 sc
= ngx_pcalloc(c
->pool
, sizeof(ngx_ssl_connection_t
));
493 sc
->buffer
= ((flags
& NGX_SSL_BUFFER
) != 0);
495 sc
->connection
= SSL_new(ssl
->ctx
);
497 if (sc
->connection
== NULL
) {
498 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_new() failed");
502 if (SSL_set_fd(sc
->connection
, c
->fd
) == 0) {
503 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_fd() failed");
507 if (flags
& NGX_SSL_CLIENT
) {
508 SSL_set_connect_state(sc
->connection
);
511 SSL_set_accept_state(sc
->connection
);
514 if (SSL_set_ex_data(sc
->connection
, ngx_ssl_connection_index
, c
) == 0) {
515 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_ex_data() failed");
526 ngx_ssl_set_session(ngx_connection_t
*c
, ngx_ssl_session_t
*session
)
529 if (SSL_set_session(c
->ssl
->connection
, session
) == 0) {
530 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_session() failed");
540 ngx_ssl_handshake(ngx_connection_t
*c
)
545 ngx_ssl_clear_error(c
->log
);
547 n
= SSL_do_handshake(c
->ssl
->connection
);
549 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_do_handshake: %d", n
);
553 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
557 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
563 char buf
[129], *s
, *d
;
564 #if OPENSSL_VERSION_NUMBER >= 0x1000000fL
569 cipher
= SSL_get_current_cipher(c
->ssl
->connection
);
572 SSL_CIPHER_description(cipher
, &buf
[1], 128);
574 for (s
= &buf
[1], d
= buf
; *s
; s
++) {
575 if (*s
== ' ' && *d
== ' ') {
579 if (*s
== LF
|| *s
== CR
) {
592 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
593 "SSL: %s, cipher: \"%s\"",
594 SSL_get_version(c
->ssl
->connection
), &buf
[1]);
596 if (SSL_session_reused(c
->ssl
->connection
)) {
597 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
598 "SSL reused session");
602 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
603 "SSL no shared ciphers");
608 c
->ssl
->handshaked
= 1;
610 c
->recv
= ngx_ssl_recv
;
611 c
->send
= ngx_ssl_write
;
612 c
->recv_chain
= ngx_ssl_recv_chain
;
613 c
->send_chain
= ngx_ssl_send_chain
;
615 /* initial handshake done, disable renegotiation (CVE-2009-3555) */
616 if (c
->ssl
->connection
->s3
) {
617 c
->ssl
->connection
->s3
->flags
|= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
;
623 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
625 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
627 if (sslerr
== SSL_ERROR_WANT_READ
) {
629 c
->read
->handler
= ngx_ssl_handshake_handler
;
630 c
->write
->handler
= ngx_ssl_handshake_handler
;
632 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
639 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
641 c
->read
->handler
= ngx_ssl_handshake_handler
;
642 c
->write
->handler
= ngx_ssl_handshake_handler
;
644 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
651 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
653 c
->ssl
->no_wait_shutdown
= 1;
654 c
->ssl
->no_send_shutdown
= 1;
657 if (sslerr
== SSL_ERROR_ZERO_RETURN
|| ERR_peek_error() == 0) {
658 ngx_log_error(NGX_LOG_INFO
, c
->log
, err
,
659 "peer closed connection in SSL handshake");
666 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_do_handshake() failed");
673 ngx_ssl_handshake_handler(ngx_event_t
*ev
)
679 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
680 "SSL handshake handler: %d", ev
->write
);
687 if (ngx_ssl_handshake(c
) == NGX_AGAIN
) {
696 ngx_ssl_recv_chain(ngx_connection_t
*c
, ngx_chain_t
*cl
)
709 n
= ngx_ssl_recv(c
, last
, b
->end
- last
);
715 if (last
== b
->end
) {
731 if (n
== 0 || n
== NGX_ERROR
) {
744 ngx_ssl_recv(ngx_connection_t
*c
, u_char
*buf
, size_t size
)
748 if (c
->ssl
->last
== NGX_ERROR
) {
753 if (c
->ssl
->last
== NGX_DONE
) {
761 ngx_ssl_clear_error(c
->log
);
764 * SSL_read() may return data in parts, so try to read
765 * until SSL_read() would return no data
770 n
= SSL_read(c
->ssl
->connection
, buf
, size
);
772 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_read: %d", n
);
778 c
->ssl
->last
= ngx_ssl_handle_recv(c
, n
);
780 if (c
->ssl
->last
== NGX_OK
) {
797 switch (c
->ssl
->last
) {
817 ngx_ssl_handle_recv(ngx_connection_t
*c
, int n
)
822 if (c
->ssl
->renegotiation
) {
824 * disable renegotiation (CVE-2009-3555):
825 * OpenSSL (at least up to 0.9.8l) does not handle disabled
826 * renegotiation gracefully, so drop connection here
829 ngx_log_error(NGX_LOG_NOTICE
, c
->log
, 0, "SSL renegotiation disabled");
831 c
->ssl
->no_wait_shutdown
= 1;
832 c
->ssl
->no_send_shutdown
= 1;
839 if (c
->ssl
->saved_write_handler
) {
841 c
->write
->handler
= c
->ssl
->saved_write_handler
;
842 c
->ssl
->saved_write_handler
= NULL
;
845 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
849 ngx_post_event(c
->write
, &ngx_posted_events
);
855 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
857 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
859 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
861 if (sslerr
== SSL_ERROR_WANT_READ
) {
866 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
868 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
869 "peer started SSL renegotiation");
873 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
878 * we do not set the timer because there is already the read event timer
881 if (c
->ssl
->saved_write_handler
== NULL
) {
882 c
->ssl
->saved_write_handler
= c
->write
->handler
;
883 c
->write
->handler
= ngx_ssl_write_handler
;
889 c
->ssl
->no_wait_shutdown
= 1;
890 c
->ssl
->no_send_shutdown
= 1;
892 if (sslerr
== SSL_ERROR_ZERO_RETURN
|| ERR_peek_error() == 0) {
893 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
894 "peer shutdown SSL cleanly");
898 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_read() failed");
905 ngx_ssl_write_handler(ngx_event_t
*wev
)
911 c
->read
->handler(c
->read
);
916 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
917 * before the SSL_write() call to decrease a SSL overhead.
919 * Besides for protocols such as HTTP it is possible to always buffer
920 * the output to decrease a SSL overhead some more.
924 ngx_ssl_send_chain(ngx_connection_t
*c
, ngx_chain_t
*in
, off_t limit
)
931 if (!c
->ssl
->buffer
) {
934 if (ngx_buf_special(in
->buf
)) {
939 n
= ngx_ssl_write(c
, in
->buf
->pos
, in
->buf
->last
- in
->buf
->pos
);
941 if (n
== NGX_ERROR
) {
942 return NGX_CHAIN_ERROR
;
945 if (n
== NGX_AGAIN
) {
946 c
->buffered
|= NGX_SSL_BUFFERED
;
952 if (in
->buf
->pos
== in
->buf
->last
) {
961 /* the maximum limit size is the maximum uint32_t value - the page size */
963 if (limit
== 0 || limit
> (off_t
) (NGX_MAX_UINT32_VALUE
- ngx_pagesize
)) {
964 limit
= NGX_MAX_UINT32_VALUE
- ngx_pagesize
;
970 buf
= ngx_create_temp_buf(c
->pool
, NGX_SSL_BUFSIZE
);
972 return NGX_CHAIN_ERROR
;
978 if (buf
->start
== NULL
) {
979 buf
->start
= ngx_palloc(c
->pool
, NGX_SSL_BUFSIZE
);
980 if (buf
->start
== NULL
) {
981 return NGX_CHAIN_ERROR
;
984 buf
->pos
= buf
->start
;
985 buf
->last
= buf
->start
;
986 buf
->end
= buf
->start
+ NGX_SSL_BUFSIZE
;
990 flush
= (in
== NULL
) ? 1 : 0;
994 while (in
&& buf
->last
< buf
->end
&& send
< limit
) {
995 if (in
->buf
->last_buf
|| in
->buf
->flush
) {
999 if (ngx_buf_special(in
->buf
)) {
1004 size
= in
->buf
->last
- in
->buf
->pos
;
1006 if (size
> buf
->end
- buf
->last
) {
1007 size
= buf
->end
- buf
->last
;
1010 if (send
+ size
> limit
) {
1011 size
= (ssize_t
) (limit
- send
);
1015 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1016 "SSL buf copy: %d", size
);
1018 ngx_memcpy(buf
->last
, in
->buf
->pos
, size
);
1021 in
->buf
->pos
+= size
;
1024 if (in
->buf
->pos
== in
->buf
->last
) {
1029 size
= buf
->last
- buf
->pos
;
1031 if (!flush
&& buf
->last
< buf
->end
&& c
->ssl
->buffer
) {
1035 n
= ngx_ssl_write(c
, buf
->pos
, size
);
1037 if (n
== NGX_ERROR
) {
1038 return NGX_CHAIN_ERROR
;
1041 if (n
== NGX_AGAIN
) {
1042 c
->buffered
|= NGX_SSL_BUFFERED
;
1053 if (buf
->pos
== buf
->last
) {
1054 buf
->pos
= buf
->start
;
1055 buf
->last
= buf
->start
;
1058 if (in
== NULL
|| send
== limit
) {
1063 if (buf
->pos
< buf
->last
) {
1064 c
->buffered
|= NGX_SSL_BUFFERED
;
1067 c
->buffered
&= ~NGX_SSL_BUFFERED
;
1075 ngx_ssl_write(ngx_connection_t
*c
, u_char
*data
, size_t size
)
1080 ngx_ssl_clear_error(c
->log
);
1082 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL to write: %d", size
);
1084 n
= SSL_write(c
->ssl
->connection
, data
, size
);
1086 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_write: %d", n
);
1090 if (c
->ssl
->saved_read_handler
) {
1092 c
->read
->handler
= c
->ssl
->saved_read_handler
;
1093 c
->ssl
->saved_read_handler
= NULL
;
1096 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1100 ngx_post_event(c
->read
, &ngx_posted_events
);
1106 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
1108 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
1110 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
1112 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
1113 c
->write
->ready
= 0;
1117 if (sslerr
== SSL_ERROR_WANT_READ
) {
1119 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1120 "peer started SSL renegotiation");
1124 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1129 * we do not set the timer because there is already
1130 * the write event timer
1133 if (c
->ssl
->saved_read_handler
== NULL
) {
1134 c
->ssl
->saved_read_handler
= c
->read
->handler
;
1135 c
->read
->handler
= ngx_ssl_read_handler
;
1141 c
->ssl
->no_wait_shutdown
= 1;
1142 c
->ssl
->no_send_shutdown
= 1;
1143 c
->write
->error
= 1;
1145 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_write() failed");
1152 ngx_ssl_read_handler(ngx_event_t
*rev
)
1154 ngx_connection_t
*c
;
1158 c
->write
->handler(c
->write
);
1163 ngx_ssl_free_buffer(ngx_connection_t
*c
)
1165 if (c
->ssl
->buf
&& c
->ssl
->buf
->start
) {
1166 if (ngx_pfree(c
->pool
, c
->ssl
->buf
->start
) == NGX_OK
) {
1167 c
->ssl
->buf
->start
= NULL
;
1174 ngx_ssl_shutdown(ngx_connection_t
*c
)
1176 int n
, sslerr
, mode
;
1180 mode
= SSL_RECEIVED_SHUTDOWN
|SSL_SENT_SHUTDOWN
;
1183 mode
= SSL_get_shutdown(c
->ssl
->connection
);
1185 if (c
->ssl
->no_wait_shutdown
) {
1186 mode
|= SSL_RECEIVED_SHUTDOWN
;
1189 if (c
->ssl
->no_send_shutdown
) {
1190 mode
|= SSL_SENT_SHUTDOWN
;
1194 SSL_set_shutdown(c
->ssl
->connection
, mode
);
1196 ngx_ssl_clear_error(c
->log
);
1198 n
= SSL_shutdown(c
->ssl
->connection
);
1200 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_shutdown: %d", n
);
1204 /* SSL_shutdown() never returns -1, on error it returns 0 */
1206 if (n
!= 1 && ERR_peek_error()) {
1207 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
1209 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1210 "SSL_get_error: %d", sslerr
);
1213 if (n
== 1 || sslerr
== 0 || sslerr
== SSL_ERROR_ZERO_RETURN
) {
1214 SSL_free(c
->ssl
->connection
);
1220 if (sslerr
== SSL_ERROR_WANT_READ
|| sslerr
== SSL_ERROR_WANT_WRITE
) {
1221 c
->read
->handler
= ngx_ssl_shutdown_handler
;
1222 c
->write
->handler
= ngx_ssl_shutdown_handler
;
1224 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1228 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
1232 if (sslerr
== SSL_ERROR_WANT_READ
) {
1233 ngx_add_timer(c
->read
, 30000);
1239 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
1241 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_shutdown() failed");
1243 SSL_free(c
->ssl
->connection
);
1251 ngx_ssl_shutdown_handler(ngx_event_t
*ev
)
1253 ngx_connection_t
*c
;
1254 ngx_connection_handler_pt handler
;
1257 handler
= c
->ssl
->handler
;
1263 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0, "SSL shutdown handler");
1265 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
1274 ngx_ssl_connection_error(ngx_connection_t
*c
, int sslerr
, ngx_err_t err
,
1280 level
= NGX_LOG_CRIT
;
1282 if (sslerr
== SSL_ERROR_SYSCALL
) {
1284 if (err
== NGX_ECONNRESET
1286 || err
== NGX_ENOTCONN
1287 || err
== NGX_ETIMEDOUT
1288 || err
== NGX_ECONNREFUSED
1289 || err
== NGX_ENETDOWN
1290 || err
== NGX_ENETUNREACH
1291 || err
== NGX_EHOSTDOWN
1292 || err
== NGX_EHOSTUNREACH
)
1294 switch (c
->log_error
) {
1296 case NGX_ERROR_IGNORE_ECONNRESET
:
1297 case NGX_ERROR_INFO
:
1298 level
= NGX_LOG_INFO
;
1302 level
= NGX_LOG_ERR
;
1310 } else if (sslerr
== SSL_ERROR_SSL
) {
1312 n
= ERR_GET_REASON(ERR_peek_error());
1314 /* handshake failures */
1315 if (n
== SSL_R_DIGEST_CHECK_FAILED
/* 149 */
1316 || n
== SSL_R_LENGTH_MISMATCH
/* 159 */
1317 || n
== SSL_R_NO_CIPHERS_PASSED
/* 182 */
1318 || n
== SSL_R_NO_CIPHERS_SPECIFIED
/* 183 */
1319 || n
== SSL_R_NO_SHARED_CIPHER
/* 193 */
1320 || n
== SSL_R_RECORD_LENGTH_MISMATCH
/* 213 */
1321 || n
== SSL_R_UNEXPECTED_MESSAGE
/* 244 */
1322 || n
== SSL_R_UNEXPECTED_RECORD
/* 245 */
1323 || n
== SSL_R_UNKNOWN_ALERT_TYPE
/* 246 */
1324 || n
== SSL_R_UNKNOWN_PROTOCOL
/* 252 */
1325 || n
== SSL_R_WRONG_VERSION_NUMBER
/* 267 */
1326 || n
== SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC
/* 281 */
1327 || n
== 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
1328 || n
== SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE
/* 1010 */
1329 || n
== SSL_R_SSLV3_ALERT_BAD_RECORD_MAC
/* 1020 */
1330 || n
== SSL_R_TLSV1_ALERT_DECRYPTION_FAILED
/* 1021 */
1331 || n
== SSL_R_TLSV1_ALERT_RECORD_OVERFLOW
/* 1022 */
1332 || n
== SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE
/* 1030 */
1333 || n
== SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE
/* 1040 */
1334 || n
== SSL_R_SSLV3_ALERT_NO_CERTIFICATE
/* 1041 */
1335 || n
== SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
/* 1042 */
1336 || n
== SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE
/* 1043 */
1337 || n
== SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED
/* 1044 */
1338 || n
== SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED
/* 1045 */
1339 || n
== SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
/* 1046 */
1340 || n
== SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER
/* 1047 */
1341 || n
== SSL_R_TLSV1_ALERT_UNKNOWN_CA
/* 1048 */
1342 || n
== SSL_R_TLSV1_ALERT_ACCESS_DENIED
/* 1049 */
1343 || n
== SSL_R_TLSV1_ALERT_DECODE_ERROR
/* 1050 */
1344 || n
== SSL_R_TLSV1_ALERT_DECRYPT_ERROR
/* 1051 */
1345 || n
== SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION
/* 1060 */
1346 || n
== SSL_R_TLSV1_ALERT_PROTOCOL_VERSION
/* 1070 */
1347 || n
== SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY
/* 1071 */
1348 || n
== SSL_R_TLSV1_ALERT_INTERNAL_ERROR
/* 1080 */
1349 || n
== SSL_R_TLSV1_ALERT_USER_CANCELLED
/* 1090 */
1350 || n
== SSL_R_TLSV1_ALERT_NO_RENEGOTIATION
) /* 1100 */
1352 switch (c
->log_error
) {
1354 case NGX_ERROR_IGNORE_ECONNRESET
:
1355 case NGX_ERROR_INFO
:
1356 level
= NGX_LOG_INFO
;
1360 level
= NGX_LOG_ERR
;
1369 ngx_ssl_error(level
, c
->log
, err
, text
);
1374 ngx_ssl_clear_error(ngx_log_t
*log
)
1376 while (ERR_peek_error()) {
1377 ngx_ssl_error(NGX_LOG_ALERT
, log
, 0, "ignoring stale global SSL error");
1385 ngx_ssl_error(ngx_uint_t level
, ngx_log_t
*log
, ngx_err_t err
, char *fmt
, ...)
1390 u_char errstr
[NGX_MAX_CONF_ERRSTR
];
1392 last
= errstr
+ NGX_MAX_CONF_ERRSTR
;
1394 va_start(args
, fmt
);
1395 p
= ngx_vslprintf(errstr
, last
- 1, fmt
, args
);
1398 p
= ngx_cpystrn(p
, (u_char
*) " (SSL:", last
- p
);
1402 n
= ERR_get_error();
1414 ERR_error_string_n(n
, (char *) p
, last
- p
);
1416 while (p
< last
&& *p
) {
1421 ngx_log_error(level
, log
, err
, "%s)", errstr
);
1426 ngx_ssl_session_cache(ngx_ssl_t
*ssl
, ngx_str_t
*sess_ctx
,
1427 ssize_t builtin_session_cache
, ngx_shm_zone_t
*shm_zone
, time_t timeout
)
1431 if (builtin_session_cache
== NGX_SSL_NO_SCACHE
) {
1432 SSL_CTX_set_session_cache_mode(ssl
->ctx
, SSL_SESS_CACHE_OFF
);
1436 SSL_CTX_set_session_id_context(ssl
->ctx
, sess_ctx
->data
, sess_ctx
->len
);
1438 if (builtin_session_cache
== NGX_SSL_NONE_SCACHE
) {
1441 * If the server explicitly says that it does not support
1442 * session reuse (see SSL_SESS_CACHE_OFF above), then
1443 * Outlook Express fails to upload a sent email to
1444 * the Sent Items folder on the IMAP server via a separate IMAP
1445 * connection in the background. Therefore we have a special
1446 * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
1447 * where the server pretends that it supports session reuse,
1448 * but it does not actually store any session.
1451 SSL_CTX_set_session_cache_mode(ssl
->ctx
,
1452 SSL_SESS_CACHE_SERVER
1453 |SSL_SESS_CACHE_NO_AUTO_CLEAR
1454 |SSL_SESS_CACHE_NO_INTERNAL_STORE
);
1456 SSL_CTX_sess_set_cache_size(ssl
->ctx
, 1);
1461 cache_mode
= SSL_SESS_CACHE_SERVER
;
1463 if (shm_zone
&& builtin_session_cache
== NGX_SSL_NO_BUILTIN_SCACHE
) {
1464 cache_mode
|= SSL_SESS_CACHE_NO_INTERNAL
;
1467 SSL_CTX_set_session_cache_mode(ssl
->ctx
, cache_mode
);
1469 if (builtin_session_cache
!= NGX_SSL_NO_BUILTIN_SCACHE
) {
1471 if (builtin_session_cache
!= NGX_SSL_DFLT_BUILTIN_SCACHE
) {
1472 SSL_CTX_sess_set_cache_size(ssl
->ctx
, builtin_session_cache
);
1476 SSL_CTX_set_timeout(ssl
->ctx
, (long) timeout
);
1479 shm_zone
->init
= ngx_ssl_session_cache_init
;
1481 SSL_CTX_sess_set_new_cb(ssl
->ctx
, ngx_ssl_new_session
);
1482 SSL_CTX_sess_set_get_cb(ssl
->ctx
, ngx_ssl_get_cached_session
);
1483 SSL_CTX_sess_set_remove_cb(ssl
->ctx
, ngx_ssl_remove_session
);
1485 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_session_cache_index
, shm_zone
)
1488 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
1489 "SSL_CTX_set_ex_data() failed");
1499 ngx_ssl_session_cache_init(ngx_shm_zone_t
*shm_zone
, void *data
)
1502 ngx_slab_pool_t
*shpool
;
1503 ngx_ssl_session_cache_t
*cache
;
1506 shm_zone
->data
= data
;
1510 if (shm_zone
->shm
.exists
) {
1511 shm_zone
->data
= data
;
1515 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1517 cache
= ngx_slab_alloc(shpool
, sizeof(ngx_ssl_session_cache_t
));
1518 if (cache
== NULL
) {
1522 shpool
->data
= cache
;
1523 shm_zone
->data
= cache
;
1525 ngx_rbtree_init(&cache
->session_rbtree
, &cache
->sentinel
,
1526 ngx_ssl_session_rbtree_insert_value
);
1528 ngx_queue_init(&cache
->expire_queue
);
1530 len
= sizeof(" in SSL session shared cache \"\"") + shm_zone
->shm
.name
.len
;
1532 shpool
->log_ctx
= ngx_slab_alloc(shpool
, len
);
1533 if (shpool
->log_ctx
== NULL
) {
1537 ngx_sprintf(shpool
->log_ctx
, " in SSL session shared cache \"%V\"%Z",
1538 &shm_zone
->shm
.name
);
1545 * The length of the session id is 16 bytes for SSLv2 sessions and
1546 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1547 * It seems that the typical length of the external ASN1 representation
1548 * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1550 * Thus on 32-bit platforms we allocate separately an rbtree node,
1551 * a session id, and an ASN1 representation, they take accordingly
1552 * 64, 32, and 128 bytes.
1554 * On 64-bit platforms we allocate separately an rbtree node + session_id,
1555 * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1557 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1558 * so they are outside the code locked by shared pool mutex
1562 ngx_ssl_new_session(ngx_ssl_conn_t
*ssl_conn
, ngx_ssl_session_t
*sess
)
1565 u_char
*p
, *id
, *cached_sess
;
1568 ngx_shm_zone_t
*shm_zone
;
1569 ngx_connection_t
*c
;
1570 ngx_slab_pool_t
*shpool
;
1571 ngx_ssl_sess_id_t
*sess_id
;
1572 ngx_ssl_session_cache_t
*cache
;
1573 u_char buf
[NGX_SSL_MAX_SESSION_SIZE
];
1575 len
= i2d_SSL_SESSION(sess
, NULL
);
1577 /* do not cache too big session */
1579 if (len
> (int) NGX_SSL_MAX_SESSION_SIZE
) {
1584 i2d_SSL_SESSION(sess
, &p
);
1586 c
= ngx_ssl_get_connection(ssl_conn
);
1588 ssl_ctx
= SSL_get_SSL_CTX(ssl_conn
);
1589 shm_zone
= SSL_CTX_get_ex_data(ssl_ctx
, ngx_ssl_session_cache_index
);
1591 cache
= shm_zone
->data
;
1592 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1594 ngx_shmtx_lock(&shpool
->mutex
);
1596 /* drop one or two expired sessions */
1597 ngx_ssl_expire_sessions(cache
, shpool
, 1);
1599 cached_sess
= ngx_slab_alloc_locked(shpool
, len
);
1601 if (cached_sess
== NULL
) {
1603 /* drop the oldest non-expired session and try once more */
1605 ngx_ssl_expire_sessions(cache
, shpool
, 0);
1607 cached_sess
= ngx_slab_alloc_locked(shpool
, len
);
1609 if (cached_sess
== NULL
) {
1615 sess_id
= ngx_slab_alloc_locked(shpool
, sizeof(ngx_ssl_sess_id_t
));
1616 if (sess_id
== NULL
) {
1620 #if (NGX_PTR_SIZE == 8)
1622 id
= sess_id
->sess_id
;
1626 id
= ngx_slab_alloc_locked(shpool
, sess
->session_id_length
);
1633 ngx_memcpy(cached_sess
, buf
, len
);
1635 ngx_memcpy(id
, sess
->session_id
, sess
->session_id_length
);
1637 hash
= ngx_crc32_short(sess
->session_id
, sess
->session_id_length
);
1639 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1640 "ssl new session: %08XD:%d:%d",
1641 hash
, sess
->session_id_length
, len
);
1643 sess_id
->node
.key
= hash
;
1644 sess_id
->node
.data
= (u_char
) sess
->session_id_length
;
1647 sess_id
->session
= cached_sess
;
1649 sess_id
->expire
= ngx_time() + SSL_CTX_get_timeout(ssl_ctx
);
1651 ngx_queue_insert_head(&cache
->expire_queue
, &sess_id
->queue
);
1653 ngx_rbtree_insert(&cache
->session_rbtree
, &sess_id
->node
);
1655 ngx_shmtx_unlock(&shpool
->mutex
);
1662 ngx_slab_free_locked(shpool
, cached_sess
);
1666 ngx_slab_free_locked(shpool
, sess_id
);
1669 ngx_shmtx_unlock(&shpool
->mutex
);
1671 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
1672 "could not add new SSL session to the session cache");
1678 static ngx_ssl_session_t
*
1679 ngx_ssl_get_cached_session(ngx_ssl_conn_t
*ssl_conn
, u_char
*id
, int len
,
1682 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1688 ngx_shm_zone_t
*shm_zone
;
1689 ngx_slab_pool_t
*shpool
;
1690 ngx_connection_t
*c
;
1691 ngx_rbtree_node_t
*node
, *sentinel
;
1692 ngx_ssl_session_t
*sess
;
1693 ngx_ssl_sess_id_t
*sess_id
;
1694 ngx_ssl_session_cache_t
*cache
;
1695 u_char buf
[NGX_SSL_MAX_SESSION_SIZE
];
1697 c
= ngx_ssl_get_connection(ssl_conn
);
1699 hash
= ngx_crc32_short(id
, (size_t) len
);
1702 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1703 "ssl get session: %08XD:%d", hash
, len
);
1705 shm_zone
= SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn
),
1706 ngx_ssl_session_cache_index
);
1708 cache
= shm_zone
->data
;
1712 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1714 ngx_shmtx_lock(&shpool
->mutex
);
1716 node
= cache
->session_rbtree
.root
;
1717 sentinel
= cache
->session_rbtree
.sentinel
;
1719 while (node
!= sentinel
) {
1721 if (hash
< node
->key
) {
1726 if (hash
> node
->key
) {
1731 /* hash == node->key */
1734 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1736 rc
= ngx_memn2cmp(id
, sess_id
->id
,
1737 (size_t) len
, (size_t) node
->data
);
1740 if (sess_id
->expire
> ngx_time()) {
1741 ngx_memcpy(buf
, sess_id
->session
, sess_id
->len
);
1743 ngx_shmtx_unlock(&shpool
->mutex
);
1746 sess
= d2i_SSL_SESSION(NULL
, &p
, sess_id
->len
);
1751 ngx_queue_remove(&sess_id
->queue
);
1753 ngx_rbtree_delete(&cache
->session_rbtree
, node
);
1755 ngx_slab_free_locked(shpool
, sess_id
->session
);
1756 #if (NGX_PTR_SIZE == 4)
1757 ngx_slab_free_locked(shpool
, sess_id
->id
);
1759 ngx_slab_free_locked(shpool
, sess_id
);
1766 node
= (rc
< 0) ? node
->left
: node
->right
;
1768 } while (node
!= sentinel
&& hash
== node
->key
);
1775 ngx_shmtx_unlock(&shpool
->mutex
);
1782 ngx_ssl_remove_cached_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
)
1784 SSL_CTX_remove_session(ssl
, sess
);
1786 ngx_ssl_remove_session(ssl
, sess
);
1791 ngx_ssl_remove_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
)
1797 ngx_shm_zone_t
*shm_zone
;
1798 ngx_slab_pool_t
*shpool
;
1799 ngx_rbtree_node_t
*node
, *sentinel
;
1800 ngx_ssl_sess_id_t
*sess_id
;
1801 ngx_ssl_session_cache_t
*cache
;
1803 shm_zone
= SSL_CTX_get_ex_data(ssl
, ngx_ssl_session_cache_index
);
1805 if (shm_zone
== NULL
) {
1809 cache
= shm_zone
->data
;
1811 id
= sess
->session_id
;
1812 len
= (size_t) sess
->session_id_length
;
1814 hash
= ngx_crc32_short(id
, len
);
1816 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ngx_cycle
->log
, 0,
1817 "ssl remove session: %08XD:%uz", hash
, len
);
1819 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1821 ngx_shmtx_lock(&shpool
->mutex
);
1823 node
= cache
->session_rbtree
.root
;
1824 sentinel
= cache
->session_rbtree
.sentinel
;
1826 while (node
!= sentinel
) {
1828 if (hash
< node
->key
) {
1833 if (hash
> node
->key
) {
1838 /* hash == node->key */
1841 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1843 rc
= ngx_memn2cmp(id
, sess_id
->id
, len
, (size_t) node
->data
);
1847 ngx_queue_remove(&sess_id
->queue
);
1849 ngx_rbtree_delete(&cache
->session_rbtree
, node
);
1851 ngx_slab_free_locked(shpool
, sess_id
->session
);
1852 #if (NGX_PTR_SIZE == 4)
1853 ngx_slab_free_locked(shpool
, sess_id
->id
);
1855 ngx_slab_free_locked(shpool
, sess_id
);
1860 node
= (rc
< 0) ? node
->left
: node
->right
;
1862 } while (node
!= sentinel
&& hash
== node
->key
);
1869 ngx_shmtx_unlock(&shpool
->mutex
);
1874 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t
*cache
,
1875 ngx_slab_pool_t
*shpool
, ngx_uint_t n
)
1879 ngx_ssl_sess_id_t
*sess_id
;
1885 if (ngx_queue_empty(&cache
->expire_queue
)) {
1889 q
= ngx_queue_last(&cache
->expire_queue
);
1891 sess_id
= ngx_queue_data(q
, ngx_ssl_sess_id_t
, queue
);
1893 if (n
++ != 0 && sess_id
->expire
> now
) {
1897 ngx_queue_remove(q
);
1899 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ngx_cycle
->log
, 0,
1900 "expire session: %08Xi", sess_id
->node
.key
);
1902 ngx_rbtree_delete(&cache
->session_rbtree
, &sess_id
->node
);
1904 ngx_slab_free_locked(shpool
, sess_id
->session
);
1905 #if (NGX_PTR_SIZE == 4)
1906 ngx_slab_free_locked(shpool
, sess_id
->id
);
1908 ngx_slab_free_locked(shpool
, sess_id
);
1914 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
1915 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
)
1917 ngx_rbtree_node_t
**p
;
1918 ngx_ssl_sess_id_t
*sess_id
, *sess_id_temp
;
1922 if (node
->key
< temp
->key
) {
1926 } else if (node
->key
> temp
->key
) {
1930 } else { /* node->key == temp->key */
1932 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1933 sess_id_temp
= (ngx_ssl_sess_id_t
*) temp
;
1935 p
= (ngx_memn2cmp(sess_id
->id
, sess_id_temp
->id
,
1936 (size_t) node
->data
, (size_t) temp
->data
)
1937 < 0) ? &temp
->left
: &temp
->right
;
1940 if (*p
== sentinel
) {
1948 node
->parent
= temp
;
1949 node
->left
= sentinel
;
1950 node
->right
= sentinel
;
1956 ngx_ssl_cleanup_ctx(void *data
)
1958 ngx_ssl_t
*ssl
= data
;
1960 SSL_CTX_free(ssl
->ctx
);
1965 ngx_ssl_get_protocol(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1967 s
->data
= (u_char
*) SSL_get_version(c
->ssl
->connection
);
1973 ngx_ssl_get_cipher_name(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1975 s
->data
= (u_char
*) SSL_get_cipher_name(c
->ssl
->connection
);
1981 ngx_ssl_get_session_id(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1987 sess
= SSL_get0_session(c
->ssl
->connection
);
1989 len
= i2d_SSL_SESSION(sess
, NULL
);
1991 buf
= ngx_alloc(len
, c
->log
);
1997 s
->data
= ngx_pnalloc(pool
, 2 * len
);
1998 if (s
->data
== NULL
) {
2004 i2d_SSL_SESSION(sess
, &p
);
2006 ngx_hex_dump(s
->data
, buf
, len
);
2015 ngx_ssl_get_raw_certificate(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2023 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2028 bio
= BIO_new(BIO_s_mem());
2030 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "BIO_new() failed");
2035 if (PEM_write_bio_X509(bio
, cert
) == 0) {
2036 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "PEM_write_bio_X509() failed");
2040 len
= BIO_pending(bio
);
2043 s
->data
= ngx_pnalloc(pool
, len
);
2044 if (s
->data
== NULL
) {
2048 BIO_read(bio
, s
->data
, len
);
2065 ngx_ssl_get_certificate(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2072 if (ngx_ssl_get_raw_certificate(c
, pool
, &cert
) != NGX_OK
) {
2076 if (cert
.len
== 0) {
2083 for (i
= 0; i
< cert
.len
- 1; i
++) {
2084 if (cert
.data
[i
] == LF
) {
2090 s
->data
= ngx_pnalloc(pool
, len
);
2091 if (s
->data
== NULL
) {
2097 for (i
= 0; i
< cert
.len
- 1; i
++) {
2098 *p
++ = cert
.data
[i
];
2099 if (cert
.data
[i
] == LF
) {
2109 ngx_ssl_get_subject_dn(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2118 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2123 name
= X509_get_subject_name(cert
);
2129 p
= X509_NAME_oneline(name
, NULL
, 0);
2131 for (len
= 0; p
[len
]; len
++) { /* void */ }
2134 s
->data
= ngx_pnalloc(pool
, len
);
2135 if (s
->data
== NULL
) {
2141 ngx_memcpy(s
->data
, p
, len
);
2151 ngx_ssl_get_issuer_dn(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2160 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2165 name
= X509_get_issuer_name(cert
);
2171 p
= X509_NAME_oneline(name
, NULL
, 0);
2173 for (len
= 0; p
[len
]; len
++) { /* void */ }
2176 s
->data
= ngx_pnalloc(pool
, len
);
2177 if (s
->data
== NULL
) {
2183 ngx_memcpy(s
->data
, p
, len
);
2193 ngx_ssl_get_serial_number(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2201 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2206 bio
= BIO_new(BIO_s_mem());
2212 i2a_ASN1_INTEGER(bio
, X509_get_serialNumber(cert
));
2213 len
= BIO_pending(bio
);
2216 s
->data
= ngx_pnalloc(pool
, len
);
2217 if (s
->data
== NULL
) {
2223 BIO_read(bio
, s
->data
, len
);
2232 ngx_ssl_get_client_verify(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
2236 if (SSL_get_verify_result(c
->ssl
->connection
) != X509_V_OK
) {
2237 ngx_str_set(s
, "FAILED");
2241 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
2244 ngx_str_set(s
, "SUCCESS");
2247 ngx_str_set(s
, "NONE");
2257 ngx_openssl_create_conf(ngx_cycle_t
*cycle
)
2259 ngx_openssl_conf_t
*oscf
;
2261 oscf
= ngx_pcalloc(cycle
->pool
, sizeof(ngx_openssl_conf_t
));
2267 * set by ngx_pcalloc():
2277 ngx_openssl_engine(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2279 ngx_openssl_conf_t
*oscf
= conf
;
2285 return "is duplicate";
2290 value
= cf
->args
->elts
;
2292 engine
= ENGINE_by_id((const char *) value
[1].data
);
2294 if (engine
== NULL
) {
2295 ngx_ssl_error(NGX_LOG_WARN
, cf
->log
, 0,
2296 "ENGINE_by_id(\"%V\") failed", &value
[1]);
2297 return NGX_CONF_ERROR
;
2300 if (ENGINE_set_default(engine
, ENGINE_METHOD_ALL
) == 0) {
2301 ngx_ssl_error(NGX_LOG_WARN
, cf
->log
, 0,
2302 "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
2305 ENGINE_free(engine
);
2307 return NGX_CONF_ERROR
;
2310 ENGINE_free(engine
);
2317 ngx_openssl_exit(ngx_cycle_t
*cycle
)