3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
17 static int ngx_http_ssl_verify_callback(int ok
, X509_STORE_CTX
*x509_store
);
18 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
);
20 static void ngx_ssl_write_handler(ngx_event_t
*wev
);
21 static void ngx_ssl_read_handler(ngx_event_t
*rev
);
22 static void ngx_ssl_shutdown_handler(ngx_event_t
*ev
);
23 static void ngx_ssl_connection_error(ngx_connection_t
*c
, int sslerr
,
24 ngx_err_t err
, char *text
);
26 static ngx_int_t
ngx_ssl_session_cache_init(ngx_shm_zone_t
*shm_zone
,
28 static int ngx_ssl_new_session(ngx_ssl_conn_t
*ssl_conn
,
29 ngx_ssl_session_t
*sess
);
30 static ngx_ssl_session_t
*ngx_ssl_get_cached_session(ngx_ssl_conn_t
*ssl_conn
,
31 u_char
*id
, int len
, int *copy
);
32 static void ngx_ssl_remove_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
);
33 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t
*cache
,
34 ngx_slab_pool_t
*shpool
, ngx_uint_t n
);
35 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
36 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
);
38 static void *ngx_openssl_create_conf(ngx_cycle_t
*cycle
);
39 static char *ngx_openssl_init_conf(ngx_cycle_t
*cycle
, void *conf
);
40 static void ngx_openssl_exit(ngx_cycle_t
*cycle
);
43 static char *ngx_openssl_noengine(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
48 static ngx_command_t ngx_openssl_commands
[] = {
50 { ngx_string("ssl_engine"),
51 NGX_MAIN_CONF
|NGX_DIRECT_CONF
|NGX_CONF_TAKE1
,
53 ngx_conf_set_str_slot
,
58 offsetof(ngx_openssl_conf_t
, engine
),
65 static ngx_core_module_t ngx_openssl_module_ctx
= {
66 ngx_string("openssl"),
67 ngx_openssl_create_conf
,
72 ngx_module_t ngx_openssl_module
= {
74 &ngx_openssl_module_ctx
, /* module context */
75 ngx_openssl_commands
, /* module directives */
76 NGX_CORE_MODULE
, /* module type */
77 NULL
, /* init master */
78 NULL
, /* init module */
79 NULL
, /* init process */
80 NULL
, /* init thread */
81 NULL
, /* exit thread */
82 NULL
, /* exit process */
83 ngx_openssl_exit
, /* exit master */
88 static long ngx_ssl_protocols
[] = {
89 SSL_OP_NO_SSLv2
|SSL_OP_NO_SSLv3
|SSL_OP_NO_TLSv1
,
90 SSL_OP_NO_SSLv3
|SSL_OP_NO_TLSv1
,
91 SSL_OP_NO_SSLv2
|SSL_OP_NO_TLSv1
,
93 SSL_OP_NO_SSLv2
|SSL_OP_NO_SSLv3
,
100 int ngx_ssl_connection_index
;
101 int ngx_ssl_server_conf_index
;
102 int ngx_ssl_session_cache_index
;
106 ngx_ssl_init(ngx_log_t
*log
)
108 #if OPENSSL_VERSION_NUMBER >= 0x00907000
109 OPENSSL_config(NULL
);
113 SSL_load_error_strings();
116 ENGINE_load_builtin_engines();
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");
147 ngx_ssl_create(ngx_ssl_t
*ssl
, ngx_uint_t protocols
, void *data
)
149 ssl
->ctx
= SSL_CTX_new(SSLv23_method());
151 if (ssl
->ctx
== NULL
) {
152 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "SSL_CTX_new() failed");
156 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_server_conf_index
, data
) == 0) {
157 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
158 "SSL_CTX_set_ex_data() failed");
162 /* client side options */
164 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MICROSOFT_SESS_ID_BUG
);
165 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NETSCAPE_CHALLENGE_BUG
);
166 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
);
168 /* server side options */
170 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
);
171 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
);
173 /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
174 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_MSIE_SSLV2_RSA_PADDING
);
176 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_SSLEAY_080_CLIENT_DH_BUG
);
177 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_TLS_D5_BUG
);
178 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_TLS_BLOCK_PADDING_BUG
);
180 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
181 SSL_CTX_set_options(ssl
->ctx
, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
);
185 if (ngx_ssl_protocols
[protocols
>> 1] != 0) {
186 SSL_CTX_set_options(ssl
->ctx
, ngx_ssl_protocols
[protocols
>> 1]);
189 SSL_CTX_set_mode(ssl
->ctx
, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
);
191 SSL_CTX_set_read_ahead(ssl
->ctx
, 1);
198 ngx_ssl_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
201 if (ngx_conf_full_name(cf
->cycle
, cert
) == NGX_ERROR
) {
205 if (SSL_CTX_use_certificate_chain_file(ssl
->ctx
, (char *) cert
->data
)
208 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
209 "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
214 if (ngx_conf_full_name(cf
->cycle
, key
) == NGX_ERROR
) {
218 if (SSL_CTX_use_PrivateKey_file(ssl
->ctx
, (char *) key
->data
,
222 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
223 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key
->data
);
232 ngx_ssl_client_certificate(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*cert
,
235 STACK_OF(X509_NAME
) *list
;
237 SSL_CTX_set_verify(ssl
->ctx
, SSL_VERIFY_PEER
, ngx_http_ssl_verify_callback
);
239 SSL_CTX_set_verify_depth(ssl
->ctx
, depth
);
241 if (cert
->len
== 0) {
245 if (ngx_conf_full_name(cf
->cycle
, cert
) == NGX_ERROR
) {
249 if (SSL_CTX_load_verify_locations(ssl
->ctx
, (char *) cert
->data
, NULL
)
252 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
253 "SSL_CTX_load_verify_locations(\"%s\") failed",
258 list
= SSL_load_client_CA_file((char *) cert
->data
);
261 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
262 "SSL_load_client_CA_file(\"%s\") failed", cert
->data
);
267 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
268 * always leaved an error in the error queue
273 SSL_CTX_set_client_CA_list(ssl
->ctx
, list
);
280 ngx_http_ssl_verify_callback(int ok
, X509_STORE_CTX
*x509_store
)
282 char *subject
, *issuer
;
287 ngx_ssl_conn_t
*ssl_conn
;
289 ssl_conn
= X509_STORE_CTX_get_ex_data(x509_store
,
290 SSL_get_ex_data_X509_STORE_CTX_idx());
292 c
= ngx_ssl_get_connection(ssl_conn
);
294 cert
= X509_STORE_CTX_get_current_cert(x509_store
);
295 err
= X509_STORE_CTX_get_error(x509_store
);
296 depth
= X509_STORE_CTX_get_error_depth(x509_store
);
298 name
= X509_get_subject_name(cert
);
299 subject
= name
? X509_NAME_oneline(name
, NULL
, 0) : "(none)";
301 name
= X509_get_issuer_name(cert
);
302 issuer
= name
? X509_NAME_oneline(name
, NULL
, 0) : "(none)";
304 ngx_log_debug5(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
305 "verify:%d, error:%d, depth:%d, "
306 "subject:\"%s\",issuer: \"%s\"",
307 ok
, err
, depth
, subject
, issuer
);
314 ngx_ssl_generate_rsa512_key(ngx_ssl_t
*ssl
)
318 if (SSL_CTX_need_tmp_RSA(ssl
->ctx
) == 0) {
322 key
= RSA_generate_key(512, RSA_F4
, NULL
, NULL
);
325 SSL_CTX_set_tmp_rsa(ssl
->ctx
, key
);
332 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0, "RSA_generate_key(512) failed");
339 ngx_ssl_create_connection(ngx_ssl_t
*ssl
, ngx_connection_t
*c
, ngx_uint_t flags
)
341 ngx_ssl_connection_t
*sc
;
343 sc
= ngx_pcalloc(c
->pool
, sizeof(ngx_ssl_connection_t
));
348 if (flags
& NGX_SSL_BUFFER
) {
351 sc
->buf
= ngx_create_temp_buf(c
->pool
, NGX_SSL_BUFSIZE
);
352 if (sc
->buf
== NULL
) {
357 sc
->connection
= SSL_new(ssl
->ctx
);
359 if (sc
->connection
== NULL
) {
360 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_new() failed");
364 if (SSL_set_fd(sc
->connection
, c
->fd
) == 0) {
365 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_fd() failed");
369 if (flags
& NGX_SSL_CLIENT
) {
370 SSL_set_connect_state(sc
->connection
);
373 SSL_set_accept_state(sc
->connection
);
376 if (SSL_set_ex_data(sc
->connection
, ngx_ssl_connection_index
, c
) == 0) {
377 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_ex_data() failed");
388 ngx_ssl_set_session(ngx_connection_t
*c
, ngx_ssl_session_t
*session
)
391 if (SSL_set_session(c
->ssl
->connection
, session
) == 0) {
392 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "SSL_set_session() failed");
402 ngx_ssl_handshake(ngx_connection_t
*c
)
407 n
= SSL_do_handshake(c
->ssl
->connection
);
409 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_do_handshake: %d", n
);
413 if (ngx_handle_read_event(c
->read
, 0) == NGX_ERROR
) {
417 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
423 char buf
[129], *s
, *d
;
426 cipher
= SSL_get_current_cipher(c
->ssl
->connection
);
429 SSL_CIPHER_description(cipher
, &buf
[1], 128);
431 for (s
= &buf
[1], d
= buf
; *s
; s
++) {
432 if (*s
== ' ' && *d
== ' ') {
436 if (*s
== LF
|| *s
== CR
) {
449 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
450 "SSL: %s, cipher: \"%s\"",
451 SSL_get_version(c
->ssl
->connection
), &buf
[1]);
453 if (SSL_session_reused(c
->ssl
->connection
)) {
454 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
455 "SSL reused session");
459 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
460 "SSL no shared ciphers");
465 c
->ssl
->handshaked
= 1;
467 c
->recv
= ngx_ssl_recv
;
468 c
->send
= ngx_ssl_write
;
469 c
->recv_chain
= ngx_ssl_recv_chain
;
470 c
->send_chain
= ngx_ssl_send_chain
;
475 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
477 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
479 if (sslerr
== SSL_ERROR_WANT_READ
) {
481 c
->read
->handler
= ngx_ssl_handshake_handler
;
482 c
->write
->handler
= ngx_ssl_handshake_handler
;
484 if (ngx_handle_read_event(c
->read
, 0) == NGX_ERROR
) {
491 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
493 c
->read
->handler
= ngx_ssl_handshake_handler
;
494 c
->write
->handler
= ngx_ssl_handshake_handler
;
496 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
503 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
505 c
->ssl
->no_wait_shutdown
= 1;
506 c
->ssl
->no_send_shutdown
= 1;
509 if (sslerr
== SSL_ERROR_ZERO_RETURN
|| ERR_peek_error() == 0) {
510 ngx_log_error(NGX_LOG_INFO
, c
->log
, err
,
511 "peer closed connection in SSL handshake");
518 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_do_handshake() failed");
525 ngx_ssl_handshake_handler(ngx_event_t
*ev
)
531 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
532 "SSL handshake handler: %d", ev
->write
);
539 if (ngx_ssl_handshake(c
) == NGX_AGAIN
) {
548 ngx_ssl_recv_chain(ngx_connection_t
*c
, ngx_chain_t
*cl
)
561 n
= ngx_ssl_recv(c
, last
, b
->end
- last
);
567 if (last
== b
->end
) {
591 ngx_ssl_recv(ngx_connection_t
*c
, u_char
*buf
, size_t size
)
595 if (c
->ssl
->last
== NGX_ERROR
) {
599 if (c
->ssl
->last
== NGX_DONE
) {
606 * SSL_read() may return data in parts, so try to read
607 * until SSL_read() would return no data
612 n
= SSL_read(c
->ssl
->connection
, buf
, size
);
614 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_read: %d", n
);
620 c
->ssl
->last
= ngx_ssl_handle_recv(c
, n
);
622 if (c
->ssl
->last
!= NGX_OK
) {
628 if (c
->ssl
->last
== NGX_DONE
) {
647 ngx_ssl_handle_recv(ngx_connection_t
*c
, int n
)
654 if (c
->ssl
->saved_write_handler
) {
656 c
->write
->handler
= c
->ssl
->saved_write_handler
;
657 c
->ssl
->saved_write_handler
= NULL
;
660 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
664 ngx_post_event(c
->write
, &ngx_posted_events
);
670 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
672 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
674 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
676 if (sslerr
== SSL_ERROR_WANT_READ
) {
681 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
683 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
684 "peer started SSL renegotiation");
688 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
693 * we do not set the timer because there is already the read event timer
696 if (c
->ssl
->saved_write_handler
== NULL
) {
697 c
->ssl
->saved_write_handler
= c
->write
->handler
;
698 c
->write
->handler
= ngx_ssl_write_handler
;
704 c
->ssl
->no_wait_shutdown
= 1;
705 c
->ssl
->no_send_shutdown
= 1;
708 if (sslerr
== SSL_ERROR_ZERO_RETURN
|| ERR_peek_error() == 0) {
709 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
710 "peer shutdown SSL cleanly");
715 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_read() failed");
722 ngx_ssl_write_handler(ngx_event_t
*wev
)
728 c
->read
->handler(c
->read
);
733 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
734 * before the SSL_write() call to decrease a SSL overhead.
736 * Besides for protocols such as HTTP it is possible to always buffer
737 * the output to decrease a SSL overhead some more.
741 ngx_ssl_send_chain(ngx_connection_t
*c
, ngx_chain_t
*in
, off_t limit
)
749 || (in
&& in
->next
== NULL
&& !(c
->buffered
& NGX_SSL_BUFFERED
)))
752 * we avoid a buffer copy if
753 * we do not need to buffer the output
754 * or the incoming buf is a single and our buffer is empty
758 if (ngx_buf_special(in
->buf
)) {
763 n
= ngx_ssl_write(c
, in
->buf
->pos
, in
->buf
->last
- in
->buf
->pos
);
765 if (n
== NGX_ERROR
) {
766 return NGX_CHAIN_ERROR
;
769 if (n
== NGX_AGAIN
) {
770 c
->buffered
|= NGX_SSL_BUFFERED
;
776 if (in
->buf
->pos
== in
->buf
->last
) {
785 /* the maximum limit size is the maximum uint32_t value - the page size */
787 if (limit
== 0 || limit
> NGX_MAX_UINT32_VALUE
- ngx_pagesize
) {
788 limit
= NGX_MAX_UINT32_VALUE
- ngx_pagesize
;
794 flush
= (in
== NULL
) ? 1 : 0;
798 while (in
&& buf
->last
< buf
->end
) {
799 if (in
->buf
->last_buf
|| in
->buf
->flush
) {
803 if (ngx_buf_special(in
->buf
)) {
808 size
= in
->buf
->last
- in
->buf
->pos
;
810 if (size
> buf
->end
- buf
->last
) {
811 size
= buf
->end
- buf
->last
;
814 if (send
+ size
> limit
) {
815 size
= (ssize_t
) (limit
- send
);
819 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
820 "SSL buf copy: %d", size
);
822 ngx_memcpy(buf
->last
, in
->buf
->pos
, size
);
826 in
->buf
->pos
+= size
;
828 if (in
->buf
->pos
== in
->buf
->last
) {
833 size
= buf
->last
- buf
->pos
;
835 if (!flush
&& buf
->last
< buf
->end
&& c
->ssl
->buffer
) {
839 n
= ngx_ssl_write(c
, buf
->pos
, size
);
841 if (n
== NGX_ERROR
) {
842 return NGX_CHAIN_ERROR
;
845 if (n
== NGX_AGAIN
) {
846 c
->buffered
|= NGX_SSL_BUFFERED
;
858 if (buf
->pos
== buf
->last
) {
859 buf
->pos
= buf
->start
;
860 buf
->last
= buf
->start
;
863 if (in
== NULL
|| send
== limit
) {
868 if (buf
->pos
< buf
->last
) {
869 c
->buffered
|= NGX_SSL_BUFFERED
;
872 c
->buffered
&= ~NGX_SSL_BUFFERED
;
880 ngx_ssl_write(ngx_connection_t
*c
, u_char
*data
, size_t size
)
885 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL to write: %d", size
);
887 n
= SSL_write(c
->ssl
->connection
, data
, size
);
889 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_write: %d", n
);
893 if (c
->ssl
->saved_read_handler
) {
895 c
->read
->handler
= c
->ssl
->saved_read_handler
;
896 c
->ssl
->saved_read_handler
= NULL
;
899 if (ngx_handle_read_event(c
->read
, 0) == NGX_ERROR
) {
903 ngx_post_event(c
->read
, &ngx_posted_events
);
909 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
911 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
913 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_get_error: %d", sslerr
);
915 if (sslerr
== SSL_ERROR_WANT_WRITE
) {
920 if (sslerr
== SSL_ERROR_WANT_READ
) {
922 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
923 "peer started SSL renegotiation");
927 if (ngx_handle_read_event(c
->read
, 0) == NGX_ERROR
) {
932 * we do not set the timer because there is already
933 * the write event timer
936 if (c
->ssl
->saved_read_handler
== NULL
) {
937 c
->ssl
->saved_read_handler
= c
->read
->handler
;
938 c
->read
->handler
= ngx_ssl_read_handler
;
944 c
->ssl
->no_wait_shutdown
= 1;
945 c
->ssl
->no_send_shutdown
= 1;
948 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_write() failed");
955 ngx_ssl_read_handler(ngx_event_t
*rev
)
961 c
->write
->handler(c
->write
);
966 ngx_ssl_shutdown(ngx_connection_t
*c
)
973 mode
= SSL_RECEIVED_SHUTDOWN
|SSL_SENT_SHUTDOWN
;
976 mode
= SSL_get_shutdown(c
->ssl
->connection
);
978 if (c
->ssl
->no_wait_shutdown
) {
979 mode
|= SSL_RECEIVED_SHUTDOWN
;
982 if (c
->ssl
->no_send_shutdown
) {
983 mode
|= SSL_SENT_SHUTDOWN
;
987 SSL_set_shutdown(c
->ssl
->connection
, mode
);
993 n
= SSL_shutdown(c
->ssl
->connection
);
995 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "SSL_shutdown: %d", n
);
997 if (n
== 1 || (n
== 0 && c
->timedout
)) {
998 SSL_free(c
->ssl
->connection
);
1013 sslerr
= SSL_get_error(c
->ssl
->connection
, n
);
1015 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1016 "SSL_get_error: %d", sslerr
);
1020 || sslerr
== SSL_ERROR_WANT_READ
1021 || sslerr
== SSL_ERROR_WANT_WRITE
)
1023 c
->read
->handler
= ngx_ssl_shutdown_handler
;
1024 c
->write
->handler
= ngx_ssl_shutdown_handler
;
1026 if (ngx_handle_read_event(c
->read
, 0) == NGX_ERROR
) {
1030 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
1034 if (again
|| sslerr
== SSL_ERROR_WANT_READ
) {
1035 ngx_add_timer(c
->read
, 30000);
1041 err
= (sslerr
== SSL_ERROR_SYSCALL
) ? ngx_errno
: 0;
1043 ngx_ssl_connection_error(c
, sslerr
, err
, "SSL_shutdown() failed");
1045 SSL_free(c
->ssl
->connection
);
1053 ngx_ssl_shutdown_handler(ngx_event_t
*ev
)
1055 ngx_connection_t
*c
;
1056 ngx_connection_handler_pt handler
;
1059 handler
= c
->ssl
->handler
;
1065 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0, "SSL shutdown handler");
1067 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
1076 ngx_ssl_connection_error(ngx_connection_t
*c
, int sslerr
, ngx_err_t err
,
1081 level
= NGX_LOG_CRIT
;
1083 if (sslerr
== SSL_ERROR_SYSCALL
) {
1085 if (err
== NGX_ECONNRESET
1087 || err
== NGX_ENOTCONN
1088 #if !(NGX_CRIT_ETIMEDOUT)
1089 || err
== NGX_ETIMEDOUT
1091 || err
== NGX_ECONNREFUSED
1092 || err
== NGX_EHOSTUNREACH
)
1094 switch (c
->log_error
) {
1096 case NGX_ERROR_IGNORE_ECONNRESET
:
1097 case NGX_ERROR_INFO
:
1098 level
= NGX_LOG_INFO
;
1102 level
= NGX_LOG_ERR
;
1111 ngx_ssl_error(level
, c
->log
, err
, text
);
1116 ngx_ssl_error(ngx_uint_t level
, ngx_log_t
*log
, ngx_err_t err
, char *fmt
, ...)
1120 u_char errstr
[NGX_MAX_CONF_ERRSTR
], *p
, *last
;
1122 last
= errstr
+ NGX_MAX_CONF_ERRSTR
;
1124 va_start(args
, fmt
);
1125 p
= ngx_vsnprintf(errstr
, sizeof(errstr
) - 1, fmt
, args
);
1128 p
= ngx_cpystrn(p
, (u_char
*) " (SSL:", last
- p
);
1132 n
= ERR_get_error();
1140 ERR_error_string_n(n
, (char *) p
, last
- p
);
1142 while (p
< last
&& *p
) {
1147 ngx_log_error(level
, log
, err
, "%s)", errstr
);
1152 ngx_ssl_session_cache(ngx_ssl_t
*ssl
, ngx_str_t
*sess_ctx
,
1153 ssize_t builtin_session_cache
, ngx_shm_zone_t
*shm_zone
, time_t timeout
)
1157 cache_mode
= SSL_SESS_CACHE_SERVER
;
1159 if (shm_zone
&& builtin_session_cache
== NGX_SSL_NO_BUILTIN_SCACHE
) {
1160 cache_mode
|= SSL_SESS_CACHE_NO_INTERNAL
;
1163 SSL_CTX_set_session_cache_mode(ssl
->ctx
, cache_mode
);
1165 SSL_CTX_set_session_id_context(ssl
->ctx
, sess_ctx
->data
, sess_ctx
->len
);
1167 if (builtin_session_cache
!= NGX_SSL_NO_BUILTIN_SCACHE
) {
1169 if (builtin_session_cache
!= NGX_SSL_DFLT_BUILTIN_SCACHE
) {
1170 SSL_CTX_sess_set_cache_size(ssl
->ctx
, builtin_session_cache
);
1174 SSL_CTX_set_timeout(ssl
->ctx
, timeout
);
1177 shm_zone
->init
= ngx_ssl_session_cache_init
;
1179 SSL_CTX_sess_set_new_cb(ssl
->ctx
, ngx_ssl_new_session
);
1180 SSL_CTX_sess_set_get_cb(ssl
->ctx
, ngx_ssl_get_cached_session
);
1181 SSL_CTX_sess_set_remove_cb(ssl
->ctx
, ngx_ssl_remove_session
);
1183 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_session_cache_index
, shm_zone
)
1186 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
1187 "SSL_CTX_set_ex_data() failed");
1197 ngx_ssl_session_cache_init(ngx_shm_zone_t
*shm_zone
, void *data
)
1199 ngx_slab_pool_t
*shpool
;
1200 ngx_rbtree_node_t
*sentinel
;
1201 ngx_ssl_session_cache_t
*cache
;
1204 shm_zone
->data
= data
;
1208 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1210 cache
= ngx_slab_alloc(shpool
, sizeof(ngx_ssl_session_cache_t
));
1211 if (cache
== NULL
) {
1215 cache
->session_cache_head
.prev
= NULL
;
1216 cache
->session_cache_head
.next
= &cache
->session_cache_tail
;
1218 cache
->session_cache_tail
.prev
= &cache
->session_cache_head
;
1219 cache
->session_cache_tail
.next
= NULL
;
1221 cache
->session_rbtree
= ngx_slab_alloc(shpool
, sizeof(ngx_rbtree_t
));
1222 if (cache
->session_rbtree
== NULL
) {
1226 sentinel
= ngx_slab_alloc(shpool
, sizeof(ngx_rbtree_node_t
));
1227 if (sentinel
== NULL
) {
1231 ngx_rbtree_sentinel_init(sentinel
);
1233 cache
->session_rbtree
->root
= sentinel
;
1234 cache
->session_rbtree
->sentinel
= sentinel
;
1235 cache
->session_rbtree
->insert
= ngx_ssl_session_rbtree_insert_value
;
1237 shm_zone
->data
= cache
;
1244 * The length of the session id is 16 bytes for SSLv2 sessions and
1245 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1246 * It seems that the typical length of the external ASN1 representation
1247 * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1249 * Thus on 32-bit platforms we allocate separately an rbtree node,
1250 * a session id, and an ASN1 representation, they take accordingly
1251 * 64, 32, and 128 bytes.
1253 * On 64-bit platforms we allocate separately an rbtree node + session_id,
1254 * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1256 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1257 * so they are outside the code locked by shared pool mutex
1261 ngx_ssl_new_session(ngx_ssl_conn_t
*ssl_conn
, ngx_ssl_session_t
*sess
)
1264 u_char
*p
, *id
, *cached_sess
;
1268 ngx_shm_zone_t
*shm_zone
;
1269 ngx_connection_t
*c
;
1270 ngx_slab_pool_t
*shpool
;
1271 ngx_ssl_sess_id_t
*sess_id
;
1272 ngx_ssl_session_cache_t
*cache
;
1273 u_char buf
[NGX_SSL_MAX_SESSION_SIZE
];
1275 len
= i2d_SSL_SESSION(sess
, NULL
);
1277 /* do not cache too big session */
1279 if (len
> (int) NGX_SSL_MAX_SESSION_SIZE
) {
1284 i2d_SSL_SESSION(sess
, &p
);
1286 c
= ngx_ssl_get_connection(ssl_conn
);
1288 ssl_ctx
= SSL_get_SSL_CTX(ssl_conn
);
1289 shm_zone
= SSL_CTX_get_ex_data(ssl_ctx
, ngx_ssl_session_cache_index
);
1291 cache
= shm_zone
->data
;
1292 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1294 ngx_shmtx_lock(&shpool
->mutex
);
1296 /* drop one or two expired sessions */
1297 ngx_ssl_expire_sessions(cache
, shpool
, 1);
1299 cached_sess
= ngx_slab_alloc_locked(shpool
, len
);
1301 if (cached_sess
== NULL
) {
1303 /* drop the oldest non-expired session and try once more */
1305 ngx_ssl_expire_sessions(cache
, shpool
, 0);
1307 cached_sess
= ngx_slab_alloc_locked(shpool
, len
);
1309 if (cached_sess
== NULL
) {
1315 sess_id
= ngx_slab_alloc_locked(shpool
, sizeof(ngx_ssl_sess_id_t
));
1316 if (sess_id
== NULL
) {
1320 #if (NGX_PTR_SIZE == 8)
1322 id
= sess_id
->sess_id
;
1326 id
= ngx_slab_alloc_locked(shpool
, sess
->session_id_length
);
1333 ngx_memcpy(cached_sess
, buf
, len
);
1335 ngx_memcpy(id
, sess
->session_id
, sess
->session_id_length
);
1337 hash
= ngx_crc32_short(sess
->session_id
, sess
->session_id_length
);
1339 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1340 "http ssl new session: %08XD:%d:%d",
1341 hash
, sess
->session_id_length
, len
);
1343 tp
= ngx_timeofday();
1345 sess_id
->node
.key
= hash
;
1346 sess_id
->node
.data
= (u_char
) sess
->session_id_length
;
1349 sess_id
->session
= cached_sess
;
1351 sess_id
->expire
= tp
->sec
+ SSL_CTX_get_timeout(ssl_ctx
);
1353 sess_id
->next
= cache
->session_cache_head
.next
;
1354 sess_id
->next
->prev
= sess_id
;
1355 sess_id
->prev
= &cache
->session_cache_head
;
1356 cache
->session_cache_head
.next
= sess_id
;
1358 ngx_rbtree_insert(cache
->session_rbtree
, &sess_id
->node
);
1360 ngx_shmtx_unlock(&shpool
->mutex
);
1367 ngx_slab_free_locked(shpool
, cached_sess
);
1371 ngx_slab_free_locked(shpool
, sess_id
);
1374 ngx_shmtx_unlock(&shpool
->mutex
);
1376 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
1377 "could not add new SSL session to the session cache");
1383 static ngx_ssl_session_t
*
1384 ngx_ssl_get_cached_session(ngx_ssl_conn_t
*ssl_conn
, u_char
*id
, int len
,
1387 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1394 ngx_shm_zone_t
*shm_zone
;
1395 ngx_slab_pool_t
*shpool
;
1396 ngx_connection_t
*c
;
1397 ngx_rbtree_node_t
*node
, *sentinel
;
1398 ngx_ssl_session_t
*sess
;
1399 ngx_ssl_sess_id_t
*sess_id
;
1400 ngx_ssl_session_cache_t
*cache
;
1401 u_char buf
[NGX_SSL_MAX_SESSION_SIZE
];
1403 c
= ngx_ssl_get_connection(ssl_conn
);
1405 hash
= ngx_crc32_short(id
, (size_t) len
);
1408 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
1409 "http ssl get session: %08XD:%d", hash
, len
);
1411 shm_zone
= SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn
),
1412 ngx_ssl_session_cache_index
);
1414 cache
= shm_zone
->data
;
1416 if (cache
->session_rbtree
== NULL
) {
1422 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1424 ngx_shmtx_lock(&shpool
->mutex
);
1426 node
= cache
->session_rbtree
->root
;
1427 sentinel
= cache
->session_rbtree
->sentinel
;
1429 while (node
!= sentinel
) {
1431 if (hash
< node
->key
) {
1436 if (hash
> node
->key
) {
1441 /* hash == node->key */
1444 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1446 rc
= ngx_memn2cmp(id
, sess_id
->id
,
1447 (size_t) len
, (size_t) node
->data
);
1450 tp
= ngx_timeofday();
1452 if (sess_id
->expire
> tp
->sec
) {
1453 ngx_memcpy(buf
, sess_id
->session
, sess_id
->len
);
1455 ngx_shmtx_unlock(&shpool
->mutex
);
1458 sess
= d2i_SSL_SESSION(NULL
, &p
, sess_id
->len
);
1463 sess_id
->next
->prev
= sess_id
->prev
;
1464 sess_id
->prev
->next
= sess_id
->next
;
1466 ngx_rbtree_delete(cache
->session_rbtree
, node
);
1468 ngx_slab_free_locked(shpool
, sess_id
->session
);
1469 #if (NGX_PTR_SIZE == 4)
1470 ngx_slab_free_locked(shpool
, sess_id
->id
);
1472 ngx_slab_free_locked(shpool
, sess_id
);
1479 node
= (rc
< 0) ? node
->left
: node
->right
;
1481 } while (node
!= sentinel
&& hash
== node
->key
);
1488 ngx_shmtx_unlock(&shpool
->mutex
);
1495 ngx_ssl_remove_session(SSL_CTX
*ssl
, ngx_ssl_session_t
*sess
)
1501 ngx_shm_zone_t
*shm_zone
;
1502 ngx_slab_pool_t
*shpool
;
1503 ngx_rbtree_node_t
*node
, *sentinel
;
1504 ngx_ssl_sess_id_t
*sess_id
;
1505 ngx_ssl_session_cache_t
*cache
;
1507 shm_zone
= SSL_CTX_get_ex_data(ssl
, ngx_ssl_session_cache_index
);
1509 cache
= shm_zone
->data
;
1511 id
= sess
->session_id
;
1512 len
= (size_t) sess
->session_id_length
;
1514 hash
= ngx_crc32_short(id
, len
);
1516 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ngx_cycle
->log
, 0,
1517 "http ssl remove session: %08XD:%uz", hash
, len
);
1519 shpool
= (ngx_slab_pool_t
*) shm_zone
->shm
.addr
;
1521 ngx_shmtx_lock(&shpool
->mutex
);
1523 node
= cache
->session_rbtree
->root
;
1524 sentinel
= cache
->session_rbtree
->sentinel
;
1526 while (node
!= sentinel
) {
1528 if (hash
< node
->key
) {
1533 if (hash
> node
->key
) {
1538 /* hash == node->key */
1541 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1543 rc
= ngx_memn2cmp(id
, sess_id
->id
, len
, (size_t) node
->data
);
1546 sess_id
->next
->prev
= sess_id
->prev
;
1547 sess_id
->prev
->next
= sess_id
->next
;
1549 ngx_rbtree_delete(cache
->session_rbtree
, node
);
1551 ngx_slab_free_locked(shpool
, sess_id
->session
);
1552 #if (NGX_PTR_SIZE == 4)
1553 ngx_slab_free_locked(shpool
, sess_id
->id
);
1555 ngx_slab_free_locked(shpool
, sess_id
);
1560 node
= (rc
< 0) ? node
->left
: node
->right
;
1562 } while (node
!= sentinel
&& hash
== node
->key
);
1569 ngx_shmtx_unlock(&shpool
->mutex
);
1574 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t
*cache
,
1575 ngx_slab_pool_t
*shpool
, ngx_uint_t n
)
1578 ngx_ssl_sess_id_t
*sess_id
;
1580 tp
= ngx_timeofday();
1584 sess_id
= cache
->session_cache_tail
.prev
;
1586 if (sess_id
== &cache
->session_cache_head
) {
1590 if (n
++ != 0 && sess_id
->expire
> tp
->sec
) {
1594 sess_id
->next
->prev
= sess_id
->prev
;
1595 sess_id
->prev
->next
= sess_id
->next
;
1597 ngx_rbtree_delete(cache
->session_rbtree
, &sess_id
->node
);
1599 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ngx_cycle
->log
, 0,
1600 "expire session: %08Xi", sess_id
->node
.key
);
1602 ngx_slab_free_locked(shpool
, sess_id
->session
);
1603 #if (NGX_PTR_SIZE == 4)
1604 ngx_slab_free_locked(shpool
, sess_id
->id
);
1606 ngx_slab_free_locked(shpool
, sess_id
);
1612 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
1613 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
)
1615 ngx_ssl_sess_id_t
*sess_id
, *sess_id_temp
;
1619 if (node
->key
< temp
->key
) {
1621 if (temp
->left
== sentinel
) {
1628 } else if (node
->key
> temp
->key
) {
1630 if (temp
->right
== sentinel
) {
1637 } else { /* node->key == temp->key */
1639 sess_id
= (ngx_ssl_sess_id_t
*) node
;
1640 sess_id_temp
= (ngx_ssl_sess_id_t
*) temp
;
1642 if (ngx_memn2cmp(sess_id
->id
, sess_id_temp
->id
,
1643 (size_t) node
->data
, (size_t) temp
->data
)
1646 if (temp
->left
== sentinel
) {
1655 if (temp
->right
== sentinel
) {
1665 node
->parent
= temp
;
1666 node
->left
= sentinel
;
1667 node
->right
= sentinel
;
1673 ngx_ssl_cleanup_ctx(void *data
)
1675 ngx_ssl_t
*ssl
= data
;
1677 SSL_CTX_free(ssl
->ctx
);
1682 ngx_ssl_get_protocol(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1684 s
->data
= (u_char
*) SSL_get_version(c
->ssl
->connection
);
1690 ngx_ssl_get_cipher_name(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1692 s
->data
= (u_char
*) SSL_get_cipher_name(c
->ssl
->connection
);
1698 ngx_ssl_get_subject_dn(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1707 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
1712 name
= X509_get_subject_name(cert
);
1717 p
= X509_NAME_oneline(name
, NULL
, 0);
1719 for (len
= 0; p
[len
]; len
++) { /* void */ }
1722 s
->data
= ngx_palloc(pool
, len
);
1723 if (s
->data
== NULL
) {
1728 ngx_memcpy(s
->data
, p
, len
);
1737 ngx_ssl_get_issuer_dn(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1746 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
1751 name
= X509_get_issuer_name(cert
);
1756 p
= X509_NAME_oneline(name
, NULL
, 0);
1758 for (len
= 0; p
[len
]; len
++) { /* void */ }
1761 s
->data
= ngx_palloc(pool
, len
);
1762 if (s
->data
== NULL
) {
1767 ngx_memcpy(s
->data
, p
, len
);
1776 ngx_ssl_get_serial_number(ngx_connection_t
*c
, ngx_pool_t
*pool
, ngx_str_t
*s
)
1784 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
1789 bio
= BIO_new(BIO_s_mem());
1794 i2a_ASN1_INTEGER(bio
, X509_get_serialNumber(cert
));
1795 len
= BIO_pending(bio
);
1798 s
->data
= ngx_palloc(pool
, len
);
1799 if (s
->data
== NULL
) {
1804 BIO_read(bio
, s
->data
, len
);
1812 ngx_openssl_create_conf(ngx_cycle_t
*cycle
)
1814 ngx_openssl_conf_t
*oscf
;
1816 oscf
= ngx_pcalloc(cycle
->pool
, sizeof(ngx_openssl_conf_t
));
1818 return NGX_CONF_ERROR
;
1822 * set by ngx_pcalloc():
1824 * oscf->engine.len = 0;
1825 * oscf->engine.data = NULL;
1833 ngx_openssl_init_conf(ngx_cycle_t
*cycle
, void *conf
)
1835 #if (NGX_SSL_ENGINE)
1836 ngx_openssl_conf_t
*oscf
= conf
;
1840 if (oscf
->engine
.len
== 0) {
1844 engine
= ENGINE_by_id((const char *) oscf
->engine
.data
);
1846 if (engine
== NULL
) {
1847 ngx_ssl_error(NGX_LOG_WARN
, cycle
->log
, 0,
1848 "ENGINE_by_id(\"%V\") failed", &oscf
->engine
);
1849 return NGX_CONF_ERROR
;
1852 if (ENGINE_set_default(engine
, ENGINE_METHOD_ALL
) == 0) {
1853 ngx_ssl_error(NGX_LOG_WARN
, cycle
->log
, 0,
1854 "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
1856 return NGX_CONF_ERROR
;
1859 ENGINE_free(engine
);
1867 #if !(NGX_SSL_ENGINE)
1870 ngx_openssl_noengine(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1872 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1873 "\"ssl_engine\" directive is available only in "
1874 "OpenSSL 0.9.7 and higher,");
1876 return NGX_CONF_ERROR
;
1883 ngx_openssl_exit(ngx_cycle_t
*cycle
)
1885 #if (NGX_SSL_ENGINE)