1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 
12 
13 #define NGX_SSL_PASSWORD_BUFFER_SIZE  4096
14 
15 
16 typedef struct {
17     ngx_uint_t  engine;   /* unsigned  engine:1; */
18 } ngx_openssl_conf_t;
19 
20 
21 static X509 *ngx_ssl_load_certificate(ngx_pool_t *pool, char **err,
22     ngx_str_t *cert, STACK_OF(X509) **chain);
23 static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
24     ngx_str_t *key, ngx_array_t *passwords);
25 static int ngx_ssl_password_callback(char *buf, int size, int rwflag,
26     void *userdata);
27 static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
28 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
29     int ret);
30 static void ngx_ssl_passwords_cleanup(void *data);
31 static int ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn,
32     ngx_ssl_session_t *sess);
33 #ifdef SSL_READ_EARLY_DATA_SUCCESS
34 static ngx_int_t ngx_ssl_try_early_data(ngx_connection_t *c);
35 #endif
36 #if (NGX_DEBUG)
37 static void ngx_ssl_handshake_log(ngx_connection_t *c);
38 #endif
39 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
40 #ifdef SSL_READ_EARLY_DATA_SUCCESS
41 static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf,
42     size_t size);
43 #endif
44 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
45 static void ngx_ssl_write_handler(ngx_event_t *wev);
46 #ifdef SSL_READ_EARLY_DATA_SUCCESS
47 static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data,
48     size_t size);
49 #endif
50 static void ngx_ssl_read_handler(ngx_event_t *rev);
51 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
52 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
53     ngx_err_t err, char *text);
54 static void ngx_ssl_clear_error(ngx_log_t *log);
55 
56 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
57     ngx_str_t *sess_ctx, ngx_array_t *certificates);
58 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
59     ngx_ssl_session_t *sess);
60 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
61 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
62     const
63 #endif
64     u_char *id, int len, int *copy);
65 static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
66 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
67     ngx_slab_pool_t *shpool, ngx_uint_t n);
68 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
69     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
70 
71 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
72 static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
73     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
74     HMAC_CTX *hctx, int enc);
75 static void ngx_ssl_session_ticket_keys_cleanup(void *data);
76 #endif
77 
78 #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
79 static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str);
80 #endif
81 
82 static time_t ngx_ssl_parse_time(
83 #if OPENSSL_VERSION_NUMBER > 0x10100000L
84     const
85 #endif
86     ASN1_TIME *asn1time, ngx_log_t *log);
87 
88 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
89 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
90 static void ngx_openssl_exit(ngx_cycle_t *cycle);
91 
92 
93 static ngx_command_t  ngx_openssl_commands[] = {
94 
95     { ngx_string("ssl_engine"),
96       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
97       ngx_openssl_engine,
98       0,
99       0,
100       NULL },
101 
102       ngx_null_command
103 };
104 
105 
106 static ngx_core_module_t  ngx_openssl_module_ctx = {
107     ngx_string("openssl"),
108     ngx_openssl_create_conf,
109     NULL
110 };
111 
112 
113 ngx_module_t  ngx_openssl_module = {
114     NGX_MODULE_V1,
115     &ngx_openssl_module_ctx,               /* module context */
116     ngx_openssl_commands,                  /* module directives */
117     NGX_CORE_MODULE,                       /* module type */
118     NULL,                                  /* init master */
119     NULL,                                  /* init module */
120     NULL,                                  /* init process */
121     NULL,                                  /* init thread */
122     NULL,                                  /* exit thread */
123     NULL,                                  /* exit process */
124     ngx_openssl_exit,                      /* exit master */
125     NGX_MODULE_V1_PADDING
126 };
127 
128 
129 int  ngx_ssl_connection_index;
130 int  ngx_ssl_server_conf_index;
131 int  ngx_ssl_session_cache_index;
132 int  ngx_ssl_session_ticket_keys_index;
133 int  ngx_ssl_ocsp_index;
134 int  ngx_ssl_certificate_index;
135 int  ngx_ssl_next_certificate_index;
136 int  ngx_ssl_certificate_name_index;
137 int  ngx_ssl_stapling_index;
138 
139 
140 ngx_int_t
ngx_ssl_init(ngx_log_t * log)141 ngx_ssl_init(ngx_log_t *log)
142 {
143 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
144 
145     if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) == 0) {
146         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "OPENSSL_init_ssl() failed");
147         return NGX_ERROR;
148     }
149 
150     /*
151      * OPENSSL_init_ssl() may leave errors in the error queue
152      * while returning success
153      */
154 
155     ERR_clear_error();
156 
157 #else
158 
159     OPENSSL_config(NULL);
160 
161     SSL_library_init();
162     SSL_load_error_strings();
163 
164     OpenSSL_add_all_algorithms();
165 
166 #endif
167 
168 #ifndef SSL_OP_NO_COMPRESSION
169     {
170     /*
171      * Disable gzip compression in OpenSSL prior to 1.0.0 version,
172      * this saves about 522K per connection.
173      */
174     int                  n;
175     STACK_OF(SSL_COMP)  *ssl_comp_methods;
176 
177     ssl_comp_methods = SSL_COMP_get_compression_methods();
178     n = sk_SSL_COMP_num(ssl_comp_methods);
179 
180     while (n--) {
181         (void) sk_SSL_COMP_pop(ssl_comp_methods);
182     }
183     }
184 #endif
185 
186     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
187 
188     if (ngx_ssl_connection_index == -1) {
189         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
190         return NGX_ERROR;
191     }
192 
193     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
194                                                          NULL);
195     if (ngx_ssl_server_conf_index == -1) {
196         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
197                       "SSL_CTX_get_ex_new_index() failed");
198         return NGX_ERROR;
199     }
200 
201     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
202                                                            NULL);
203     if (ngx_ssl_session_cache_index == -1) {
204         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
205                       "SSL_CTX_get_ex_new_index() failed");
206         return NGX_ERROR;
207     }
208 
209     ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
210                                                                  NULL, NULL);
211     if (ngx_ssl_session_ticket_keys_index == -1) {
212         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
213                       "SSL_CTX_get_ex_new_index() failed");
214         return NGX_ERROR;
215     }
216 
217     ngx_ssl_ocsp_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
218     if (ngx_ssl_ocsp_index == -1) {
219         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
220                       "SSL_CTX_get_ex_new_index() failed");
221         return NGX_ERROR;
222     }
223 
224     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
225                                                          NULL);
226     if (ngx_ssl_certificate_index == -1) {
227         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
228                       "SSL_CTX_get_ex_new_index() failed");
229         return NGX_ERROR;
230     }
231 
232     ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
233                                                            NULL);
234     if (ngx_ssl_next_certificate_index == -1) {
235         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
236         return NGX_ERROR;
237     }
238 
239     ngx_ssl_certificate_name_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
240                                                            NULL);
241 
242     if (ngx_ssl_certificate_name_index == -1) {
243         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
244         return NGX_ERROR;
245     }
246 
247     ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL);
248 
249     if (ngx_ssl_stapling_index == -1) {
250         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
251         return NGX_ERROR;
252     }
253 
254     return NGX_OK;
255 }
256 
257 
258 ngx_int_t
ngx_ssl_create(ngx_ssl_t * ssl,ngx_uint_t protocols,void * data)259 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
260 {
261     ssl->ctx = SSL_CTX_new(SSLv23_method());
262 
263     if (ssl->ctx == NULL) {
264         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
265         return NGX_ERROR;
266     }
267 
268     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
269         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
270                       "SSL_CTX_set_ex_data() failed");
271         return NGX_ERROR;
272     }
273 
274     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) {
275         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
276                       "SSL_CTX_set_ex_data() failed");
277         return NGX_ERROR;
278     }
279 
280     ssl->buffer_size = NGX_SSL_BUFSIZE;
281 
282     /* client side options */
283 
284 #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
285     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
286 #endif
287 
288 #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
289     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
290 #endif
291 
292     /* server side options */
293 
294 #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
295     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
296 #endif
297 
298 #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
299     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
300 #endif
301 
302 #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
303     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
304     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
305 #endif
306 
307 #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
308     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
309 #endif
310 
311 #ifdef SSL_OP_TLS_D5_BUG
312     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
313 #endif
314 
315 #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
316     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
317 #endif
318 
319 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
320     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
321 #endif
322 
323     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
324 
325 #if OPENSSL_VERSION_NUMBER >= 0x009080dfL
326     /* only in 0.9.8m+ */
327     SSL_CTX_clear_options(ssl->ctx,
328                           SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1);
329 #endif
330 
331     if (!(protocols & NGX_SSL_SSLv2)) {
332         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
333     }
334     if (!(protocols & NGX_SSL_SSLv3)) {
335         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
336     }
337     if (!(protocols & NGX_SSL_TLSv1)) {
338         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
339     }
340 #ifdef SSL_OP_NO_TLSv1_1
341     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
342     if (!(protocols & NGX_SSL_TLSv1_1)) {
343         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
344     }
345 #endif
346 #ifdef SSL_OP_NO_TLSv1_2
347     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
348     if (!(protocols & NGX_SSL_TLSv1_2)) {
349         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
350     }
351 #endif
352 #ifdef SSL_OP_NO_TLSv1_3
353     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_3);
354     if (!(protocols & NGX_SSL_TLSv1_3)) {
355         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_3);
356     }
357 #endif
358 
359 #ifdef SSL_CTX_set_min_proto_version
360     SSL_CTX_set_min_proto_version(ssl->ctx, 0);
361     SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_2_VERSION);
362 #endif
363 
364 #ifdef TLS1_3_VERSION
365     SSL_CTX_set_min_proto_version(ssl->ctx, 0);
366     SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_3_VERSION);
367 #endif
368 
369 #ifdef SSL_OP_NO_COMPRESSION
370     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
371 #endif
372 
373 #ifdef SSL_OP_NO_ANTI_REPLAY
374     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY);
375 #endif
376 
377 #ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
378     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
379 #endif
380 
381 #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
382     SSL_CTX_set_options(ssl->ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
383 #endif
384 
385 #ifdef SSL_MODE_RELEASE_BUFFERS
386     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
387 #endif
388 
389 #ifdef SSL_MODE_NO_AUTO_CHAIN
390     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_NO_AUTO_CHAIN);
391 #endif
392 
393     SSL_CTX_set_read_ahead(ssl->ctx, 1);
394 
395     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
396 
397     return NGX_OK;
398 }
399 
400 
401 ngx_int_t
ngx_ssl_certificates(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_array_t * certs,ngx_array_t * keys,ngx_array_t * passwords)402 ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
403     ngx_array_t *keys, ngx_array_t *passwords)
404 {
405     ngx_str_t   *cert, *key;
406     ngx_uint_t   i;
407 
408     cert = certs->elts;
409     key = keys->elts;
410 
411     for (i = 0; i < certs->nelts; i++) {
412 
413         if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords)
414             != NGX_OK)
415         {
416             return NGX_ERROR;
417         }
418     }
419 
420     return NGX_OK;
421 }
422 
423 
424 ngx_int_t
ngx_ssl_certificate(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * cert,ngx_str_t * key,ngx_array_t * passwords)425 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
426     ngx_str_t *key, ngx_array_t *passwords)
427 {
428     char            *err;
429     X509            *x509;
430     EVP_PKEY        *pkey;
431     STACK_OF(X509)  *chain;
432 
433     x509 = ngx_ssl_load_certificate(cf->pool, &err, cert, &chain);
434     if (x509 == NULL) {
435         if (err != NULL) {
436             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
437                           "cannot load certificate \"%s\": %s",
438                           cert->data, err);
439         }
440 
441         return NGX_ERROR;
442     }
443 
444     if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
445         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
446                       "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
447         X509_free(x509);
448         sk_X509_pop_free(chain, X509_free);
449         return NGX_ERROR;
450     }
451 
452     if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data)
453         == 0)
454     {
455         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
456         X509_free(x509);
457         sk_X509_pop_free(chain, X509_free);
458         return NGX_ERROR;
459     }
460 
461     if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index,
462                       SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index))
463         == 0)
464     {
465         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
466         X509_free(x509);
467         sk_X509_pop_free(chain, X509_free);
468         return NGX_ERROR;
469     }
470 
471     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) {
472         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
473                       "SSL_CTX_set_ex_data() failed");
474         X509_free(x509);
475         sk_X509_pop_free(chain, X509_free);
476         return NGX_ERROR;
477     }
478 
479     /*
480      * Note that x509 is not freed here, but will be instead freed in
481      * ngx_ssl_cleanup_ctx().  This is because we need to preserve all
482      * certificates to be able to iterate all of them through exdata
483      * (ngx_ssl_certificate_index, ngx_ssl_next_certificate_index),
484      * while OpenSSL can free a certificate if it is replaced with another
485      * certificate of the same type.
486      */
487 
488 #ifdef SSL_CTX_set0_chain
489 
490     if (SSL_CTX_set0_chain(ssl->ctx, chain) == 0) {
491         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
492                       "SSL_CTX_set0_chain(\"%s\") failed", cert->data);
493         sk_X509_pop_free(chain, X509_free);
494         return NGX_ERROR;
495     }
496 
497 #else
498     {
499     int  n;
500 
501     /* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */
502 
503     n = sk_X509_num(chain);
504 
505     while (n--) {
506         x509 = sk_X509_shift(chain);
507 
508         if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
509             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
510                           "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
511                           cert->data);
512             sk_X509_pop_free(chain, X509_free);
513             return NGX_ERROR;
514         }
515     }
516 
517     sk_X509_free(chain);
518     }
519 #endif
520 
521     pkey = ngx_ssl_load_certificate_key(cf->pool, &err, key, passwords);
522     if (pkey == NULL) {
523         if (err != NULL) {
524             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
525                           "cannot load certificate key \"%s\": %s",
526                           key->data, err);
527         }
528 
529         return NGX_ERROR;
530     }
531 
532     if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
533         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
534                       "SSL_CTX_use_PrivateKey(\"%s\") failed", key->data);
535         EVP_PKEY_free(pkey);
536         return NGX_ERROR;
537     }
538 
539     EVP_PKEY_free(pkey);
540 
541     return NGX_OK;
542 }
543 
544 
545 ngx_int_t
ngx_ssl_connection_certificate(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * cert,ngx_str_t * key,ngx_array_t * passwords)546 ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
547     ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords)
548 {
549     char            *err;
550     X509            *x509;
551     EVP_PKEY        *pkey;
552     STACK_OF(X509)  *chain;
553 
554     x509 = ngx_ssl_load_certificate(pool, &err, cert, &chain);
555     if (x509 == NULL) {
556         if (err != NULL) {
557             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
558                           "cannot load certificate \"%s\": %s",
559                           cert->data, err);
560         }
561 
562         return NGX_ERROR;
563     }
564 
565     if (SSL_use_certificate(c->ssl->connection, x509) == 0) {
566         ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
567                       "SSL_use_certificate(\"%s\") failed", cert->data);
568         X509_free(x509);
569         sk_X509_pop_free(chain, X509_free);
570         return NGX_ERROR;
571     }
572 
573     X509_free(x509);
574 
575 #ifdef SSL_set0_chain
576 
577     /*
578      * SSL_set0_chain() is only available in OpenSSL 1.0.2+,
579      * but this function is only called via certificate callback,
580      * which is only available in OpenSSL 1.0.2+ as well
581      */
582 
583     if (SSL_set0_chain(c->ssl->connection, chain) == 0) {
584         ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
585                       "SSL_set0_chain(\"%s\") failed", cert->data);
586         sk_X509_pop_free(chain, X509_free);
587         return NGX_ERROR;
588     }
589 
590 #endif
591 
592     pkey = ngx_ssl_load_certificate_key(pool, &err, key, passwords);
593     if (pkey == NULL) {
594         if (err != NULL) {
595             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
596                           "cannot load certificate key \"%s\": %s",
597                           key->data, err);
598         }
599 
600         return NGX_ERROR;
601     }
602 
603     if (SSL_use_PrivateKey(c->ssl->connection, pkey) == 0) {
604         ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
605                       "SSL_use_PrivateKey(\"%s\") failed", key->data);
606         EVP_PKEY_free(pkey);
607         return NGX_ERROR;
608     }
609 
610     EVP_PKEY_free(pkey);
611 
612     return NGX_OK;
613 }
614 
615 
616 static X509 *
ngx_ssl_load_certificate(ngx_pool_t * pool,char ** err,ngx_str_t * cert,STACK_OF (X509)** chain)617 ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert,
618     STACK_OF(X509) **chain)
619 {
620     BIO     *bio;
621     X509    *x509, *temp;
622     u_long   n;
623 
624     if (ngx_strncmp(cert->data, "data:", sizeof("data:") - 1) == 0) {
625 
626         bio = BIO_new_mem_buf(cert->data + sizeof("data:") - 1,
627                               cert->len - (sizeof("data:") - 1));
628         if (bio == NULL) {
629             *err = "BIO_new_mem_buf() failed";
630             return NULL;
631         }
632 
633     } else {
634 
635         if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, cert)
636             != NGX_OK)
637         {
638             *err = NULL;
639             return NULL;
640         }
641 
642         bio = BIO_new_file((char *) cert->data, "r");
643         if (bio == NULL) {
644             *err = "BIO_new_file() failed";
645             return NULL;
646         }
647     }
648 
649     /* certificate itself */
650 
651     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
652     if (x509 == NULL) {
653         *err = "PEM_read_bio_X509_AUX() failed";
654         BIO_free(bio);
655         return NULL;
656     }
657 
658     /* rest of the chain */
659 
660     *chain = sk_X509_new_null();
661     if (*chain == NULL) {
662         *err = "sk_X509_new_null() failed";
663         BIO_free(bio);
664         X509_free(x509);
665         return NULL;
666     }
667 
668     for ( ;; ) {
669 
670         temp = PEM_read_bio_X509(bio, NULL, NULL, NULL);
671         if (temp == NULL) {
672             n = ERR_peek_last_error();
673 
674             if (ERR_GET_LIB(n) == ERR_LIB_PEM
675                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
676             {
677                 /* end of file */
678                 ERR_clear_error();
679                 break;
680             }
681 
682             /* some real error */
683 
684             *err = "PEM_read_bio_X509() failed";
685             BIO_free(bio);
686             X509_free(x509);
687             sk_X509_pop_free(*chain, X509_free);
688             return NULL;
689         }
690 
691         if (sk_X509_push(*chain, temp) == 0) {
692             *err = "sk_X509_push() failed";
693             BIO_free(bio);
694             X509_free(x509);
695             sk_X509_pop_free(*chain, X509_free);
696             return NULL;
697         }
698     }
699 
700     BIO_free(bio);
701 
702     return x509;
703 }
704 
705 
706 static EVP_PKEY *
ngx_ssl_load_certificate_key(ngx_pool_t * pool,char ** err,ngx_str_t * key,ngx_array_t * passwords)707 ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
708     ngx_str_t *key, ngx_array_t *passwords)
709 {
710     BIO              *bio;
711     EVP_PKEY         *pkey;
712     ngx_str_t        *pwd;
713     ngx_uint_t        tries;
714     pem_password_cb  *cb;
715 
716     if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) {
717 
718 #ifndef OPENSSL_NO_ENGINE
719 
720         u_char  *p, *last;
721         ENGINE  *engine;
722 
723         p = key->data + sizeof("engine:") - 1;
724         last = (u_char *) ngx_strchr(p, ':');
725 
726         if (last == NULL) {
727             *err = "invalid syntax";
728             return NULL;
729         }
730 
731         *last = '\0';
732 
733         engine = ENGINE_by_id((char *) p);
734 
735         if (engine == NULL) {
736             *err = "ENGINE_by_id() failed";
737             return NULL;
738         }
739 
740         *last++ = ':';
741 
742         pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);
743 
744         if (pkey == NULL) {
745             *err = "ENGINE_load_private_key() failed";
746             ENGINE_free(engine);
747             return NULL;
748         }
749 
750         ENGINE_free(engine);
751 
752         return pkey;
753 
754 #else
755 
756         *err = "loading \"engine:...\" certificate keys is not supported";
757         return NULL;
758 
759 #endif
760     }
761 
762     if (ngx_strncmp(key->data, "data:", sizeof("data:") - 1) == 0) {
763 
764         bio = BIO_new_mem_buf(key->data + sizeof("data:") - 1,
765                               key->len - (sizeof("data:") - 1));
766         if (bio == NULL) {
767             *err = "BIO_new_mem_buf() failed";
768             return NULL;
769         }
770 
771     } else {
772 
773         if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, key)
774             != NGX_OK)
775         {
776             *err = NULL;
777             return NULL;
778         }
779 
780         bio = BIO_new_file((char *) key->data, "r");
781         if (bio == NULL) {
782             *err = "BIO_new_file() failed";
783             return NULL;
784         }
785     }
786 
787     if (passwords) {
788         tries = passwords->nelts;
789         pwd = passwords->elts;
790         cb = ngx_ssl_password_callback;
791 
792     } else {
793         tries = 1;
794         pwd = NULL;
795         cb = NULL;
796     }
797 
798     for ( ;; ) {
799 
800         pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
801         if (pkey != NULL) {
802             break;
803         }
804 
805         if (tries-- > 1) {
806             ERR_clear_error();
807             (void) BIO_reset(bio);
808             pwd++;
809             continue;
810         }
811 
812         *err = "PEM_read_bio_PrivateKey() failed";
813         BIO_free(bio);
814         return NULL;
815     }
816 
817     BIO_free(bio);
818 
819     return pkey;
820 }
821 
822 
823 static int
ngx_ssl_password_callback(char * buf,int size,int rwflag,void * userdata)824 ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
825 {
826     ngx_str_t *pwd = userdata;
827 
828     if (rwflag) {
829         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
830                       "ngx_ssl_password_callback() is called for encryption");
831         return 0;
832     }
833 
834     if (pwd == NULL) {
835         return 0;
836     }
837 
838     if (pwd->len > (size_t) size) {
839         ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
840                       "password is truncated to %d bytes", size);
841     } else {
842         size = pwd->len;
843     }
844 
845     ngx_memcpy(buf, pwd->data, size);
846 
847     return size;
848 }
849 
850 
851 ngx_int_t
ngx_ssl_ciphers(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * ciphers,ngx_uint_t prefer_server_ciphers)852 ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
853     ngx_uint_t prefer_server_ciphers)
854 {
855     if (SSL_CTX_set_cipher_list(ssl->ctx, (char *) ciphers->data) == 0) {
856         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
857                       "SSL_CTX_set_cipher_list(\"%V\") failed",
858                       ciphers);
859         return NGX_ERROR;
860     }
861 
862     if (prefer_server_ciphers) {
863         SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
864     }
865 
866 #if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
867     /* a temporary 512-bit RSA key is required for export versions of MSIE */
868     SSL_CTX_set_tmp_rsa_callback(ssl->ctx, ngx_ssl_rsa512_key_callback);
869 #endif
870 
871     return NGX_OK;
872 }
873 
874 
875 ngx_int_t
ngx_ssl_client_certificate(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * cert,ngx_int_t depth)876 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
877     ngx_int_t depth)
878 {
879     STACK_OF(X509_NAME)  *list;
880 
881     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_ssl_verify_callback);
882 
883     SSL_CTX_set_verify_depth(ssl->ctx, depth);
884 
885     if (cert->len == 0) {
886         return NGX_OK;
887     }
888 
889     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
890         return NGX_ERROR;
891     }
892 
893     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
894         == 0)
895     {
896         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
897                       "SSL_CTX_load_verify_locations(\"%s\") failed",
898                       cert->data);
899         return NGX_ERROR;
900     }
901 
902     /*
903      * SSL_CTX_load_verify_locations() may leave errors in the error queue
904      * while returning success
905      */
906 
907     ERR_clear_error();
908 
909     list = SSL_load_client_CA_file((char *) cert->data);
910 
911     if (list == NULL) {
912         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
913                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
914         return NGX_ERROR;
915     }
916 
917     SSL_CTX_set_client_CA_list(ssl->ctx, list);
918 
919     return NGX_OK;
920 }
921 
922 
923 ngx_int_t
ngx_ssl_trusted_certificate(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * cert,ngx_int_t depth)924 ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
925     ngx_int_t depth)
926 {
927     SSL_CTX_set_verify(ssl->ctx, SSL_CTX_get_verify_mode(ssl->ctx),
928                        ngx_ssl_verify_callback);
929 
930     SSL_CTX_set_verify_depth(ssl->ctx, depth);
931 
932     if (cert->len == 0) {
933         return NGX_OK;
934     }
935 
936     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
937         return NGX_ERROR;
938     }
939 
940     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
941         == 0)
942     {
943         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
944                       "SSL_CTX_load_verify_locations(\"%s\") failed",
945                       cert->data);
946         return NGX_ERROR;
947     }
948 
949     /*
950      * SSL_CTX_load_verify_locations() may leave errors in the error queue
951      * while returning success
952      */
953 
954     ERR_clear_error();
955 
956     return NGX_OK;
957 }
958 
959 
960 ngx_int_t
ngx_ssl_crl(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * crl)961 ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
962 {
963     X509_STORE   *store;
964     X509_LOOKUP  *lookup;
965 
966     if (crl->len == 0) {
967         return NGX_OK;
968     }
969 
970     if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
971         return NGX_ERROR;
972     }
973 
974     store = SSL_CTX_get_cert_store(ssl->ctx);
975 
976     if (store == NULL) {
977         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
978                       "SSL_CTX_get_cert_store() failed");
979         return NGX_ERROR;
980     }
981 
982     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
983 
984     if (lookup == NULL) {
985         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
986                       "X509_STORE_add_lookup() failed");
987         return NGX_ERROR;
988     }
989 
990     if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
991         == 0)
992     {
993         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
994                       "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
995         return NGX_ERROR;
996     }
997 
998     X509_STORE_set_flags(store,
999                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1000 
1001     return NGX_OK;
1002 }
1003 
1004 
1005 static int
ngx_ssl_verify_callback(int ok,X509_STORE_CTX * x509_store)1006 ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
1007 {
1008 #if (NGX_DEBUG)
1009     char              *subject, *issuer;
1010     int                err, depth;
1011     X509              *cert;
1012     X509_NAME         *sname, *iname;
1013     ngx_connection_t  *c;
1014     ngx_ssl_conn_t    *ssl_conn;
1015 
1016     ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
1017                                           SSL_get_ex_data_X509_STORE_CTX_idx());
1018 
1019     c = ngx_ssl_get_connection(ssl_conn);
1020 
1021     if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) {
1022         return 1;
1023     }
1024 
1025     cert = X509_STORE_CTX_get_current_cert(x509_store);
1026     err = X509_STORE_CTX_get_error(x509_store);
1027     depth = X509_STORE_CTX_get_error_depth(x509_store);
1028 
1029     sname = X509_get_subject_name(cert);
1030 
1031     if (sname) {
1032         subject = X509_NAME_oneline(sname, NULL, 0);
1033         if (subject == NULL) {
1034             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
1035                           "X509_NAME_oneline() failed");
1036         }
1037 
1038     } else {
1039         subject = NULL;
1040     }
1041 
1042     iname = X509_get_issuer_name(cert);
1043 
1044     if (iname) {
1045         issuer = X509_NAME_oneline(iname, NULL, 0);
1046         if (issuer == NULL) {
1047             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
1048                           "X509_NAME_oneline() failed");
1049         }
1050 
1051     } else {
1052         issuer = NULL;
1053     }
1054 
1055     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
1056                    "verify:%d, error:%d, depth:%d, "
1057                    "subject:\"%s\", issuer:\"%s\"",
1058                    ok, err, depth,
1059                    subject ? subject : "(none)",
1060                    issuer ? issuer : "(none)");
1061 
1062     if (subject) {
1063         OPENSSL_free(subject);
1064     }
1065 
1066     if (issuer) {
1067         OPENSSL_free(issuer);
1068     }
1069 #endif
1070 
1071     return 1;
1072 }
1073 
1074 
1075 static void
ngx_ssl_info_callback(const ngx_ssl_conn_t * ssl_conn,int where,int ret)1076 ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
1077 {
1078     BIO               *rbio, *wbio;
1079     ngx_connection_t  *c;
1080 
1081 #ifndef SSL_OP_NO_RENEGOTIATION
1082 
1083     if ((where & SSL_CB_HANDSHAKE_START)
1084         && SSL_is_server((ngx_ssl_conn_t *) ssl_conn))
1085     {
1086         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
1087 
1088         if (c->ssl->handshaked) {
1089             c->ssl->renegotiation = 1;
1090             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
1091         }
1092     }
1093 
1094 #endif
1095 
1096     if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1097         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
1098 
1099         if (!c->ssl->handshake_buffer_set) {
1100             /*
1101              * By default OpenSSL uses 4k buffer during a handshake,
1102              * which is too low for long certificate chains and might
1103              * result in extra round-trips.
1104              *
1105              * To adjust a buffer size we detect that buffering was added
1106              * to write side of the connection by comparing rbio and wbio.
1107              * If they are different, we assume that it's due to buffering
1108              * added to wbio, and set buffer size.
1109              */
1110 
1111             rbio = SSL_get_rbio(ssl_conn);
1112             wbio = SSL_get_wbio(ssl_conn);
1113 
1114             if (rbio != wbio) {
1115                 (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE);
1116                 c->ssl->handshake_buffer_set = 1;
1117             }
1118         }
1119     }
1120 }
1121 
1122 
1123 #if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
1124 
1125 RSA *
ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t * ssl_conn,int is_export,int key_length)1126 ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
1127     int key_length)
1128 {
1129     static RSA  *key;
1130 
1131     if (key_length != 512) {
1132         return NULL;
1133     }
1134 
1135 #ifndef OPENSSL_NO_DEPRECATED
1136 
1137     if (key == NULL) {
1138         key = RSA_generate_key(512, RSA_F4, NULL, NULL);
1139     }
1140 
1141 #endif
1142 
1143     return key;
1144 }
1145 
1146 #endif
1147 
1148 
1149 ngx_array_t *
ngx_ssl_read_password_file(ngx_conf_t * cf,ngx_str_t * file)1150 ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
1151 {
1152     u_char              *p, *last, *end;
1153     size_t               len;
1154     ssize_t              n;
1155     ngx_fd_t             fd;
1156     ngx_str_t           *pwd;
1157     ngx_array_t         *passwords;
1158     ngx_pool_cleanup_t  *cln;
1159     u_char               buf[NGX_SSL_PASSWORD_BUFFER_SIZE];
1160 
1161     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
1162         return NULL;
1163     }
1164 
1165     passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
1166     if (passwords == NULL) {
1167         return NULL;
1168     }
1169 
1170     cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
1171     if (cln == NULL) {
1172         return NULL;
1173     }
1174 
1175     cln->handler = ngx_ssl_passwords_cleanup;
1176     cln->data = passwords;
1177 
1178     fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
1179 
1180     if (fd == NGX_INVALID_FILE) {
1181         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1182                            ngx_open_file_n " \"%s\" failed", file->data);
1183         return NULL;
1184     }
1185 
1186     len = 0;
1187     last = buf;
1188 
1189     do {
1190         n = ngx_read_fd(fd, last, NGX_SSL_PASSWORD_BUFFER_SIZE - len);
1191 
1192         if (n == -1) {
1193             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1194                                ngx_read_fd_n " \"%s\" failed", file->data);
1195             passwords = NULL;
1196             goto cleanup;
1197         }
1198 
1199         end = last + n;
1200 
1201         if (len && n == 0) {
1202             *end++ = LF;
1203         }
1204 
1205         p = buf;
1206 
1207         for ( ;; ) {
1208             last = ngx_strlchr(last, end, LF);
1209 
1210             if (last == NULL) {
1211                 break;
1212             }
1213 
1214             len = last++ - p;
1215 
1216             if (len && p[len - 1] == CR) {
1217                 len--;
1218             }
1219 
1220             if (len) {
1221                 pwd = ngx_array_push(passwords);
1222                 if (pwd == NULL) {
1223                     passwords = NULL;
1224                     goto cleanup;
1225                 }
1226 
1227                 pwd->len = len;
1228                 pwd->data = ngx_pnalloc(cf->temp_pool, len);
1229 
1230                 if (pwd->data == NULL) {
1231                     passwords->nelts--;
1232                     passwords = NULL;
1233                     goto cleanup;
1234                 }
1235 
1236                 ngx_memcpy(pwd->data, p, len);
1237             }
1238 
1239             p = last;
1240         }
1241 
1242         len = end - p;
1243 
1244         if (len == NGX_SSL_PASSWORD_BUFFER_SIZE) {
1245             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1246                                "too long line in \"%s\"", file->data);
1247             passwords = NULL;
1248             goto cleanup;
1249         }
1250 
1251         ngx_memmove(buf, p, len);
1252         last = buf + len;
1253 
1254     } while (n != 0);
1255 
1256     if (passwords->nelts == 0) {
1257         pwd = ngx_array_push(passwords);
1258         if (pwd == NULL) {
1259             passwords = NULL;
1260             goto cleanup;
1261         }
1262 
1263         ngx_memzero(pwd, sizeof(ngx_str_t));
1264     }
1265 
1266 cleanup:
1267 
1268     if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1269         ngx_conf_log_error(NGX_LOG_ALERT, cf, ngx_errno,
1270                            ngx_close_file_n " \"%s\" failed", file->data);
1271     }
1272 
1273     ngx_explicit_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);
1274 
1275     return passwords;
1276 }
1277 
1278 
1279 ngx_array_t *
ngx_ssl_preserve_passwords(ngx_conf_t * cf,ngx_array_t * passwords)1280 ngx_ssl_preserve_passwords(ngx_conf_t *cf, ngx_array_t *passwords)
1281 {
1282     ngx_str_t           *opwd, *pwd;
1283     ngx_uint_t           i;
1284     ngx_array_t         *pwds;
1285     ngx_pool_cleanup_t  *cln;
1286     static ngx_array_t   empty_passwords;
1287 
1288     if (passwords == NULL) {
1289 
1290         /*
1291          * If there are no passwords, an empty array is used
1292          * to make sure OpenSSL's default password callback
1293          * won't block on reading from stdin.
1294          */
1295 
1296         return &empty_passwords;
1297     }
1298 
1299     /*
1300      * Passwords are normally allocated from the temporary pool
1301      * and cleared after parsing configuration.  To be used at
1302      * runtime they have to be copied to the configuration pool.
1303      */
1304 
1305     pwds = ngx_array_create(cf->pool, passwords->nelts, sizeof(ngx_str_t));
1306     if (pwds == NULL) {
1307         return NULL;
1308     }
1309 
1310     cln = ngx_pool_cleanup_add(cf->pool, 0);
1311     if (cln == NULL) {
1312         return NULL;
1313     }
1314 
1315     cln->handler = ngx_ssl_passwords_cleanup;
1316     cln->data = pwds;
1317 
1318     opwd = passwords->elts;
1319 
1320     for (i = 0; i < passwords->nelts; i++) {
1321 
1322         pwd = ngx_array_push(pwds);
1323         if (pwd == NULL) {
1324             return NULL;
1325         }
1326 
1327         pwd->len = opwd[i].len;
1328         pwd->data = ngx_pnalloc(cf->pool, pwd->len);
1329 
1330         if (pwd->data == NULL) {
1331             pwds->nelts--;
1332             return NULL;
1333         }
1334 
1335         ngx_memcpy(pwd->data, opwd[i].data, opwd[i].len);
1336     }
1337 
1338     return pwds;
1339 }
1340 
1341 
1342 static void
ngx_ssl_passwords_cleanup(void * data)1343 ngx_ssl_passwords_cleanup(void *data)
1344 {
1345     ngx_array_t *passwords = data;
1346 
1347     ngx_str_t   *pwd;
1348     ngx_uint_t   i;
1349 
1350     pwd = passwords->elts;
1351 
1352     for (i = 0; i < passwords->nelts; i++) {
1353         ngx_explicit_memzero(pwd[i].data, pwd[i].len);
1354     }
1355 }
1356 
1357 
1358 ngx_int_t
ngx_ssl_dhparam(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * file)1359 ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
1360 {
1361     BIO  *bio;
1362 
1363     if (file->len == 0) {
1364         return NGX_OK;
1365     }
1366 
1367     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
1368         return NGX_ERROR;
1369     }
1370 
1371     bio = BIO_new_file((char *) file->data, "r");
1372     if (bio == NULL) {
1373         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1374                       "BIO_new_file(\"%s\") failed", file->data);
1375         return NGX_ERROR;
1376     }
1377 
1378 #ifdef SSL_CTX_set_tmp_dh
1379     {
1380     DH  *dh;
1381 
1382     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1383     if (dh == NULL) {
1384         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1385                       "PEM_read_bio_DHparams(\"%s\") failed", file->data);
1386         BIO_free(bio);
1387         return NGX_ERROR;
1388     }
1389 
1390     if (SSL_CTX_set_tmp_dh(ssl->ctx, dh) != 1) {
1391         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1392                       "SSL_CTX_set_tmp_dh(\"%s\") failed", file->data);
1393         DH_free(dh);
1394         BIO_free(bio);
1395         return NGX_ERROR;
1396     }
1397 
1398     DH_free(dh);
1399     }
1400 #else
1401     {
1402     EVP_PKEY  *dh;
1403 
1404     /*
1405      * PEM_read_bio_DHparams() and SSL_CTX_set_tmp_dh()
1406      * are deprecated in OpenSSL 3.0
1407      */
1408 
1409     dh = PEM_read_bio_Parameters(bio, NULL);
1410     if (dh == NULL) {
1411         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1412                       "PEM_read_bio_Parameters(\"%s\") failed", file->data);
1413         BIO_free(bio);
1414         return NGX_ERROR;
1415     }
1416 
1417     if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) {
1418         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1419                       "SSL_CTX_set0_tmp_dh_pkey(\%s\") failed", file->data);
1420         BIO_free(bio);
1421         return NGX_ERROR;
1422     }
1423     }
1424 #endif
1425 
1426     BIO_free(bio);
1427 
1428     return NGX_OK;
1429 }
1430 
1431 
1432 ngx_int_t
ngx_ssl_ecdh_curve(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * name)1433 ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
1434 {
1435 #ifndef OPENSSL_NO_ECDH
1436 
1437     /*
1438      * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
1439      * from RFC 4492 section 5.1.1, or explicitly described curves over
1440      * binary fields.  OpenSSL only supports the "named curves", which provide
1441      * maximum interoperability.
1442      */
1443 
1444 #if (defined SSL_CTX_set1_curves_list || defined SSL_CTRL_SET_CURVES_LIST)
1445 
1446     /*
1447      * OpenSSL 1.0.2+ allows configuring a curve list instead of a single
1448      * curve previously supported.  By default an internal list is used,
1449      * with prime256v1 being preferred by server in OpenSSL 1.0.2b+
1450      * and X25519 in OpenSSL 1.1.0+.
1451      *
1452      * By default a curve preferred by the client will be used for
1453      * key exchange.  The SSL_OP_CIPHER_SERVER_PREFERENCE option can
1454      * be used to prefer server curves instead, similar to what it
1455      * does for ciphers.
1456      */
1457 
1458     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
1459 
1460 #if SSL_CTRL_SET_ECDH_AUTO
1461     /* not needed in OpenSSL 1.1.0+ */
1462     SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
1463 #endif
1464 
1465     if (ngx_strcmp(name->data, "auto") == 0) {
1466         return NGX_OK;
1467     }
1468 
1469     if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) {
1470         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1471                       "SSL_CTX_set1_curves_list(\"%s\") failed", name->data);
1472         return NGX_ERROR;
1473     }
1474 
1475 #else
1476 
1477     int      nid;
1478     char    *curve;
1479     EC_KEY  *ecdh;
1480 
1481     if (ngx_strcmp(name->data, "auto") == 0) {
1482         curve = "prime256v1";
1483 
1484     } else {
1485         curve = (char *) name->data;
1486     }
1487 
1488     nid = OBJ_sn2nid(curve);
1489     if (nid == 0) {
1490         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1491                       "OBJ_sn2nid(\"%s\") failed: unknown curve", curve);
1492         return NGX_ERROR;
1493     }
1494 
1495     ecdh = EC_KEY_new_by_curve_name(nid);
1496     if (ecdh == NULL) {
1497         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1498                       "EC_KEY_new_by_curve_name(\"%s\") failed", curve);
1499         return NGX_ERROR;
1500     }
1501 
1502     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
1503 
1504     SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
1505 
1506     EC_KEY_free(ecdh);
1507 #endif
1508 #endif
1509 
1510     return NGX_OK;
1511 }
1512 
1513 
1514 ngx_int_t
ngx_ssl_early_data(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_uint_t enable)1515 ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable)
1516 {
1517     if (!enable) {
1518         return NGX_OK;
1519     }
1520 
1521 #ifdef SSL_ERROR_EARLY_DATA_REJECTED
1522 
1523     /* BoringSSL */
1524 
1525     SSL_CTX_set_early_data_enabled(ssl->ctx, 1);
1526 
1527 #elif defined SSL_READ_EARLY_DATA_SUCCESS
1528 
1529     /* OpenSSL */
1530 
1531     SSL_CTX_set_max_early_data(ssl->ctx, NGX_SSL_BUFSIZE);
1532 
1533 #else
1534     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1535                   "\"ssl_early_data\" is not supported on this platform, "
1536                   "ignored");
1537 #endif
1538 
1539     return NGX_OK;
1540 }
1541 
1542 
1543 ngx_int_t
ngx_ssl_conf_commands(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_array_t * commands)1544 ngx_ssl_conf_commands(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *commands)
1545 {
1546     if (commands == NULL) {
1547         return NGX_OK;
1548     }
1549 
1550 #ifdef SSL_CONF_FLAG_FILE
1551     {
1552     int            type;
1553     u_char        *key, *value;
1554     ngx_uint_t     i;
1555     ngx_keyval_t  *cmd;
1556     SSL_CONF_CTX  *cctx;
1557 
1558     cctx = SSL_CONF_CTX_new();
1559     if (cctx == NULL) {
1560         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1561                       "SSL_CONF_CTX_new() failed");
1562         return NGX_ERROR;
1563     }
1564 
1565     SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
1566     SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
1567     SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
1568     SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
1569     SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
1570 
1571     SSL_CONF_CTX_set_ssl_ctx(cctx, ssl->ctx);
1572 
1573     cmd = commands->elts;
1574     for (i = 0; i < commands->nelts; i++) {
1575 
1576         key = cmd[i].key.data;
1577         type = SSL_CONF_cmd_value_type(cctx, (char *) key);
1578 
1579         if (type == SSL_CONF_TYPE_FILE || type == SSL_CONF_TYPE_DIR) {
1580             if (ngx_conf_full_name(cf->cycle, &cmd[i].value, 1) != NGX_OK) {
1581                 SSL_CONF_CTX_free(cctx);
1582                 return NGX_ERROR;
1583             }
1584         }
1585 
1586         value = cmd[i].value.data;
1587 
1588         if (SSL_CONF_cmd(cctx, (char *) key, (char *) value) <= 0) {
1589             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1590                           "SSL_CONF_cmd(\"%s\", \"%s\") failed", key, value);
1591             SSL_CONF_CTX_free(cctx);
1592             return NGX_ERROR;
1593         }
1594     }
1595 
1596     if (SSL_CONF_CTX_finish(cctx) != 1) {
1597         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1598                       "SSL_CONF_finish() failed");
1599         SSL_CONF_CTX_free(cctx);
1600         return NGX_ERROR;
1601     }
1602 
1603     SSL_CONF_CTX_free(cctx);
1604 
1605     return NGX_OK;
1606     }
1607 #else
1608     ngx_log_error(NGX_LOG_EMERG, ssl->log, 0,
1609                   "SSL_CONF_cmd() is not available on this platform");
1610     return NGX_ERROR;
1611 #endif
1612 }
1613 
1614 
1615 ngx_int_t
ngx_ssl_client_session_cache(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_uint_t enable)1616 ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable)
1617 {
1618     if (!enable) {
1619         return NGX_OK;
1620     }
1621 
1622     SSL_CTX_set_session_cache_mode(ssl->ctx,
1623                                    SSL_SESS_CACHE_CLIENT
1624                                    |SSL_SESS_CACHE_NO_INTERNAL);
1625 
1626     SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_client_session);
1627 
1628     return NGX_OK;
1629 }
1630 
1631 
1632 static int
ngx_ssl_new_client_session(ngx_ssl_conn_t * ssl_conn,ngx_ssl_session_t * sess)1633 ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1634 {
1635     ngx_connection_t  *c;
1636 
1637     c = ngx_ssl_get_connection(ssl_conn);
1638 
1639     if (c->ssl->save_session) {
1640         c->ssl->session = sess;
1641 
1642         c->ssl->save_session(c);
1643 
1644         c->ssl->session = NULL;
1645     }
1646 
1647     return 0;
1648 }
1649 
1650 
1651 ngx_int_t
ngx_ssl_create_connection(ngx_ssl_t * ssl,ngx_connection_t * c,ngx_uint_t flags)1652 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
1653 {
1654     ngx_ssl_connection_t  *sc;
1655 
1656     sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
1657     if (sc == NULL) {
1658         return NGX_ERROR;
1659     }
1660 
1661     sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
1662     sc->buffer_size = ssl->buffer_size;
1663 
1664     sc->session_ctx = ssl->ctx;
1665 
1666 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1667     if (SSL_CTX_get_max_early_data(ssl->ctx)) {
1668         sc->try_early_data = 1;
1669     }
1670 #endif
1671 
1672     sc->connection = SSL_new(ssl->ctx);
1673 
1674     if (sc->connection == NULL) {
1675         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
1676         return NGX_ERROR;
1677     }
1678 
1679     if (SSL_set_fd(sc->connection, c->fd) == 0) {
1680         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
1681         return NGX_ERROR;
1682     }
1683 
1684     if (flags & NGX_SSL_CLIENT) {
1685         SSL_set_connect_state(sc->connection);
1686 
1687     } else {
1688         SSL_set_accept_state(sc->connection);
1689 
1690 #ifdef SSL_OP_NO_RENEGOTIATION
1691         SSL_set_options(sc->connection, SSL_OP_NO_RENEGOTIATION);
1692 #endif
1693     }
1694 
1695     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
1696         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
1697         return NGX_ERROR;
1698     }
1699 
1700     c->ssl = sc;
1701 
1702     return NGX_OK;
1703 }
1704 
1705 
1706 ngx_ssl_session_t *
ngx_ssl_get_session(ngx_connection_t * c)1707 ngx_ssl_get_session(ngx_connection_t *c)
1708 {
1709 #ifdef TLS1_3_VERSION
1710     if (c->ssl->session) {
1711         SSL_SESSION_up_ref(c->ssl->session);
1712         return c->ssl->session;
1713     }
1714 #endif
1715 
1716     return SSL_get1_session(c->ssl->connection);
1717 }
1718 
1719 
1720 ngx_ssl_session_t *
ngx_ssl_get0_session(ngx_connection_t * c)1721 ngx_ssl_get0_session(ngx_connection_t *c)
1722 {
1723     if (c->ssl->session) {
1724         return c->ssl->session;
1725     }
1726 
1727     return SSL_get0_session(c->ssl->connection);
1728 }
1729 
1730 
1731 ngx_int_t
ngx_ssl_set_session(ngx_connection_t * c,ngx_ssl_session_t * session)1732 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
1733 {
1734     if (session) {
1735         if (SSL_set_session(c->ssl->connection, session) == 0) {
1736             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
1737             return NGX_ERROR;
1738         }
1739     }
1740 
1741     return NGX_OK;
1742 }
1743 
1744 
1745 ngx_int_t
ngx_ssl_handshake(ngx_connection_t * c)1746 ngx_ssl_handshake(ngx_connection_t *c)
1747 {
1748     int        n, sslerr;
1749     ngx_err_t  err;
1750     ngx_int_t  rc;
1751 
1752 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1753     if (c->ssl->try_early_data) {
1754         return ngx_ssl_try_early_data(c);
1755     }
1756 #endif
1757 
1758     if (c->ssl->in_ocsp) {
1759         return ngx_ssl_ocsp_validate(c);
1760     }
1761 
1762     ngx_ssl_clear_error(c->log);
1763 
1764     n = SSL_do_handshake(c->ssl->connection);
1765 
1766     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
1767 
1768     if (n == 1) {
1769 
1770         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1771             return NGX_ERROR;
1772         }
1773 
1774         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1775             return NGX_ERROR;
1776         }
1777 
1778 #if (NGX_DEBUG)
1779         ngx_ssl_handshake_log(c);
1780 #endif
1781 
1782         c->recv = ngx_ssl_recv;
1783         c->send = ngx_ssl_write;
1784         c->recv_chain = ngx_ssl_recv_chain;
1785         c->send_chain = ngx_ssl_send_chain;
1786 
1787         c->read->ready = 1;
1788         c->write->ready = 1;
1789 
1790 #ifndef SSL_OP_NO_RENEGOTIATION
1791 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1792 #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
1793 
1794         /* initial handshake done, disable renegotiation (CVE-2009-3555) */
1795         if (c->ssl->connection->s3 && SSL_is_server(c->ssl->connection)) {
1796             c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
1797         }
1798 
1799 #endif
1800 #endif
1801 #endif
1802 
1803         rc = ngx_ssl_ocsp_validate(c);
1804 
1805         if (rc == NGX_ERROR) {
1806             return NGX_ERROR;
1807         }
1808 
1809         if (rc == NGX_AGAIN) {
1810             c->read->handler = ngx_ssl_handshake_handler;
1811             c->write->handler = ngx_ssl_handshake_handler;
1812             return NGX_AGAIN;
1813         }
1814 
1815         c->ssl->handshaked = 1;
1816 
1817         return NGX_OK;
1818     }
1819 
1820     sslerr = SSL_get_error(c->ssl->connection, n);
1821 
1822     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1823 
1824     if (sslerr == SSL_ERROR_WANT_READ) {
1825         c->read->ready = 0;
1826         c->read->handler = ngx_ssl_handshake_handler;
1827         c->write->handler = ngx_ssl_handshake_handler;
1828 
1829         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1830             return NGX_ERROR;
1831         }
1832 
1833         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1834             return NGX_ERROR;
1835         }
1836 
1837         return NGX_AGAIN;
1838     }
1839 
1840     if (sslerr == SSL_ERROR_WANT_WRITE) {
1841         c->write->ready = 0;
1842         c->read->handler = ngx_ssl_handshake_handler;
1843         c->write->handler = ngx_ssl_handshake_handler;
1844 
1845         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1846             return NGX_ERROR;
1847         }
1848 
1849         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1850             return NGX_ERROR;
1851         }
1852 
1853         return NGX_AGAIN;
1854     }
1855 
1856     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1857 
1858     c->ssl->no_wait_shutdown = 1;
1859     c->ssl->no_send_shutdown = 1;
1860     c->read->eof = 1;
1861 
1862     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
1863         ngx_connection_error(c, err,
1864                              "peer closed connection in SSL handshake");
1865 
1866         return NGX_ERROR;
1867     }
1868 
1869     if (c->ssl->handshake_rejected) {
1870         ngx_connection_error(c, err, "handshake rejected");
1871         ERR_clear_error();
1872 
1873         return NGX_ERROR;
1874     }
1875 
1876     c->read->error = 1;
1877 
1878     ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
1879 
1880     return NGX_ERROR;
1881 }
1882 
1883 
1884 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1885 
1886 static ngx_int_t
ngx_ssl_try_early_data(ngx_connection_t * c)1887 ngx_ssl_try_early_data(ngx_connection_t *c)
1888 {
1889     int        n, sslerr;
1890     u_char     buf;
1891     size_t     readbytes;
1892     ngx_err_t  err;
1893     ngx_int_t  rc;
1894 
1895     ngx_ssl_clear_error(c->log);
1896 
1897     readbytes = 0;
1898 
1899     n = SSL_read_early_data(c->ssl->connection, &buf, 1, &readbytes);
1900 
1901     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1902                    "SSL_read_early_data: %d, %uz", n, readbytes);
1903 
1904     if (n == SSL_READ_EARLY_DATA_FINISH) {
1905         c->ssl->try_early_data = 0;
1906         return ngx_ssl_handshake(c);
1907     }
1908 
1909     if (n == SSL_READ_EARLY_DATA_SUCCESS) {
1910 
1911         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1912             return NGX_ERROR;
1913         }
1914 
1915         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1916             return NGX_ERROR;
1917         }
1918 
1919 #if (NGX_DEBUG)
1920         ngx_ssl_handshake_log(c);
1921 #endif
1922 
1923         c->ssl->try_early_data = 0;
1924 
1925         c->ssl->early_buf = buf;
1926         c->ssl->early_preread = 1;
1927 
1928         c->ssl->in_early = 1;
1929 
1930         c->recv = ngx_ssl_recv;
1931         c->send = ngx_ssl_write;
1932         c->recv_chain = ngx_ssl_recv_chain;
1933         c->send_chain = ngx_ssl_send_chain;
1934 
1935         c->read->ready = 1;
1936         c->write->ready = 1;
1937 
1938         rc = ngx_ssl_ocsp_validate(c);
1939 
1940         if (rc == NGX_ERROR) {
1941             return NGX_ERROR;
1942         }
1943 
1944         if (rc == NGX_AGAIN) {
1945             c->read->handler = ngx_ssl_handshake_handler;
1946             c->write->handler = ngx_ssl_handshake_handler;
1947             return NGX_AGAIN;
1948         }
1949 
1950         c->ssl->handshaked = 1;
1951 
1952         return NGX_OK;
1953     }
1954 
1955     /* SSL_READ_EARLY_DATA_ERROR */
1956 
1957     sslerr = SSL_get_error(c->ssl->connection, n);
1958 
1959     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1960 
1961     if (sslerr == SSL_ERROR_WANT_READ) {
1962         c->read->ready = 0;
1963         c->read->handler = ngx_ssl_handshake_handler;
1964         c->write->handler = ngx_ssl_handshake_handler;
1965 
1966         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1967             return NGX_ERROR;
1968         }
1969 
1970         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1971             return NGX_ERROR;
1972         }
1973 
1974         return NGX_AGAIN;
1975     }
1976 
1977     if (sslerr == SSL_ERROR_WANT_WRITE) {
1978         c->write->ready = 0;
1979         c->read->handler = ngx_ssl_handshake_handler;
1980         c->write->handler = ngx_ssl_handshake_handler;
1981 
1982         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1983             return NGX_ERROR;
1984         }
1985 
1986         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1987             return NGX_ERROR;
1988         }
1989 
1990         return NGX_AGAIN;
1991     }
1992 
1993     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1994 
1995     c->ssl->no_wait_shutdown = 1;
1996     c->ssl->no_send_shutdown = 1;
1997     c->read->eof = 1;
1998 
1999     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
2000         ngx_connection_error(c, err,
2001                              "peer closed connection in SSL handshake");
2002 
2003         return NGX_ERROR;
2004     }
2005 
2006     c->read->error = 1;
2007 
2008     ngx_ssl_connection_error(c, sslerr, err, "SSL_read_early_data() failed");
2009 
2010     return NGX_ERROR;
2011 }
2012 
2013 #endif
2014 
2015 
2016 #if (NGX_DEBUG)
2017 
2018 static void
ngx_ssl_handshake_log(ngx_connection_t * c)2019 ngx_ssl_handshake_log(ngx_connection_t *c)
2020 {
2021     char         buf[129], *s, *d;
2022 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
2023     const
2024 #endif
2025     SSL_CIPHER  *cipher;
2026 
2027     if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) {
2028         return;
2029     }
2030 
2031     cipher = SSL_get_current_cipher(c->ssl->connection);
2032 
2033     if (cipher) {
2034         SSL_CIPHER_description(cipher, &buf[1], 128);
2035 
2036         for (s = &buf[1], d = buf; *s; s++) {
2037             if (*s == ' ' && *d == ' ') {
2038                 continue;
2039             }
2040 
2041             if (*s == LF || *s == CR) {
2042                 continue;
2043             }
2044 
2045             *++d = *s;
2046         }
2047 
2048         if (*d != ' ') {
2049             d++;
2050         }
2051 
2052         *d = '\0';
2053 
2054         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2055                        "SSL: %s, cipher: \"%s\"",
2056                        SSL_get_version(c->ssl->connection), &buf[1]);
2057 
2058         if (SSL_session_reused(c->ssl->connection)) {
2059             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2060                            "SSL reused session");
2061         }
2062 
2063     } else {
2064         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2065                        "SSL no shared ciphers");
2066     }
2067 }
2068 
2069 #endif
2070 
2071 
2072 static void
ngx_ssl_handshake_handler(ngx_event_t * ev)2073 ngx_ssl_handshake_handler(ngx_event_t *ev)
2074 {
2075     ngx_connection_t  *c;
2076 
2077     c = ev->data;
2078 
2079     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2080                    "SSL handshake handler: %d", ev->write);
2081 
2082     if (ev->timedout) {
2083         c->ssl->handler(c);
2084         return;
2085     }
2086 
2087     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
2088         return;
2089     }
2090 
2091     c->ssl->handler(c);
2092 }
2093 
2094 
2095 ssize_t
ngx_ssl_recv_chain(ngx_connection_t * c,ngx_chain_t * cl,off_t limit)2096 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit)
2097 {
2098     u_char     *last;
2099     ssize_t     n, bytes, size;
2100     ngx_buf_t  *b;
2101 
2102     bytes = 0;
2103 
2104     b = cl->buf;
2105     last = b->last;
2106 
2107     for ( ;; ) {
2108         size = b->end - last;
2109 
2110         if (limit) {
2111             if (bytes >= limit) {
2112                 return bytes;
2113             }
2114 
2115             if (bytes + size > limit) {
2116                 size = (ssize_t) (limit - bytes);
2117             }
2118         }
2119 
2120         n = ngx_ssl_recv(c, last, size);
2121 
2122         if (n > 0) {
2123             last += n;
2124             bytes += n;
2125 
2126             if (!c->read->ready) {
2127                 return bytes;
2128             }
2129 
2130             if (last == b->end) {
2131                 cl = cl->next;
2132 
2133                 if (cl == NULL) {
2134                     return bytes;
2135                 }
2136 
2137                 b = cl->buf;
2138                 last = b->last;
2139             }
2140 
2141             continue;
2142         }
2143 
2144         if (bytes) {
2145 
2146             if (n == 0 || n == NGX_ERROR) {
2147                 c->read->ready = 1;
2148             }
2149 
2150             return bytes;
2151         }
2152 
2153         return n;
2154     }
2155 }
2156 
2157 
2158 ssize_t
ngx_ssl_recv(ngx_connection_t * c,u_char * buf,size_t size)2159 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
2160 {
2161     int  n, bytes;
2162 
2163 #ifdef SSL_READ_EARLY_DATA_SUCCESS
2164     if (c->ssl->in_early) {
2165         return ngx_ssl_recv_early(c, buf, size);
2166     }
2167 #endif
2168 
2169     if (c->ssl->last == NGX_ERROR) {
2170         c->read->error = 1;
2171         return NGX_ERROR;
2172     }
2173 
2174     if (c->ssl->last == NGX_DONE) {
2175         c->read->ready = 0;
2176         c->read->eof = 1;
2177         return 0;
2178     }
2179 
2180     bytes = 0;
2181 
2182     ngx_ssl_clear_error(c->log);
2183 
2184     /*
2185      * SSL_read() may return data in parts, so try to read
2186      * until SSL_read() would return no data
2187      */
2188 
2189     for ( ;; ) {
2190 
2191         n = SSL_read(c->ssl->connection, buf, size);
2192 
2193         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
2194 
2195         if (n > 0) {
2196             bytes += n;
2197         }
2198 
2199         c->ssl->last = ngx_ssl_handle_recv(c, n);
2200 
2201         if (c->ssl->last == NGX_OK) {
2202 
2203             size -= n;
2204 
2205             if (size == 0) {
2206                 c->read->ready = 1;
2207 
2208                 if (c->read->available >= 0) {
2209                     c->read->available -= bytes;
2210 
2211                     /*
2212                      * there can be data buffered at SSL layer,
2213                      * so we post an event to continue reading on the next
2214                      * iteration of the event loop
2215                      */
2216 
2217                     if (c->read->available < 0) {
2218                         c->read->available = 0;
2219                         c->read->ready = 0;
2220 
2221                         if (c->read->posted) {
2222                             ngx_delete_posted_event(c->read);
2223                         }
2224 
2225                         ngx_post_event(c->read, &ngx_posted_next_events);
2226                     }
2227 
2228                     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2229                                    "SSL_read: avail:%d", c->read->available);
2230 
2231                 } else {
2232 
2233 #if (NGX_HAVE_FIONREAD)
2234 
2235                     if (ngx_socket_nread(c->fd, &c->read->available) == -1) {
2236                         c->read->error = 1;
2237                         ngx_connection_error(c, ngx_socket_errno,
2238                                              ngx_socket_nread_n " failed");
2239                         return NGX_ERROR;
2240                     }
2241 
2242                     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2243                                    "SSL_read: avail:%d", c->read->available);
2244 
2245 #endif
2246                 }
2247 
2248                 return bytes;
2249             }
2250 
2251             buf += n;
2252 
2253             continue;
2254         }
2255 
2256         if (bytes) {
2257             if (c->ssl->last != NGX_AGAIN) {
2258                 c->read->ready = 1;
2259             }
2260 
2261             return bytes;
2262         }
2263 
2264         switch (c->ssl->last) {
2265 
2266         case NGX_DONE:
2267             c->read->ready = 0;
2268             c->read->eof = 1;
2269             return 0;
2270 
2271         case NGX_ERROR:
2272             c->read->error = 1;
2273 
2274             /* fall through */
2275 
2276         case NGX_AGAIN:
2277             return c->ssl->last;
2278         }
2279     }
2280 }
2281 
2282 
2283 #ifdef SSL_READ_EARLY_DATA_SUCCESS
2284 
2285 static ssize_t
ngx_ssl_recv_early(ngx_connection_t * c,u_char * buf,size_t size)2286 ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
2287 {
2288     int        n, bytes;
2289     size_t     readbytes;
2290 
2291     if (c->ssl->last == NGX_ERROR) {
2292         c->read->error = 1;
2293         return NGX_ERROR;
2294     }
2295 
2296     if (c->ssl->last == NGX_DONE) {
2297         c->read->ready = 0;
2298         c->read->eof = 1;
2299         return 0;
2300     }
2301 
2302     bytes = 0;
2303 
2304     ngx_ssl_clear_error(c->log);
2305 
2306     if (c->ssl->early_preread) {
2307 
2308         if (size == 0) {
2309             c->read->ready = 0;
2310             c->read->eof = 1;
2311             return 0;
2312         }
2313 
2314         *buf = c->ssl->early_buf;
2315 
2316         c->ssl->early_preread = 0;
2317 
2318         bytes = 1;
2319         size -= 1;
2320         buf += 1;
2321     }
2322 
2323     if (c->ssl->write_blocked) {
2324         return NGX_AGAIN;
2325     }
2326 
2327     /*
2328      * SSL_read_early_data() may return data in parts, so try to read
2329      * until SSL_read_early_data() would return no data
2330      */
2331 
2332     for ( ;; ) {
2333 
2334         readbytes = 0;
2335 
2336         n = SSL_read_early_data(c->ssl->connection, buf, size, &readbytes);
2337 
2338         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2339                        "SSL_read_early_data: %d, %uz", n, readbytes);
2340 
2341         if (n == SSL_READ_EARLY_DATA_SUCCESS) {
2342 
2343             c->ssl->last = ngx_ssl_handle_recv(c, 1);
2344 
2345             bytes += readbytes;
2346             size -= readbytes;
2347 
2348             if (size == 0) {
2349                 c->read->ready = 1;
2350                 return bytes;
2351             }
2352 
2353             buf += readbytes;
2354 
2355             continue;
2356         }
2357 
2358         if (n == SSL_READ_EARLY_DATA_FINISH) {
2359 
2360             c->ssl->last = ngx_ssl_handle_recv(c, 1);
2361             c->ssl->in_early = 0;
2362 
2363             if (bytes) {
2364                 c->read->ready = 1;
2365                 return bytes;
2366             }
2367 
2368             return ngx_ssl_recv(c, buf, size);
2369         }
2370 
2371         /* SSL_READ_EARLY_DATA_ERROR */
2372 
2373         c->ssl->last = ngx_ssl_handle_recv(c, 0);
2374 
2375         if (bytes) {
2376             if (c->ssl->last != NGX_AGAIN) {
2377                 c->read->ready = 1;
2378             }
2379 
2380             return bytes;
2381         }
2382 
2383         switch (c->ssl->last) {
2384 
2385         case NGX_DONE:
2386             c->read->ready = 0;
2387             c->read->eof = 1;
2388             return 0;
2389 
2390         case NGX_ERROR:
2391             c->read->error = 1;
2392 
2393             /* fall through */
2394 
2395         case NGX_AGAIN:
2396             return c->ssl->last;
2397         }
2398     }
2399 }
2400 
2401 #endif
2402 
2403 
2404 static ngx_int_t
ngx_ssl_handle_recv(ngx_connection_t * c,int n)2405 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
2406 {
2407     int        sslerr;
2408     ngx_err_t  err;
2409 
2410 #ifndef SSL_OP_NO_RENEGOTIATION
2411 
2412     if (c->ssl->renegotiation) {
2413         /*
2414          * disable renegotiation (CVE-2009-3555):
2415          * OpenSSL (at least up to 0.9.8l) does not handle disabled
2416          * renegotiation gracefully, so drop connection here
2417          */
2418 
2419         ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
2420 
2421         while (ERR_peek_error()) {
2422             ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
2423                           "ignoring stale global SSL error");
2424         }
2425 
2426         ERR_clear_error();
2427 
2428         c->ssl->no_wait_shutdown = 1;
2429         c->ssl->no_send_shutdown = 1;
2430 
2431         return NGX_ERROR;
2432     }
2433 
2434 #endif
2435 
2436     if (n > 0) {
2437 
2438         if (c->ssl->saved_write_handler) {
2439 
2440             c->write->handler = c->ssl->saved_write_handler;
2441             c->ssl->saved_write_handler = NULL;
2442             c->write->ready = 1;
2443 
2444             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
2445                 return NGX_ERROR;
2446             }
2447 
2448             ngx_post_event(c->write, &ngx_posted_events);
2449         }
2450 
2451         return NGX_OK;
2452     }
2453 
2454     sslerr = SSL_get_error(c->ssl->connection, n);
2455 
2456     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
2457 
2458     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
2459 
2460     if (sslerr == SSL_ERROR_WANT_READ) {
2461 
2462         if (c->ssl->saved_write_handler) {
2463 
2464             c->write->handler = c->ssl->saved_write_handler;
2465             c->ssl->saved_write_handler = NULL;
2466             c->write->ready = 1;
2467 
2468             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
2469                 return NGX_ERROR;
2470             }
2471 
2472             ngx_post_event(c->write, &ngx_posted_events);
2473         }
2474 
2475         c->read->ready = 0;
2476         return NGX_AGAIN;
2477     }
2478 
2479     if (sslerr == SSL_ERROR_WANT_WRITE) {
2480 
2481         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2482                        "SSL_read: want write");
2483 
2484         c->write->ready = 0;
2485 
2486         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
2487             return NGX_ERROR;
2488         }
2489 
2490         /*
2491          * we do not set the timer because there is already the read event timer
2492          */
2493 
2494         if (c->ssl->saved_write_handler == NULL) {
2495             c->ssl->saved_write_handler = c->write->handler;
2496             c->write->handler = ngx_ssl_write_handler;
2497         }
2498 
2499         return NGX_AGAIN;
2500     }
2501 
2502     c->ssl->no_wait_shutdown = 1;
2503     c->ssl->no_send_shutdown = 1;
2504 
2505     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
2506         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2507                        "peer shutdown SSL cleanly");
2508         return NGX_DONE;
2509     }
2510 
2511     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
2512 
2513     return NGX_ERROR;
2514 }
2515 
2516 
2517 static void
ngx_ssl_write_handler(ngx_event_t * wev)2518 ngx_ssl_write_handler(ngx_event_t *wev)
2519 {
2520     ngx_connection_t  *c;
2521 
2522     c = wev->data;
2523 
2524     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL write handler");
2525 
2526     c->read->handler(c->read);
2527 }
2528 
2529 
2530 /*
2531  * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
2532  * before the SSL_write() call to decrease a SSL overhead.
2533  *
2534  * Besides for protocols such as HTTP it is possible to always buffer
2535  * the output to decrease a SSL overhead some more.
2536  */
2537 
2538 ngx_chain_t *
ngx_ssl_send_chain(ngx_connection_t * c,ngx_chain_t * in,off_t limit)2539 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
2540 {
2541     int          n;
2542     ngx_uint_t   flush;
2543     ssize_t      send, size;
2544     ngx_buf_t   *buf;
2545 
2546     if (!c->ssl->buffer) {
2547 
2548         while (in) {
2549             if (ngx_buf_special(in->buf)) {
2550                 in = in->next;
2551                 continue;
2552             }
2553 
2554             n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
2555 
2556             if (n == NGX_ERROR) {
2557                 return NGX_CHAIN_ERROR;
2558             }
2559 
2560             if (n == NGX_AGAIN) {
2561                 return in;
2562             }
2563 
2564             in->buf->pos += n;
2565 
2566             if (in->buf->pos == in->buf->last) {
2567                 in = in->next;
2568             }
2569         }
2570 
2571         return in;
2572     }
2573 
2574 
2575     /* the maximum limit size is the maximum int32_t value - the page size */
2576 
2577     if (limit == 0 || limit > (off_t) (NGX_MAX_INT32_VALUE - ngx_pagesize)) {
2578         limit = NGX_MAX_INT32_VALUE - ngx_pagesize;
2579     }
2580 
2581     buf = c->ssl->buf;
2582 
2583     if (buf == NULL) {
2584         buf = ngx_create_temp_buf(c->pool, c->ssl->buffer_size);
2585         if (buf == NULL) {
2586             return NGX_CHAIN_ERROR;
2587         }
2588 
2589         c->ssl->buf = buf;
2590     }
2591 
2592     if (buf->start == NULL) {
2593         buf->start = ngx_palloc(c->pool, c->ssl->buffer_size);
2594         if (buf->start == NULL) {
2595             return NGX_CHAIN_ERROR;
2596         }
2597 
2598         buf->pos = buf->start;
2599         buf->last = buf->start;
2600         buf->end = buf->start + c->ssl->buffer_size;
2601     }
2602 
2603     send = buf->last - buf->pos;
2604     flush = (in == NULL) ? 1 : buf->flush;
2605 
2606     for ( ;; ) {
2607 
2608         while (in && buf->last < buf->end && send < limit) {
2609             if (in->buf->last_buf || in->buf->flush) {
2610                 flush = 1;
2611             }
2612 
2613             if (ngx_buf_special(in->buf)) {
2614                 in = in->next;
2615                 continue;
2616             }
2617 
2618             size = in->buf->last - in->buf->pos;
2619 
2620             if (size > buf->end - buf->last) {
2621                 size = buf->end - buf->last;
2622             }
2623 
2624             if (send + size > limit) {
2625                 size = (ssize_t) (limit - send);
2626             }
2627 
2628             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2629                            "SSL buf copy: %z", size);
2630 
2631             ngx_memcpy(buf->last, in->buf->pos, size);
2632 
2633             buf->last += size;
2634             in->buf->pos += size;
2635             send += size;
2636 
2637             if (in->buf->pos == in->buf->last) {
2638                 in = in->next;
2639             }
2640         }
2641 
2642         if (!flush && send < limit && buf->last < buf->end) {
2643             break;
2644         }
2645 
2646         size = buf->last - buf->pos;
2647 
2648         if (size == 0) {
2649             buf->flush = 0;
2650             c->buffered &= ~NGX_SSL_BUFFERED;
2651             return in;
2652         }
2653 
2654         n = ngx_ssl_write(c, buf->pos, size);
2655 
2656         if (n == NGX_ERROR) {
2657             return NGX_CHAIN_ERROR;
2658         }
2659 
2660         if (n == NGX_AGAIN) {
2661             break;
2662         }
2663 
2664         buf->pos += n;
2665 
2666         if (n < size) {
2667             break;
2668         }
2669 
2670         flush = 0;
2671 
2672         buf->pos = buf->start;
2673         buf->last = buf->start;
2674 
2675         if (in == NULL || send == limit) {
2676             break;
2677         }
2678     }
2679 
2680     buf->flush = flush;
2681 
2682     if (buf->pos < buf->last) {
2683         c->buffered |= NGX_SSL_BUFFERED;
2684 
2685     } else {
2686         c->buffered &= ~NGX_SSL_BUFFERED;
2687     }
2688 
2689     return in;
2690 }
2691 
2692 
2693 ssize_t
ngx_ssl_write(ngx_connection_t * c,u_char * data,size_t size)2694 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
2695 {
2696     int        n, sslerr;
2697     ngx_err_t  err;
2698 
2699 #ifdef SSL_READ_EARLY_DATA_SUCCESS
2700     if (c->ssl->in_early) {
2701         return ngx_ssl_write_early(c, data, size);
2702     }
2703 #endif
2704 
2705     ngx_ssl_clear_error(c->log);
2706 
2707     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size);
2708 
2709     n = SSL_write(c->ssl->connection, data, size);
2710 
2711     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
2712 
2713     if (n > 0) {
2714 
2715         if (c->ssl->saved_read_handler) {
2716 
2717             c->read->handler = c->ssl->saved_read_handler;
2718             c->ssl->saved_read_handler = NULL;
2719             c->read->ready = 1;
2720 
2721             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2722                 return NGX_ERROR;
2723             }
2724 
2725             ngx_post_event(c->read, &ngx_posted_events);
2726         }
2727 
2728         c->sent += n;
2729 
2730         return n;
2731     }
2732 
2733     sslerr = SSL_get_error(c->ssl->connection, n);
2734 
2735     if (sslerr == SSL_ERROR_ZERO_RETURN) {
2736 
2737         /*
2738          * OpenSSL 1.1.1 fails to return SSL_ERROR_SYSCALL if an error
2739          * happens during SSL_write() after close_notify alert from the
2740          * peer, and returns SSL_ERROR_ZERO_RETURN instead,
2741          * https://git.openssl.org/?p=openssl.git;a=commitdiff;h=8051ab2
2742          */
2743 
2744         sslerr = SSL_ERROR_SYSCALL;
2745     }
2746 
2747     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
2748 
2749     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
2750 
2751     if (sslerr == SSL_ERROR_WANT_WRITE) {
2752 
2753         if (c->ssl->saved_read_handler) {
2754 
2755             c->read->handler = c->ssl->saved_read_handler;
2756             c->ssl->saved_read_handler = NULL;
2757             c->read->ready = 1;
2758 
2759             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2760                 return NGX_ERROR;
2761             }
2762 
2763             ngx_post_event(c->read, &ngx_posted_events);
2764         }
2765 
2766         c->write->ready = 0;
2767         return NGX_AGAIN;
2768     }
2769 
2770     if (sslerr == SSL_ERROR_WANT_READ) {
2771 
2772         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2773                        "SSL_write: want read");
2774 
2775         c->read->ready = 0;
2776 
2777         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2778             return NGX_ERROR;
2779         }
2780 
2781         /*
2782          * we do not set the timer because there is already
2783          * the write event timer
2784          */
2785 
2786         if (c->ssl->saved_read_handler == NULL) {
2787             c->ssl->saved_read_handler = c->read->handler;
2788             c->read->handler = ngx_ssl_read_handler;
2789         }
2790 
2791         return NGX_AGAIN;
2792     }
2793 
2794     c->ssl->no_wait_shutdown = 1;
2795     c->ssl->no_send_shutdown = 1;
2796     c->write->error = 1;
2797 
2798     ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
2799 
2800     return NGX_ERROR;
2801 }
2802 
2803 
2804 #ifdef SSL_READ_EARLY_DATA_SUCCESS
2805 
2806 ssize_t
ngx_ssl_write_early(ngx_connection_t * c,u_char * data,size_t size)2807 ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
2808 {
2809     int        n, sslerr;
2810     size_t     written;
2811     ngx_err_t  err;
2812 
2813     ngx_ssl_clear_error(c->log);
2814 
2815     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size);
2816 
2817     written = 0;
2818 
2819     n = SSL_write_early_data(c->ssl->connection, data, size, &written);
2820 
2821     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2822                    "SSL_write_early_data: %d, %uz", n, written);
2823 
2824     if (n > 0) {
2825 
2826         if (c->ssl->saved_read_handler) {
2827 
2828             c->read->handler = c->ssl->saved_read_handler;
2829             c->ssl->saved_read_handler = NULL;
2830             c->read->ready = 1;
2831 
2832             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2833                 return NGX_ERROR;
2834             }
2835 
2836             ngx_post_event(c->read, &ngx_posted_events);
2837         }
2838 
2839         if (c->ssl->write_blocked) {
2840             c->ssl->write_blocked = 0;
2841             ngx_post_event(c->read, &ngx_posted_events);
2842         }
2843 
2844         c->sent += written;
2845 
2846         return written;
2847     }
2848 
2849     sslerr = SSL_get_error(c->ssl->connection, n);
2850 
2851     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
2852 
2853     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
2854 
2855     if (sslerr == SSL_ERROR_WANT_WRITE) {
2856 
2857         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2858                        "SSL_write_early_data: want write");
2859 
2860         if (c->ssl->saved_read_handler) {
2861 
2862             c->read->handler = c->ssl->saved_read_handler;
2863             c->ssl->saved_read_handler = NULL;
2864             c->read->ready = 1;
2865 
2866             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2867                 return NGX_ERROR;
2868             }
2869 
2870             ngx_post_event(c->read, &ngx_posted_events);
2871         }
2872 
2873         /*
2874          * OpenSSL 1.1.1a fails to handle SSL_read_early_data()
2875          * if an SSL_write_early_data() call blocked on writing,
2876          * see https://github.com/openssl/openssl/issues/7757
2877          */
2878 
2879         c->ssl->write_blocked = 1;
2880 
2881         c->write->ready = 0;
2882         return NGX_AGAIN;
2883     }
2884 
2885     if (sslerr == SSL_ERROR_WANT_READ) {
2886 
2887         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2888                        "SSL_write_early_data: want read");
2889 
2890         c->read->ready = 0;
2891 
2892         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
2893             return NGX_ERROR;
2894         }
2895 
2896         /*
2897          * we do not set the timer because there is already
2898          * the write event timer
2899          */
2900 
2901         if (c->ssl->saved_read_handler == NULL) {
2902             c->ssl->saved_read_handler = c->read->handler;
2903             c->read->handler = ngx_ssl_read_handler;
2904         }
2905 
2906         return NGX_AGAIN;
2907     }
2908 
2909     c->ssl->no_wait_shutdown = 1;
2910     c->ssl->no_send_shutdown = 1;
2911     c->write->error = 1;
2912 
2913     ngx_ssl_connection_error(c, sslerr, err, "SSL_write_early_data() failed");
2914 
2915     return NGX_ERROR;
2916 }
2917 
2918 #endif
2919 
2920 
2921 static void
ngx_ssl_read_handler(ngx_event_t * rev)2922 ngx_ssl_read_handler(ngx_event_t *rev)
2923 {
2924     ngx_connection_t  *c;
2925 
2926     c = rev->data;
2927 
2928     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL read handler");
2929 
2930     c->write->handler(c->write);
2931 }
2932 
2933 
2934 void
ngx_ssl_free_buffer(ngx_connection_t * c)2935 ngx_ssl_free_buffer(ngx_connection_t *c)
2936 {
2937     if (c->ssl->buf && c->ssl->buf->start) {
2938         if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
2939             c->ssl->buf->start = NULL;
2940         }
2941     }
2942 }
2943 
2944 
2945 ngx_int_t
ngx_ssl_shutdown(ngx_connection_t * c)2946 ngx_ssl_shutdown(ngx_connection_t *c)
2947 {
2948     int         n, sslerr, mode;
2949     ngx_int_t   rc;
2950     ngx_err_t   err;
2951     ngx_uint_t  tries;
2952 
2953     rc = NGX_OK;
2954 
2955     ngx_ssl_ocsp_cleanup(c);
2956 
2957     if (SSL_in_init(c->ssl->connection)) {
2958         /*
2959          * OpenSSL 1.0.2f complains if SSL_shutdown() is called during
2960          * an SSL handshake, while previous versions always return 0.
2961          * Avoid calling SSL_shutdown() if handshake wasn't completed.
2962          */
2963 
2964         goto done;
2965     }
2966 
2967     if (c->timedout || c->error || c->buffered) {
2968         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
2969         SSL_set_quiet_shutdown(c->ssl->connection, 1);
2970 
2971     } else {
2972         mode = SSL_get_shutdown(c->ssl->connection);
2973 
2974         if (c->ssl->no_wait_shutdown) {
2975             mode |= SSL_RECEIVED_SHUTDOWN;
2976         }
2977 
2978         if (c->ssl->no_send_shutdown) {
2979             mode |= SSL_SENT_SHUTDOWN;
2980         }
2981 
2982         if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
2983             SSL_set_quiet_shutdown(c->ssl->connection, 1);
2984         }
2985     }
2986 
2987     SSL_set_shutdown(c->ssl->connection, mode);
2988 
2989     ngx_ssl_clear_error(c->log);
2990 
2991     tries = 2;
2992 
2993     for ( ;; ) {
2994 
2995         /*
2996          * For bidirectional shutdown, SSL_shutdown() needs to be called
2997          * twice: first call sends the "close notify" alert and returns 0,
2998          * second call waits for the peer's "close notify" alert.
2999          */
3000 
3001         n = SSL_shutdown(c->ssl->connection);
3002 
3003         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
3004 
3005         if (n == 1) {
3006             goto done;
3007         }
3008 
3009         if (n == 0 && tries-- > 1) {
3010             continue;
3011         }
3012 
3013         /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
3014 
3015         sslerr = SSL_get_error(c->ssl->connection, n);
3016 
3017         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3018                        "SSL_get_error: %d", sslerr);
3019 
3020         if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
3021             c->read->handler = ngx_ssl_shutdown_handler;
3022             c->write->handler = ngx_ssl_shutdown_handler;
3023 
3024             if (sslerr == SSL_ERROR_WANT_READ) {
3025                 c->read->ready = 0;
3026 
3027             } else {
3028                 c->write->ready = 0;
3029             }
3030 
3031             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
3032                 goto failed;
3033             }
3034 
3035             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
3036                 goto failed;
3037             }
3038 
3039             ngx_add_timer(c->read, 3000);
3040 
3041             return NGX_AGAIN;
3042         }
3043 
3044         if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
3045             goto done;
3046         }
3047 
3048         err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
3049 
3050         ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
3051 
3052         break;
3053     }
3054 
3055 failed:
3056 
3057     rc = NGX_ERROR;
3058 
3059 done:
3060 
3061     if (c->ssl->shutdown_without_free) {
3062         c->ssl->shutdown_without_free = 0;
3063         c->recv = ngx_recv;
3064         return rc;
3065     }
3066 
3067     SSL_free(c->ssl->connection);
3068     c->ssl = NULL;
3069     c->recv = ngx_recv;
3070 
3071     return rc;
3072 }
3073 
3074 
3075 static void
ngx_ssl_shutdown_handler(ngx_event_t * ev)3076 ngx_ssl_shutdown_handler(ngx_event_t *ev)
3077 {
3078     ngx_connection_t           *c;
3079     ngx_connection_handler_pt   handler;
3080 
3081     c = ev->data;
3082     handler = c->ssl->handler;
3083 
3084     if (ev->timedout) {
3085         c->timedout = 1;
3086     }
3087 
3088     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
3089 
3090     if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3091         return;
3092     }
3093 
3094     handler(c);
3095 }
3096 
3097 
3098 static void
ngx_ssl_connection_error(ngx_connection_t * c,int sslerr,ngx_err_t err,char * text)3099 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
3100     char *text)
3101 {
3102     int         n;
3103     ngx_uint_t  level;
3104 
3105     level = NGX_LOG_CRIT;
3106 
3107     if (sslerr == SSL_ERROR_SYSCALL) {
3108 
3109         if (err == NGX_ECONNRESET
3110 #if (NGX_WIN32)
3111             || err == NGX_ECONNABORTED
3112 #endif
3113             || err == NGX_EPIPE
3114             || err == NGX_ENOTCONN
3115             || err == NGX_ETIMEDOUT
3116             || err == NGX_ECONNREFUSED
3117             || err == NGX_ENETDOWN
3118             || err == NGX_ENETUNREACH
3119             || err == NGX_EHOSTDOWN
3120             || err == NGX_EHOSTUNREACH)
3121         {
3122             switch (c->log_error) {
3123 
3124             case NGX_ERROR_IGNORE_ECONNRESET:
3125             case NGX_ERROR_INFO:
3126                 level = NGX_LOG_INFO;
3127                 break;
3128 
3129             case NGX_ERROR_ERR:
3130                 level = NGX_LOG_ERR;
3131                 break;
3132 
3133             default:
3134                 break;
3135             }
3136         }
3137 
3138     } else if (sslerr == SSL_ERROR_SSL) {
3139 
3140         n = ERR_GET_REASON(ERR_peek_error());
3141 
3142             /* handshake failures */
3143         if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC                        /*  103 */
3144 #ifdef SSL_R_NO_SUITABLE_KEY_SHARE
3145             || n == SSL_R_NO_SUITABLE_KEY_SHARE                      /*  101 */
3146 #endif
3147 #ifdef SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM
3148             || n == SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM            /*  118 */
3149 #endif
3150             || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  /*  129 */
3151             || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
3152             || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              /*  151 */
3153             || n == SSL_R_EXCESSIVE_MESSAGE_SIZE                     /*  152 */
3154             || n == SSL_R_HTTPS_PROXY_REQUEST                        /*  155 */
3155             || n == SSL_R_HTTP_REQUEST                               /*  156 */
3156             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
3157 #ifdef SSL_R_NO_CIPHERS_PASSED
3158             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
3159 #endif
3160             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
3161             || n == SSL_R_NO_COMPRESSION_SPECIFIED                   /*  187 */
3162             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
3163             || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
3164 #ifdef SSL_R_CLIENTHELLO_TLSEXT
3165             || n == SSL_R_CLIENTHELLO_TLSEXT                         /*  226 */
3166 #endif
3167 #ifdef SSL_R_PARSE_TLSEXT
3168             || n == SSL_R_PARSE_TLSEXT                               /*  227 */
3169 #endif
3170 #ifdef SSL_R_CALLBACK_FAILED
3171             || n == SSL_R_CALLBACK_FAILED                            /*  234 */
3172 #endif
3173             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
3174             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
3175             || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
3176             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
3177 #ifdef SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS
3178             || n == SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS             /*  253 */
3179 #endif
3180             || n == SSL_R_UNSUPPORTED_PROTOCOL                       /*  258 */
3181 #ifdef SSL_R_NO_SHARED_GROUP
3182             || n == SSL_R_NO_SHARED_GROUP                            /*  266 */
3183 #endif
3184             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
3185             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
3186 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
3187             || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG                   /*  335 */
3188             || n == SSL_R_RENEGOTIATION_ENCODING_ERR                 /*  336 */
3189             || n == SSL_R_RENEGOTIATION_MISMATCH                     /*  337 */
3190 #endif
3191 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
3192             || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED       /*  338 */
3193 #endif
3194 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
3195             || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING           /*  345 */
3196 #endif
3197 #ifdef SSL_R_INAPPROPRIATE_FALLBACK
3198             || n == SSL_R_INAPPROPRIATE_FALLBACK                     /*  373 */
3199 #endif
3200 #ifdef SSL_R_CERT_CB_ERROR
3201             || n == SSL_R_CERT_CB_ERROR                              /*  377 */
3202 #endif
3203 #ifdef SSL_R_VERSION_TOO_LOW
3204             || n == SSL_R_VERSION_TOO_LOW                            /*  396 */
3205 #endif
3206             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
3207 #ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE
3208             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
3209             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
3210             || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED              /* 1021 */
3211             || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW                /* 1022 */
3212             || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE          /* 1030 */
3213             || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE              /* 1040 */
3214             || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE                 /* 1041 */
3215             || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE                /* 1042 */
3216             || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE        /* 1043 */
3217             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED            /* 1044 */
3218             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED            /* 1045 */
3219             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN            /* 1046 */
3220             || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER              /* 1047 */
3221             || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA                     /* 1048 */
3222             || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED                  /* 1049 */
3223             || n == SSL_R_TLSV1_ALERT_DECODE_ERROR                   /* 1050 */
3224             || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR                  /* 1051 */
3225             || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION             /* 1060 */
3226             || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION               /* 1070 */
3227             || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY          /* 1071 */
3228             || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR                 /* 1080 */
3229             || n == SSL_R_TLSV1_ALERT_USER_CANCELLED                 /* 1090 */
3230             || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION               /* 1100 */
3231 #endif
3232             )
3233         {
3234             switch (c->log_error) {
3235 
3236             case NGX_ERROR_IGNORE_ECONNRESET:
3237             case NGX_ERROR_INFO:
3238                 level = NGX_LOG_INFO;
3239                 break;
3240 
3241             case NGX_ERROR_ERR:
3242                 level = NGX_LOG_ERR;
3243                 break;
3244 
3245             default:
3246                 break;
3247             }
3248         }
3249     }
3250 
3251     ngx_ssl_error(level, c->log, err, text);
3252 }
3253 
3254 
3255 static void
ngx_ssl_clear_error(ngx_log_t * log)3256 ngx_ssl_clear_error(ngx_log_t *log)
3257 {
3258     while (ERR_peek_error()) {
3259         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
3260     }
3261 
3262     ERR_clear_error();
3263 }
3264 
3265 
3266 void ngx_cdecl
ngx_ssl_error(ngx_uint_t level,ngx_log_t * log,ngx_err_t err,char * fmt,...)3267 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
3268 {
3269     int          flags;
3270     u_long       n;
3271     va_list      args;
3272     u_char      *p, *last;
3273     u_char       errstr[NGX_MAX_CONF_ERRSTR];
3274     const char  *data;
3275 
3276     last = errstr + NGX_MAX_CONF_ERRSTR;
3277 
3278     va_start(args, fmt);
3279     p = ngx_vslprintf(errstr, last - 1, fmt, args);
3280     va_end(args);
3281 
3282     if (ERR_peek_error()) {
3283         p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
3284 
3285         for ( ;; ) {
3286 
3287             n = ERR_peek_error_data(&data, &flags);
3288 
3289             if (n == 0) {
3290                 break;
3291             }
3292 
3293             /* ERR_error_string_n() requires at least one byte */
3294 
3295             if (p >= last - 1) {
3296                 goto next;
3297             }
3298 
3299             *p++ = ' ';
3300 
3301             ERR_error_string_n(n, (char *) p, last - p);
3302 
3303             while (p < last && *p) {
3304                 p++;
3305             }
3306 
3307             if (p < last && *data && (flags & ERR_TXT_STRING)) {
3308                 *p++ = ':';
3309                 p = ngx_cpystrn(p, (u_char *) data, last - p);
3310             }
3311 
3312         next:
3313 
3314             (void) ERR_get_error();
3315         }
3316 
3317         if (p < last) {
3318             *p++ = ')';
3319         }
3320     }
3321 
3322     ngx_log_error(level, log, err, "%*s", p - errstr, errstr);
3323 }
3324 
3325 
3326 ngx_int_t
ngx_ssl_session_cache(ngx_ssl_t * ssl,ngx_str_t * sess_ctx,ngx_array_t * certificates,ssize_t builtin_session_cache,ngx_shm_zone_t * shm_zone,time_t timeout)3327 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
3328     ngx_array_t *certificates, ssize_t builtin_session_cache,
3329     ngx_shm_zone_t *shm_zone, time_t timeout)
3330 {
3331     long  cache_mode;
3332 
3333     SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
3334 
3335     if (ngx_ssl_session_id_context(ssl, sess_ctx, certificates) != NGX_OK) {
3336         return NGX_ERROR;
3337     }
3338 
3339     if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
3340         SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
3341         return NGX_OK;
3342     }
3343 
3344     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
3345 
3346         /*
3347          * If the server explicitly says that it does not support
3348          * session reuse (see SSL_SESS_CACHE_OFF above), then
3349          * Outlook Express fails to upload a sent email to
3350          * the Sent Items folder on the IMAP server via a separate IMAP
3351          * connection in the background.  Therefore we have a special
3352          * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
3353          * where the server pretends that it supports session reuse,
3354          * but it does not actually store any session.
3355          */
3356 
3357         SSL_CTX_set_session_cache_mode(ssl->ctx,
3358                                        SSL_SESS_CACHE_SERVER
3359                                        |SSL_SESS_CACHE_NO_AUTO_CLEAR
3360                                        |SSL_SESS_CACHE_NO_INTERNAL_STORE);
3361 
3362         SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
3363 
3364         return NGX_OK;
3365     }
3366 
3367     cache_mode = SSL_SESS_CACHE_SERVER;
3368 
3369     if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
3370         cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
3371     }
3372 
3373     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
3374 
3375     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
3376 
3377         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
3378             SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
3379         }
3380     }
3381 
3382     if (shm_zone) {
3383         SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
3384         SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
3385         SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
3386 
3387         if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
3388             == 0)
3389         {
3390             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3391                           "SSL_CTX_set_ex_data() failed");
3392             return NGX_ERROR;
3393         }
3394     }
3395 
3396     return NGX_OK;
3397 }
3398 
3399 
3400 static ngx_int_t
ngx_ssl_session_id_context(ngx_ssl_t * ssl,ngx_str_t * sess_ctx,ngx_array_t * certificates)3401 ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
3402     ngx_array_t *certificates)
3403 {
3404     int                   n, i;
3405     X509                 *cert;
3406     X509_NAME            *name;
3407     ngx_str_t            *certs;
3408     ngx_uint_t            k;
3409     EVP_MD_CTX           *md;
3410     unsigned int          len;
3411     STACK_OF(X509_NAME)  *list;
3412     u_char                buf[EVP_MAX_MD_SIZE];
3413 
3414     /*
3415      * Session ID context is set based on the string provided,
3416      * the server certificates, and the client CA list.
3417      */
3418 
3419     md = EVP_MD_CTX_create();
3420     if (md == NULL) {
3421         return NGX_ERROR;
3422     }
3423 
3424     if (EVP_DigestInit_ex(md, EVP_sha1(), NULL) == 0) {
3425         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3426                       "EVP_DigestInit_ex() failed");
3427         goto failed;
3428     }
3429 
3430     if (EVP_DigestUpdate(md, sess_ctx->data, sess_ctx->len) == 0) {
3431         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3432                       "EVP_DigestUpdate() failed");
3433         goto failed;
3434     }
3435 
3436     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
3437          cert;
3438          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
3439     {
3440         if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
3441             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3442                           "X509_digest() failed");
3443             goto failed;
3444         }
3445 
3446         if (EVP_DigestUpdate(md, buf, len) == 0) {
3447             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3448                           "EVP_DigestUpdate() failed");
3449             goto failed;
3450         }
3451     }
3452 
3453     if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL
3454         && certificates != NULL)
3455     {
3456         /*
3457          * If certificates are loaded dynamically, we use certificate
3458          * names as specified in the configuration (with variables).
3459          */
3460 
3461         certs = certificates->elts;
3462         for (k = 0; k < certificates->nelts; k++) {
3463 
3464             if (EVP_DigestUpdate(md, certs[k].data, certs[k].len) == 0) {
3465                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3466                               "EVP_DigestUpdate() failed");
3467                 goto failed;
3468             }
3469         }
3470     }
3471 
3472     list = SSL_CTX_get_client_CA_list(ssl->ctx);
3473 
3474     if (list != NULL) {
3475         n = sk_X509_NAME_num(list);
3476 
3477         for (i = 0; i < n; i++) {
3478             name = sk_X509_NAME_value(list, i);
3479 
3480             if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) {
3481                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3482                               "X509_NAME_digest() failed");
3483                 goto failed;
3484             }
3485 
3486             if (EVP_DigestUpdate(md, buf, len) == 0) {
3487                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3488                               "EVP_DigestUpdate() failed");
3489                 goto failed;
3490             }
3491         }
3492     }
3493 
3494     if (EVP_DigestFinal_ex(md, buf, &len) == 0) {
3495         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3496                       "EVP_DigestFinal_ex() failed");
3497         goto failed;
3498     }
3499 
3500     EVP_MD_CTX_destroy(md);
3501 
3502     if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) {
3503         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
3504                       "SSL_CTX_set_session_id_context() failed");
3505         return NGX_ERROR;
3506     }
3507 
3508     return NGX_OK;
3509 
3510 failed:
3511 
3512     EVP_MD_CTX_destroy(md);
3513 
3514     return NGX_ERROR;
3515 }
3516 
3517 
3518 ngx_int_t
ngx_ssl_session_cache_init(ngx_shm_zone_t * shm_zone,void * data)3519 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
3520 {
3521     size_t                    len;
3522     ngx_slab_pool_t          *shpool;
3523     ngx_ssl_session_cache_t  *cache;
3524 
3525     if (data) {
3526         shm_zone->data = data;
3527         return NGX_OK;
3528     }
3529 
3530     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
3531 
3532     if (shm_zone->shm.exists) {
3533         shm_zone->data = shpool->data;
3534         return NGX_OK;
3535     }
3536 
3537     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
3538     if (cache == NULL) {
3539         return NGX_ERROR;
3540     }
3541 
3542     shpool->data = cache;
3543     shm_zone->data = cache;
3544 
3545     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
3546                     ngx_ssl_session_rbtree_insert_value);
3547 
3548     ngx_queue_init(&cache->expire_queue);
3549 
3550     len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
3551 
3552     shpool->log_ctx = ngx_slab_alloc(shpool, len);
3553     if (shpool->log_ctx == NULL) {
3554         return NGX_ERROR;
3555     }
3556 
3557     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
3558                 &shm_zone->shm.name);
3559 
3560     shpool->log_nomem = 0;
3561 
3562     return NGX_OK;
3563 }
3564 
3565 
3566 /*
3567  * The length of the session id is 16 bytes for SSLv2 sessions and
3568  * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
3569  * It seems that the typical length of the external ASN1 representation
3570  * of a session is 118 or 119 bytes for SSLv3/TSLv1.
3571  *
3572  * Thus on 32-bit platforms we allocate separately an rbtree node,
3573  * a session id, and an ASN1 representation, they take accordingly
3574  * 64, 32, and 128 bytes.
3575  *
3576  * On 64-bit platforms we allocate separately an rbtree node + session_id,
3577  * and an ASN1 representation, they take accordingly 128 and 128 bytes.
3578  *
3579  * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
3580  * so they are outside the code locked by shared pool mutex
3581  */
3582 
3583 static int
ngx_ssl_new_session(ngx_ssl_conn_t * ssl_conn,ngx_ssl_session_t * sess)3584 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
3585 {
3586     int                       len;
3587     u_char                   *p, *id, *cached_sess, *session_id;
3588     uint32_t                  hash;
3589     SSL_CTX                  *ssl_ctx;
3590     unsigned int              session_id_length;
3591     ngx_shm_zone_t           *shm_zone;
3592     ngx_connection_t         *c;
3593     ngx_slab_pool_t          *shpool;
3594     ngx_ssl_sess_id_t        *sess_id;
3595     ngx_ssl_session_cache_t  *cache;
3596     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
3597 
3598     len = i2d_SSL_SESSION(sess, NULL);
3599 
3600     /* do not cache too big session */
3601 
3602     if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
3603         return 0;
3604     }
3605 
3606     p = buf;
3607     i2d_SSL_SESSION(sess, &p);
3608 
3609     c = ngx_ssl_get_connection(ssl_conn);
3610 
3611     ssl_ctx = c->ssl->session_ctx;
3612     shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
3613 
3614     cache = shm_zone->data;
3615     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
3616 
3617     ngx_shmtx_lock(&shpool->mutex);
3618 
3619     /* drop one or two expired sessions */
3620     ngx_ssl_expire_sessions(cache, shpool, 1);
3621 
3622     cached_sess = ngx_slab_alloc_locked(shpool, len);
3623 
3624     if (cached_sess == NULL) {
3625 
3626         /* drop the oldest non-expired session and try once more */
3627 
3628         ngx_ssl_expire_sessions(cache, shpool, 0);
3629 
3630         cached_sess = ngx_slab_alloc_locked(shpool, len);
3631 
3632         if (cached_sess == NULL) {
3633             sess_id = NULL;
3634             goto failed;
3635         }
3636     }
3637 
3638     sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
3639 
3640     if (sess_id == NULL) {
3641 
3642         /* drop the oldest non-expired session and try once more */
3643 
3644         ngx_ssl_expire_sessions(cache, shpool, 0);
3645 
3646         sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
3647 
3648         if (sess_id == NULL) {
3649             goto failed;
3650         }
3651     }
3652 
3653     session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
3654 
3655 #if (NGX_PTR_SIZE == 8)
3656 
3657     id = sess_id->sess_id;
3658 
3659 #else
3660 
3661     id = ngx_slab_alloc_locked(shpool, session_id_length);
3662 
3663     if (id == NULL) {
3664 
3665         /* drop the oldest non-expired session and try once more */
3666 
3667         ngx_ssl_expire_sessions(cache, shpool, 0);
3668 
3669         id = ngx_slab_alloc_locked(shpool, session_id_length);
3670 
3671         if (id == NULL) {
3672             goto failed;
3673         }
3674     }
3675 
3676 #endif
3677 
3678     ngx_memcpy(cached_sess, buf, len);
3679 
3680     ngx_memcpy(id, session_id, session_id_length);
3681 
3682     hash = ngx_crc32_short(session_id, session_id_length);
3683 
3684     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
3685                    "ssl new session: %08XD:%ud:%d",
3686                    hash, session_id_length, len);
3687 
3688     sess_id->node.key = hash;
3689     sess_id->node.data = (u_char) session_id_length;
3690     sess_id->id = id;
3691     sess_id->len = len;
3692     sess_id->session = cached_sess;
3693 
3694     sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
3695 
3696     ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
3697 
3698     ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
3699 
3700     ngx_shmtx_unlock(&shpool->mutex);
3701 
3702     return 0;
3703 
3704 failed:
3705 
3706     if (cached_sess) {
3707         ngx_slab_free_locked(shpool, cached_sess);
3708     }
3709 
3710     if (sess_id) {
3711         ngx_slab_free_locked(shpool, sess_id);
3712     }
3713 
3714     ngx_shmtx_unlock(&shpool->mutex);
3715 
3716     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
3717                   "could not allocate new session%s", shpool->log_ctx);
3718 
3719     return 0;
3720 }
3721 
3722 
3723 static ngx_ssl_session_t *
ngx_ssl_get_cached_session(ngx_ssl_conn_t * ssl_conn,const u_char * id,int len,int * copy)3724 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
3725 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
3726     const
3727 #endif
3728     u_char *id, int len, int *copy)
3729 {
3730     size_t                    slen;
3731     uint32_t                  hash;
3732     ngx_int_t                 rc;
3733     const u_char             *p;
3734     ngx_shm_zone_t           *shm_zone;
3735     ngx_slab_pool_t          *shpool;
3736     ngx_rbtree_node_t        *node, *sentinel;
3737     ngx_ssl_session_t        *sess;
3738     ngx_ssl_sess_id_t        *sess_id;
3739     ngx_ssl_session_cache_t  *cache;
3740     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
3741     ngx_connection_t         *c;
3742 
3743     hash = ngx_crc32_short((u_char *) (uintptr_t) id, (size_t) len);
3744     *copy = 0;
3745 
3746     c = ngx_ssl_get_connection(ssl_conn);
3747 
3748     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3749                    "ssl get session: %08XD:%d", hash, len);
3750 
3751     shm_zone = SSL_CTX_get_ex_data(c->ssl->session_ctx,
3752                                    ngx_ssl_session_cache_index);
3753 
3754     cache = shm_zone->data;
3755 
3756     sess = NULL;
3757 
3758     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
3759 
3760     ngx_shmtx_lock(&shpool->mutex);
3761 
3762     node = cache->session_rbtree.root;
3763     sentinel = cache->session_rbtree.sentinel;
3764 
3765     while (node != sentinel) {
3766 
3767         if (hash < node->key) {
3768             node = node->left;
3769             continue;
3770         }
3771 
3772         if (hash > node->key) {
3773             node = node->right;
3774             continue;
3775         }
3776 
3777         /* hash == node->key */
3778 
3779         sess_id = (ngx_ssl_sess_id_t *) node;
3780 
3781         rc = ngx_memn2cmp((u_char *) (uintptr_t) id, sess_id->id,
3782                           (size_t) len, (size_t) node->data);
3783 
3784         if (rc == 0) {
3785 
3786             if (sess_id->expire > ngx_time()) {
3787                 slen = sess_id->len;
3788 
3789                 ngx_memcpy(buf, sess_id->session, slen);
3790 
3791                 ngx_shmtx_unlock(&shpool->mutex);
3792 
3793                 p = buf;
3794                 sess = d2i_SSL_SESSION(NULL, &p, slen);
3795 
3796                 return sess;
3797             }
3798 
3799             ngx_queue_remove(&sess_id->queue);
3800 
3801             ngx_rbtree_delete(&cache->session_rbtree, node);
3802 
3803             ngx_slab_free_locked(shpool, sess_id->session);
3804 #if (NGX_PTR_SIZE == 4)
3805             ngx_slab_free_locked(shpool, sess_id->id);
3806 #endif
3807             ngx_slab_free_locked(shpool, sess_id);
3808 
3809             sess = NULL;
3810 
3811             goto done;
3812         }
3813 
3814         node = (rc < 0) ? node->left : node->right;
3815     }
3816 
3817 done:
3818 
3819     ngx_shmtx_unlock(&shpool->mutex);
3820 
3821     return sess;
3822 }
3823 
3824 
3825 void
ngx_ssl_remove_cached_session(SSL_CTX * ssl,ngx_ssl_session_t * sess)3826 ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
3827 {
3828     SSL_CTX_remove_session(ssl, sess);
3829 
3830     ngx_ssl_remove_session(ssl, sess);
3831 }
3832 
3833 
3834 static void
ngx_ssl_remove_session(SSL_CTX * ssl,ngx_ssl_session_t * sess)3835 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
3836 {
3837     u_char                   *id;
3838     uint32_t                  hash;
3839     ngx_int_t                 rc;
3840     unsigned int              len;
3841     ngx_shm_zone_t           *shm_zone;
3842     ngx_slab_pool_t          *shpool;
3843     ngx_rbtree_node_t        *node, *sentinel;
3844     ngx_ssl_sess_id_t        *sess_id;
3845     ngx_ssl_session_cache_t  *cache;
3846 
3847     shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
3848 
3849     if (shm_zone == NULL) {
3850         return;
3851     }
3852 
3853     cache = shm_zone->data;
3854 
3855     id = (u_char *) SSL_SESSION_get_id(sess, &len);
3856 
3857     hash = ngx_crc32_short(id, len);
3858 
3859     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
3860                    "ssl remove session: %08XD:%ud", hash, len);
3861 
3862     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
3863 
3864     ngx_shmtx_lock(&shpool->mutex);
3865 
3866     node = cache->session_rbtree.root;
3867     sentinel = cache->session_rbtree.sentinel;
3868 
3869     while (node != sentinel) {
3870 
3871         if (hash < node->key) {
3872             node = node->left;
3873             continue;
3874         }
3875 
3876         if (hash > node->key) {
3877             node = node->right;
3878             continue;
3879         }
3880 
3881         /* hash == node->key */
3882 
3883         sess_id = (ngx_ssl_sess_id_t *) node;
3884 
3885         rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
3886 
3887         if (rc == 0) {
3888 
3889             ngx_queue_remove(&sess_id->queue);
3890 
3891             ngx_rbtree_delete(&cache->session_rbtree, node);
3892 
3893             ngx_slab_free_locked(shpool, sess_id->session);
3894 #if (NGX_PTR_SIZE == 4)
3895             ngx_slab_free_locked(shpool, sess_id->id);
3896 #endif
3897             ngx_slab_free_locked(shpool, sess_id);
3898 
3899             goto done;
3900         }
3901 
3902         node = (rc < 0) ? node->left : node->right;
3903     }
3904 
3905 done:
3906 
3907     ngx_shmtx_unlock(&shpool->mutex);
3908 }
3909 
3910 
3911 static void
ngx_ssl_expire_sessions(ngx_ssl_session_cache_t * cache,ngx_slab_pool_t * shpool,ngx_uint_t n)3912 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
3913     ngx_slab_pool_t *shpool, ngx_uint_t n)
3914 {
3915     time_t              now;
3916     ngx_queue_t        *q;
3917     ngx_ssl_sess_id_t  *sess_id;
3918 
3919     now = ngx_time();
3920 
3921     while (n < 3) {
3922 
3923         if (ngx_queue_empty(&cache->expire_queue)) {
3924             return;
3925         }
3926 
3927         q = ngx_queue_last(&cache->expire_queue);
3928 
3929         sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
3930 
3931         if (n++ != 0 && sess_id->expire > now) {
3932             return;
3933         }
3934 
3935         ngx_queue_remove(q);
3936 
3937         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
3938                        "expire session: %08Xi", sess_id->node.key);
3939 
3940         ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
3941 
3942         ngx_slab_free_locked(shpool, sess_id->session);
3943 #if (NGX_PTR_SIZE == 4)
3944         ngx_slab_free_locked(shpool, sess_id->id);
3945 #endif
3946         ngx_slab_free_locked(shpool, sess_id);
3947     }
3948 }
3949 
3950 
3951 static void
ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t * temp,ngx_rbtree_node_t * node,ngx_rbtree_node_t * sentinel)3952 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
3953     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
3954 {
3955     ngx_rbtree_node_t  **p;
3956     ngx_ssl_sess_id_t   *sess_id, *sess_id_temp;
3957 
3958     for ( ;; ) {
3959 
3960         if (node->key < temp->key) {
3961 
3962             p = &temp->left;
3963 
3964         } else if (node->key > temp->key) {
3965 
3966             p = &temp->right;
3967 
3968         } else { /* node->key == temp->key */
3969 
3970             sess_id = (ngx_ssl_sess_id_t *) node;
3971             sess_id_temp = (ngx_ssl_sess_id_t *) temp;
3972 
3973             p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
3974                               (size_t) node->data, (size_t) temp->data)
3975                  < 0) ? &temp->left : &temp->right;
3976         }
3977 
3978         if (*p == sentinel) {
3979             break;
3980         }
3981 
3982         temp = *p;
3983     }
3984 
3985     *p = node;
3986     node->parent = temp;
3987     node->left = sentinel;
3988     node->right = sentinel;
3989     ngx_rbt_red(node);
3990 }
3991 
3992 
3993 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
3994 
3995 ngx_int_t
ngx_ssl_session_ticket_keys(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_array_t * paths)3996 ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
3997 {
3998     u_char                         buf[80];
3999     size_t                         size;
4000     ssize_t                        n;
4001     ngx_str_t                     *path;
4002     ngx_file_t                     file;
4003     ngx_uint_t                     i;
4004     ngx_array_t                   *keys;
4005     ngx_file_info_t                fi;
4006     ngx_pool_cleanup_t            *cln;
4007     ngx_ssl_session_ticket_key_t  *key;
4008 
4009     if (paths == NULL) {
4010         return NGX_OK;
4011     }
4012 
4013     keys = ngx_array_create(cf->pool, paths->nelts,
4014                             sizeof(ngx_ssl_session_ticket_key_t));
4015     if (keys == NULL) {
4016         return NGX_ERROR;
4017     }
4018 
4019     cln = ngx_pool_cleanup_add(cf->pool, 0);
4020     if (cln == NULL) {
4021         return NGX_ERROR;
4022     }
4023 
4024     cln->handler = ngx_ssl_session_ticket_keys_cleanup;
4025     cln->data = keys;
4026 
4027     path = paths->elts;
4028     for (i = 0; i < paths->nelts; i++) {
4029 
4030         if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) {
4031             return NGX_ERROR;
4032         }
4033 
4034         ngx_memzero(&file, sizeof(ngx_file_t));
4035         file.name = path[i];
4036         file.log = cf->log;
4037 
4038         file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
4039                                 NGX_FILE_OPEN, 0);
4040 
4041         if (file.fd == NGX_INVALID_FILE) {
4042             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
4043                                ngx_open_file_n " \"%V\" failed", &file.name);
4044             return NGX_ERROR;
4045         }
4046 
4047         if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
4048             ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
4049                                ngx_fd_info_n " \"%V\" failed", &file.name);
4050             goto failed;
4051         }
4052 
4053         size = ngx_file_size(&fi);
4054 
4055         if (size != 48 && size != 80) {
4056             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4057                                "\"%V\" must be 48 or 80 bytes", &file.name);
4058             goto failed;
4059         }
4060 
4061         n = ngx_read_file(&file, buf, size, 0);
4062 
4063         if (n == NGX_ERROR) {
4064             ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
4065                                ngx_read_file_n " \"%V\" failed", &file.name);
4066             goto failed;
4067         }
4068 
4069         if ((size_t) n != size) {
4070             ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
4071                                ngx_read_file_n " \"%V\" returned only "
4072                                "%z bytes instead of %uz", &file.name, n, size);
4073             goto failed;
4074         }
4075 
4076         key = ngx_array_push(keys);
4077         if (key == NULL) {
4078             goto failed;
4079         }
4080 
4081         if (size == 48) {
4082             key->size = 48;
4083             ngx_memcpy(key->name, buf, 16);
4084             ngx_memcpy(key->aes_key, buf + 16, 16);
4085             ngx_memcpy(key->hmac_key, buf + 32, 16);
4086 
4087         } else {
4088             key->size = 80;
4089             ngx_memcpy(key->name, buf, 16);
4090             ngx_memcpy(key->hmac_key, buf + 16, 32);
4091             ngx_memcpy(key->aes_key, buf + 48, 32);
4092         }
4093 
4094         if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
4095             ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
4096                           ngx_close_file_n " \"%V\" failed", &file.name);
4097         }
4098 
4099         ngx_explicit_memzero(&buf, 80);
4100     }
4101 
4102     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
4103         == 0)
4104     {
4105         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
4106                       "SSL_CTX_set_ex_data() failed");
4107         return NGX_ERROR;
4108     }
4109 
4110     if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
4111                                          ngx_ssl_session_ticket_key_callback)
4112         == 0)
4113     {
4114         ngx_log_error(NGX_LOG_WARN, cf->log, 0,
4115                       "nginx was built with Session Tickets support, however, "
4116                       "now it is linked dynamically to an OpenSSL library "
4117                       "which has no tlsext support, therefore Session Tickets "
4118                       "are not available");
4119     }
4120 
4121     return NGX_OK;
4122 
4123 failed:
4124 
4125     if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
4126         ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
4127                       ngx_close_file_n " \"%V\" failed", &file.name);
4128     }
4129 
4130     ngx_explicit_memzero(&buf, 80);
4131 
4132     return NGX_ERROR;
4133 }
4134 
4135 
4136 static int
ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t * ssl_conn,unsigned char * name,unsigned char * iv,EVP_CIPHER_CTX * ectx,HMAC_CTX * hctx,int enc)4137 ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
4138     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
4139     HMAC_CTX *hctx, int enc)
4140 {
4141     size_t                         size;
4142     SSL_CTX                       *ssl_ctx;
4143     ngx_uint_t                     i;
4144     ngx_array_t                   *keys;
4145     ngx_connection_t              *c;
4146     ngx_ssl_session_ticket_key_t  *key;
4147     const EVP_MD                  *digest;
4148     const EVP_CIPHER              *cipher;
4149 
4150     c = ngx_ssl_get_connection(ssl_conn);
4151     ssl_ctx = c->ssl->session_ctx;
4152 
4153 #ifdef OPENSSL_NO_SHA256
4154     digest = EVP_sha1();
4155 #else
4156     digest = EVP_sha256();
4157 #endif
4158 
4159     keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
4160     if (keys == NULL) {
4161         return -1;
4162     }
4163 
4164     key = keys->elts;
4165 
4166     if (enc == 1) {
4167         /* encrypt session ticket */
4168 
4169         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4170                        "ssl session ticket encrypt, key: \"%*xs\" (%s session)",
4171                        (size_t) 16, key[0].name,
4172                        SSL_session_reused(ssl_conn) ? "reused" : "new");
4173 
4174         if (key[0].size == 48) {
4175             cipher = EVP_aes_128_cbc();
4176             size = 16;
4177 
4178         } else {
4179             cipher = EVP_aes_256_cbc();
4180             size = 32;
4181         }
4182 
4183         if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) {
4184             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "RAND_bytes() failed");
4185             return -1;
4186         }
4187 
4188         if (EVP_EncryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1) {
4189             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
4190                           "EVP_EncryptInit_ex() failed");
4191             return -1;
4192         }
4193 
4194 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
4195         if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) {
4196             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed");
4197             return -1;
4198         }
4199 #else
4200         HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL);
4201 #endif
4202 
4203         ngx_memcpy(name, key[0].name, 16);
4204 
4205         return 1;
4206 
4207     } else {
4208         /* decrypt session ticket */
4209 
4210         for (i = 0; i < keys->nelts; i++) {
4211             if (ngx_memcmp(name, key[i].name, 16) == 0) {
4212                 goto found;
4213             }
4214         }
4215 
4216         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
4217                        "ssl session ticket decrypt, key: \"%*xs\" not found",
4218                        (size_t) 16, name);
4219 
4220         return 0;
4221 
4222     found:
4223 
4224         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4225                        "ssl session ticket decrypt, key: \"%*xs\"%s",
4226                        (size_t) 16, key[i].name, (i == 0) ? " (default)" : "");
4227 
4228         if (key[i].size == 48) {
4229             cipher = EVP_aes_128_cbc();
4230             size = 16;
4231 
4232         } else {
4233             cipher = EVP_aes_256_cbc();
4234             size = 32;
4235         }
4236 
4237 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
4238         if (HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL) != 1) {
4239             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed");
4240             return -1;
4241         }
4242 #else
4243         HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL);
4244 #endif
4245 
4246         if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[i].aes_key, iv) != 1) {
4247             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
4248                           "EVP_DecryptInit_ex() failed");
4249             return -1;
4250         }
4251 
4252         return (i == 0) ? 1 : 2 /* renew */;
4253     }
4254 }
4255 
4256 
4257 static void
ngx_ssl_session_ticket_keys_cleanup(void * data)4258 ngx_ssl_session_ticket_keys_cleanup(void *data)
4259 {
4260     ngx_array_t  *keys = data;
4261 
4262     ngx_explicit_memzero(keys->elts,
4263                          keys->nelts * sizeof(ngx_ssl_session_ticket_key_t));
4264 }
4265 
4266 #else
4267 
4268 ngx_int_t
ngx_ssl_session_ticket_keys(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_array_t * paths)4269 ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
4270 {
4271     if (paths) {
4272         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
4273                       "\"ssl_session_ticket_key\" ignored, not supported");
4274     }
4275 
4276     return NGX_OK;
4277 }
4278 
4279 #endif
4280 
4281 
4282 void
ngx_ssl_cleanup_ctx(void * data)4283 ngx_ssl_cleanup_ctx(void *data)
4284 {
4285     ngx_ssl_t  *ssl = data;
4286 
4287     X509  *cert, *next;
4288 
4289     cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
4290 
4291     while (cert) {
4292         next = X509_get_ex_data(cert, ngx_ssl_next_certificate_index);
4293         X509_free(cert);
4294         cert = next;
4295     }
4296 
4297     SSL_CTX_free(ssl->ctx);
4298 }
4299 
4300 
4301 ngx_int_t
ngx_ssl_check_host(ngx_connection_t * c,ngx_str_t * name)4302 ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name)
4303 {
4304     X509   *cert;
4305 
4306     cert = SSL_get_peer_certificate(c->ssl->connection);
4307     if (cert == NULL) {
4308         return NGX_ERROR;
4309     }
4310 
4311 #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
4312 
4313     /* X509_check_host() is only available in OpenSSL 1.0.2+ */
4314 
4315     if (name->len == 0) {
4316         goto failed;
4317     }
4318 
4319     if (X509_check_host(cert, (char *) name->data, name->len, 0, NULL) != 1) {
4320         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4321                        "X509_check_host(): no match");
4322         goto failed;
4323     }
4324 
4325     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4326                    "X509_check_host(): match");
4327 
4328     goto found;
4329 
4330 #else
4331     {
4332     int                      n, i;
4333     X509_NAME               *sname;
4334     ASN1_STRING             *str;
4335     X509_NAME_ENTRY         *entry;
4336     GENERAL_NAME            *altname;
4337     STACK_OF(GENERAL_NAME)  *altnames;
4338 
4339     /*
4340      * As per RFC6125 and RFC2818, we check subjectAltName extension,
4341      * and if it's not present - commonName in Subject is checked.
4342      */
4343 
4344     altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4345 
4346     if (altnames) {
4347         n = sk_GENERAL_NAME_num(altnames);
4348 
4349         for (i = 0; i < n; i++) {
4350             altname = sk_GENERAL_NAME_value(altnames, i);
4351 
4352             if (altname->type != GEN_DNS) {
4353                 continue;
4354             }
4355 
4356             str = altname->d.dNSName;
4357 
4358             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
4359                            "SSL subjectAltName: \"%*s\"",
4360                            ASN1_STRING_length(str), ASN1_STRING_data(str));
4361 
4362             if (ngx_ssl_check_name(name, str) == NGX_OK) {
4363                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4364                                "SSL subjectAltName: match");
4365                 GENERAL_NAMES_free(altnames);
4366                 goto found;
4367             }
4368         }
4369 
4370         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4371                        "SSL subjectAltName: no match");
4372 
4373         GENERAL_NAMES_free(altnames);
4374         goto failed;
4375     }
4376 
4377     /*
4378      * If there is no subjectAltName extension, check commonName
4379      * in Subject.  While RFC2818 requires to only check "most specific"
4380      * CN, both Apache and OpenSSL check all CNs, and so do we.
4381      */
4382 
4383     sname = X509_get_subject_name(cert);
4384 
4385     if (sname == NULL) {
4386         goto failed;
4387     }
4388 
4389     i = -1;
4390     for ( ;; ) {
4391         i = X509_NAME_get_index_by_NID(sname, NID_commonName, i);
4392 
4393         if (i < 0) {
4394             break;
4395         }
4396 
4397         entry = X509_NAME_get_entry(sname, i);
4398         str = X509_NAME_ENTRY_get_data(entry);
4399 
4400         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
4401                        "SSL commonName: \"%*s\"",
4402                        ASN1_STRING_length(str), ASN1_STRING_data(str));
4403 
4404         if (ngx_ssl_check_name(name, str) == NGX_OK) {
4405             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4406                            "SSL commonName: match");
4407             goto found;
4408         }
4409     }
4410 
4411     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4412                    "SSL commonName: no match");
4413     }
4414 #endif
4415 
4416 failed:
4417 
4418     X509_free(cert);
4419     return NGX_ERROR;
4420 
4421 found:
4422 
4423     X509_free(cert);
4424     return NGX_OK;
4425 }
4426 
4427 
4428 #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
4429 
4430 static ngx_int_t
ngx_ssl_check_name(ngx_str_t * name,ASN1_STRING * pattern)4431 ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *pattern)
4432 {
4433     u_char  *s, *p, *end;
4434     size_t   slen, plen;
4435 
4436     s = name->data;
4437     slen = name->len;
4438 
4439     p = ASN1_STRING_data(pattern);
4440     plen = ASN1_STRING_length(pattern);
4441 
4442     if (slen == plen && ngx_strncasecmp(s, p, plen) == 0) {
4443         return NGX_OK;
4444     }
4445 
4446     if (plen > 2 && p[0] == '*' && p[1] == '.') {
4447         plen -= 1;
4448         p += 1;
4449 
4450         end = s + slen;
4451         s = ngx_strlchr(s, end, '.');
4452 
4453         if (s == NULL) {
4454             return NGX_ERROR;
4455         }
4456 
4457         slen = end - s;
4458 
4459         if (plen == slen && ngx_strncasecmp(s, p, plen) == 0) {
4460             return NGX_OK;
4461         }
4462     }
4463 
4464     return NGX_ERROR;
4465 }
4466 
4467 #endif
4468 
4469 
4470 ngx_int_t
ngx_ssl_get_protocol(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4471 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4472 {
4473     s->data = (u_char *) SSL_get_version(c->ssl->connection);
4474     return NGX_OK;
4475 }
4476 
4477 
4478 ngx_int_t
ngx_ssl_get_cipher_name(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4479 ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4480 {
4481     s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
4482     return NGX_OK;
4483 }
4484 
4485 
4486 ngx_int_t
ngx_ssl_get_ciphers(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4487 ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4488 {
4489 #ifdef SSL_CTRL_GET_RAW_CIPHERLIST
4490 
4491     int                n, i, bytes;
4492     size_t             len;
4493     u_char            *ciphers, *p;
4494     const SSL_CIPHER  *cipher;
4495 
4496     bytes = SSL_get0_raw_cipherlist(c->ssl->connection, NULL);
4497     n = SSL_get0_raw_cipherlist(c->ssl->connection, &ciphers);
4498 
4499     if (n <= 0) {
4500         s->len = 0;
4501         return NGX_OK;
4502     }
4503 
4504     len = 0;
4505     n /= bytes;
4506 
4507     for (i = 0; i < n; i++) {
4508         cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes);
4509 
4510         if (cipher) {
4511             len += ngx_strlen(SSL_CIPHER_get_name(cipher));
4512 
4513         } else {
4514             len += sizeof("0x") - 1 + bytes * (sizeof("00") - 1);
4515         }
4516 
4517         len += sizeof(":") - 1;
4518     }
4519 
4520     s->data = ngx_pnalloc(pool, len);
4521     if (s->data == NULL) {
4522         return NGX_ERROR;
4523     }
4524 
4525     p = s->data;
4526 
4527     for (i = 0; i < n; i++) {
4528         cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes);
4529 
4530         if (cipher) {
4531             p = ngx_sprintf(p, "%s", SSL_CIPHER_get_name(cipher));
4532 
4533         } else {
4534             p = ngx_sprintf(p, "0x");
4535             p = ngx_hex_dump(p, ciphers + i * bytes, bytes);
4536         }
4537 
4538         *p++ = ':';
4539     }
4540 
4541     p--;
4542 
4543     s->len = p - s->data;
4544 
4545 #else
4546 
4547     u_char  buf[4096];
4548 
4549     if (SSL_get_shared_ciphers(c->ssl->connection, (char *) buf, 4096)
4550         == NULL)
4551     {
4552         s->len = 0;
4553         return NGX_OK;
4554     }
4555 
4556     s->len = ngx_strlen(buf);
4557     s->data = ngx_pnalloc(pool, s->len);
4558     if (s->data == NULL) {
4559         return NGX_ERROR;
4560     }
4561 
4562     ngx_memcpy(s->data, buf, s->len);
4563 
4564 #endif
4565 
4566     return NGX_OK;
4567 }
4568 
4569 
4570 ngx_int_t
ngx_ssl_get_curves(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4571 ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4572 {
4573 #ifdef SSL_CTRL_GET_CURVES
4574 
4575     int         *curves, n, i, nid;
4576     u_char      *p;
4577     size_t       len;
4578 
4579     n = SSL_get1_curves(c->ssl->connection, NULL);
4580 
4581     if (n <= 0) {
4582         s->len = 0;
4583         return NGX_OK;
4584     }
4585 
4586     curves = ngx_palloc(pool, n * sizeof(int));
4587 
4588     n = SSL_get1_curves(c->ssl->connection, curves);
4589     len = 0;
4590 
4591     for (i = 0; i < n; i++) {
4592         nid = curves[i];
4593 
4594         if (nid & TLSEXT_nid_unknown) {
4595             len += sizeof("0x0000") - 1;
4596 
4597         } else {
4598             len += ngx_strlen(OBJ_nid2sn(nid));
4599         }
4600 
4601         len += sizeof(":") - 1;
4602     }
4603 
4604     s->data = ngx_pnalloc(pool, len);
4605     if (s->data == NULL) {
4606         return NGX_ERROR;
4607     }
4608 
4609     p = s->data;
4610 
4611     for (i = 0; i < n; i++) {
4612         nid = curves[i];
4613 
4614         if (nid & TLSEXT_nid_unknown) {
4615             p = ngx_sprintf(p, "0x%04xd", nid & 0xffff);
4616 
4617         } else {
4618             p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid));
4619         }
4620 
4621         *p++ = ':';
4622     }
4623 
4624     p--;
4625 
4626     s->len = p - s->data;
4627 
4628 #else
4629 
4630     s->len = 0;
4631 
4632 #endif
4633 
4634     return NGX_OK;
4635 }
4636 
4637 
4638 ngx_int_t
ngx_ssl_get_session_id(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4639 ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4640 {
4641     u_char        *buf;
4642     SSL_SESSION   *sess;
4643     unsigned int   len;
4644 
4645     sess = SSL_get0_session(c->ssl->connection);
4646     if (sess == NULL) {
4647         s->len = 0;
4648         return NGX_OK;
4649     }
4650 
4651     buf = (u_char *) SSL_SESSION_get_id(sess, &len);
4652 
4653     s->len = 2 * len;
4654     s->data = ngx_pnalloc(pool, 2 * len);
4655     if (s->data == NULL) {
4656         return NGX_ERROR;
4657     }
4658 
4659     ngx_hex_dump(s->data, buf, len);
4660 
4661     return NGX_OK;
4662 }
4663 
4664 
4665 ngx_int_t
ngx_ssl_get_session_reused(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4666 ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4667 {
4668     if (SSL_session_reused(c->ssl->connection)) {
4669         ngx_str_set(s, "r");
4670 
4671     } else {
4672         ngx_str_set(s, ".");
4673     }
4674 
4675     return NGX_OK;
4676 }
4677 
4678 
4679 ngx_int_t
ngx_ssl_get_early_data(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4680 ngx_ssl_get_early_data(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4681 {
4682     s->len = 0;
4683 
4684 #ifdef SSL_ERROR_EARLY_DATA_REJECTED
4685 
4686     /* BoringSSL */
4687 
4688     if (SSL_in_early_data(c->ssl->connection)) {
4689         ngx_str_set(s, "1");
4690     }
4691 
4692 #elif defined SSL_READ_EARLY_DATA_SUCCESS
4693 
4694     /* OpenSSL */
4695 
4696     if (!SSL_is_init_finished(c->ssl->connection)) {
4697         ngx_str_set(s, "1");
4698     }
4699 
4700 #endif
4701 
4702     return NGX_OK;
4703 }
4704 
4705 
4706 ngx_int_t
ngx_ssl_get_server_name(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4707 ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4708 {
4709 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4710 
4711     size_t       len;
4712     const char  *name;
4713 
4714     name = SSL_get_servername(c->ssl->connection, TLSEXT_NAMETYPE_host_name);
4715 
4716     if (name) {
4717         len = ngx_strlen(name);
4718 
4719         s->len = len;
4720         s->data = ngx_pnalloc(pool, len);
4721         if (s->data == NULL) {
4722             return NGX_ERROR;
4723         }
4724 
4725         ngx_memcpy(s->data, name, len);
4726 
4727         return NGX_OK;
4728     }
4729 
4730 #endif
4731 
4732     s->len = 0;
4733     return NGX_OK;
4734 }
4735 
4736 
4737 ngx_int_t
ngx_ssl_get_raw_certificate(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4738 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4739 {
4740     size_t   len;
4741     BIO     *bio;
4742     X509    *cert;
4743 
4744     s->len = 0;
4745 
4746     cert = SSL_get_peer_certificate(c->ssl->connection);
4747     if (cert == NULL) {
4748         return NGX_OK;
4749     }
4750 
4751     bio = BIO_new(BIO_s_mem());
4752     if (bio == NULL) {
4753         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
4754         X509_free(cert);
4755         return NGX_ERROR;
4756     }
4757 
4758     if (PEM_write_bio_X509(bio, cert) == 0) {
4759         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
4760         goto failed;
4761     }
4762 
4763     len = BIO_pending(bio);
4764     s->len = len;
4765 
4766     s->data = ngx_pnalloc(pool, len);
4767     if (s->data == NULL) {
4768         goto failed;
4769     }
4770 
4771     BIO_read(bio, s->data, len);
4772 
4773     BIO_free(bio);
4774     X509_free(cert);
4775 
4776     return NGX_OK;
4777 
4778 failed:
4779 
4780     BIO_free(bio);
4781     X509_free(cert);
4782 
4783     return NGX_ERROR;
4784 }
4785 
4786 
4787 ngx_int_t
ngx_ssl_get_certificate(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4788 ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4789 {
4790     u_char      *p;
4791     size_t       len;
4792     ngx_uint_t   i;
4793     ngx_str_t    cert;
4794 
4795     if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
4796         return NGX_ERROR;
4797     }
4798 
4799     if (cert.len == 0) {
4800         s->len = 0;
4801         return NGX_OK;
4802     }
4803 
4804     len = cert.len - 1;
4805 
4806     for (i = 0; i < cert.len - 1; i++) {
4807         if (cert.data[i] == LF) {
4808             len++;
4809         }
4810     }
4811 
4812     s->len = len;
4813     s->data = ngx_pnalloc(pool, len);
4814     if (s->data == NULL) {
4815         return NGX_ERROR;
4816     }
4817 
4818     p = s->data;
4819 
4820     for (i = 0; i < cert.len - 1; i++) {
4821         *p++ = cert.data[i];
4822         if (cert.data[i] == LF) {
4823             *p++ = '\t';
4824         }
4825     }
4826 
4827     return NGX_OK;
4828 }
4829 
4830 
4831 ngx_int_t
ngx_ssl_get_escaped_certificate(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4832 ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool,
4833     ngx_str_t *s)
4834 {
4835     ngx_str_t  cert;
4836     uintptr_t  n;
4837 
4838     if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
4839         return NGX_ERROR;
4840     }
4841 
4842     if (cert.len == 0) {
4843         s->len = 0;
4844         return NGX_OK;
4845     }
4846 
4847     n = ngx_escape_uri(NULL, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT);
4848 
4849     s->len = cert.len + n * 2;
4850     s->data = ngx_pnalloc(pool, s->len);
4851     if (s->data == NULL) {
4852         return NGX_ERROR;
4853     }
4854 
4855     ngx_escape_uri(s->data, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT);
4856 
4857     return NGX_OK;
4858 }
4859 
4860 
4861 ngx_int_t
ngx_ssl_get_subject_dn(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4862 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4863 {
4864     BIO        *bio;
4865     X509       *cert;
4866     X509_NAME  *name;
4867 
4868     s->len = 0;
4869 
4870     cert = SSL_get_peer_certificate(c->ssl->connection);
4871     if (cert == NULL) {
4872         return NGX_OK;
4873     }
4874 
4875     name = X509_get_subject_name(cert);
4876     if (name == NULL) {
4877         X509_free(cert);
4878         return NGX_ERROR;
4879     }
4880 
4881     bio = BIO_new(BIO_s_mem());
4882     if (bio == NULL) {
4883         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
4884         X509_free(cert);
4885         return NGX_ERROR;
4886     }
4887 
4888     if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) {
4889         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed");
4890         goto failed;
4891     }
4892 
4893     s->len = BIO_pending(bio);
4894     s->data = ngx_pnalloc(pool, s->len);
4895     if (s->data == NULL) {
4896         goto failed;
4897     }
4898 
4899     BIO_read(bio, s->data, s->len);
4900 
4901     BIO_free(bio);
4902     X509_free(cert);
4903 
4904     return NGX_OK;
4905 
4906 failed:
4907 
4908     BIO_free(bio);
4909     X509_free(cert);
4910 
4911     return NGX_ERROR;
4912 }
4913 
4914 
4915 ngx_int_t
ngx_ssl_get_issuer_dn(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4916 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4917 {
4918     BIO        *bio;
4919     X509       *cert;
4920     X509_NAME  *name;
4921 
4922     s->len = 0;
4923 
4924     cert = SSL_get_peer_certificate(c->ssl->connection);
4925     if (cert == NULL) {
4926         return NGX_OK;
4927     }
4928 
4929     name = X509_get_issuer_name(cert);
4930     if (name == NULL) {
4931         X509_free(cert);
4932         return NGX_ERROR;
4933     }
4934 
4935     bio = BIO_new(BIO_s_mem());
4936     if (bio == NULL) {
4937         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
4938         X509_free(cert);
4939         return NGX_ERROR;
4940     }
4941 
4942     if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) {
4943         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed");
4944         goto failed;
4945     }
4946 
4947     s->len = BIO_pending(bio);
4948     s->data = ngx_pnalloc(pool, s->len);
4949     if (s->data == NULL) {
4950         goto failed;
4951     }
4952 
4953     BIO_read(bio, s->data, s->len);
4954 
4955     BIO_free(bio);
4956     X509_free(cert);
4957 
4958     return NGX_OK;
4959 
4960 failed:
4961 
4962     BIO_free(bio);
4963     X509_free(cert);
4964 
4965     return NGX_ERROR;
4966 }
4967 
4968 
4969 ngx_int_t
ngx_ssl_get_subject_dn_legacy(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)4970 ngx_ssl_get_subject_dn_legacy(ngx_connection_t *c, ngx_pool_t *pool,
4971     ngx_str_t *s)
4972 {
4973     char       *p;
4974     size_t      len;
4975     X509       *cert;
4976     X509_NAME  *name;
4977 
4978     s->len = 0;
4979 
4980     cert = SSL_get_peer_certificate(c->ssl->connection);
4981     if (cert == NULL) {
4982         return NGX_OK;
4983     }
4984 
4985     name = X509_get_subject_name(cert);
4986     if (name == NULL) {
4987         X509_free(cert);
4988         return NGX_ERROR;
4989     }
4990 
4991     p = X509_NAME_oneline(name, NULL, 0);
4992     if (p == NULL) {
4993         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed");
4994         X509_free(cert);
4995         return NGX_ERROR;
4996     }
4997 
4998     for (len = 0; p[len]; len++) { /* void */ }
4999 
5000     s->len = len;
5001     s->data = ngx_pnalloc(pool, len);
5002     if (s->data == NULL) {
5003         OPENSSL_free(p);
5004         X509_free(cert);
5005         return NGX_ERROR;
5006     }
5007 
5008     ngx_memcpy(s->data, p, len);
5009 
5010     OPENSSL_free(p);
5011     X509_free(cert);
5012 
5013     return NGX_OK;
5014 }
5015 
5016 
5017 ngx_int_t
ngx_ssl_get_issuer_dn_legacy(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5018 ngx_ssl_get_issuer_dn_legacy(ngx_connection_t *c, ngx_pool_t *pool,
5019     ngx_str_t *s)
5020 {
5021     char       *p;
5022     size_t      len;
5023     X509       *cert;
5024     X509_NAME  *name;
5025 
5026     s->len = 0;
5027 
5028     cert = SSL_get_peer_certificate(c->ssl->connection);
5029     if (cert == NULL) {
5030         return NGX_OK;
5031     }
5032 
5033     name = X509_get_issuer_name(cert);
5034     if (name == NULL) {
5035         X509_free(cert);
5036         return NGX_ERROR;
5037     }
5038 
5039     p = X509_NAME_oneline(name, NULL, 0);
5040     if (p == NULL) {
5041         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed");
5042         X509_free(cert);
5043         return NGX_ERROR;
5044     }
5045 
5046     for (len = 0; p[len]; len++) { /* void */ }
5047 
5048     s->len = len;
5049     s->data = ngx_pnalloc(pool, len);
5050     if (s->data == NULL) {
5051         OPENSSL_free(p);
5052         X509_free(cert);
5053         return NGX_ERROR;
5054     }
5055 
5056     ngx_memcpy(s->data, p, len);
5057 
5058     OPENSSL_free(p);
5059     X509_free(cert);
5060 
5061     return NGX_OK;
5062 }
5063 
5064 
5065 ngx_int_t
ngx_ssl_get_serial_number(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5066 ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
5067 {
5068     size_t   len;
5069     X509    *cert;
5070     BIO     *bio;
5071 
5072     s->len = 0;
5073 
5074     cert = SSL_get_peer_certificate(c->ssl->connection);
5075     if (cert == NULL) {
5076         return NGX_OK;
5077     }
5078 
5079     bio = BIO_new(BIO_s_mem());
5080     if (bio == NULL) {
5081         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
5082         X509_free(cert);
5083         return NGX_ERROR;
5084     }
5085 
5086     i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
5087     len = BIO_pending(bio);
5088 
5089     s->len = len;
5090     s->data = ngx_pnalloc(pool, len);
5091     if (s->data == NULL) {
5092         BIO_free(bio);
5093         X509_free(cert);
5094         return NGX_ERROR;
5095     }
5096 
5097     BIO_read(bio, s->data, len);
5098     BIO_free(bio);
5099     X509_free(cert);
5100 
5101     return NGX_OK;
5102 }
5103 
5104 
5105 ngx_int_t
ngx_ssl_get_fingerprint(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5106 ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
5107 {
5108     X509          *cert;
5109     unsigned int   len;
5110     u_char         buf[EVP_MAX_MD_SIZE];
5111 
5112     s->len = 0;
5113 
5114     cert = SSL_get_peer_certificate(c->ssl->connection);
5115     if (cert == NULL) {
5116         return NGX_OK;
5117     }
5118 
5119     if (!X509_digest(cert, EVP_sha1(), buf, &len)) {
5120         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_digest() failed");
5121         X509_free(cert);
5122         return NGX_ERROR;
5123     }
5124 
5125     s->len = 2 * len;
5126     s->data = ngx_pnalloc(pool, 2 * len);
5127     if (s->data == NULL) {
5128         X509_free(cert);
5129         return NGX_ERROR;
5130     }
5131 
5132     ngx_hex_dump(s->data, buf, len);
5133 
5134     X509_free(cert);
5135 
5136     return NGX_OK;
5137 }
5138 
5139 
5140 ngx_int_t
ngx_ssl_get_client_verify(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5141 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
5142 {
5143     X509        *cert;
5144     long         rc;
5145     const char  *str;
5146 
5147     cert = SSL_get_peer_certificate(c->ssl->connection);
5148     if (cert == NULL) {
5149         ngx_str_set(s, "NONE");
5150         return NGX_OK;
5151     }
5152 
5153     X509_free(cert);
5154 
5155     rc = SSL_get_verify_result(c->ssl->connection);
5156 
5157     if (rc == X509_V_OK) {
5158         if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) {
5159             ngx_str_set(s, "SUCCESS");
5160             return NGX_OK;
5161         }
5162 
5163     } else {
5164         str = X509_verify_cert_error_string(rc);
5165     }
5166 
5167     s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
5168     if (s->data == NULL) {
5169         return NGX_ERROR;
5170     }
5171 
5172     s->len = ngx_sprintf(s->data, "FAILED:%s", str) - s->data;
5173 
5174     return NGX_OK;
5175 }
5176 
5177 
5178 ngx_int_t
ngx_ssl_get_client_v_start(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5179 ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
5180 {
5181     BIO     *bio;
5182     X509    *cert;
5183     size_t   len;
5184 
5185     s->len = 0;
5186 
5187     cert = SSL_get_peer_certificate(c->ssl->connection);
5188     if (cert == NULL) {
5189         return NGX_OK;
5190     }
5191 
5192     bio = BIO_new(BIO_s_mem());
5193     if (bio == NULL) {
5194         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
5195         X509_free(cert);
5196         return NGX_ERROR;
5197     }
5198 
5199 #if OPENSSL_VERSION_NUMBER > 0x10100000L
5200     ASN1_TIME_print(bio, X509_get0_notBefore(cert));
5201 #else
5202     ASN1_TIME_print(bio, X509_get_notBefore(cert));
5203 #endif
5204 
5205     len = BIO_pending(bio);
5206 
5207     s->len = len;
5208     s->data = ngx_pnalloc(pool, len);
5209     if (s->data == NULL) {
5210         BIO_free(bio);
5211         X509_free(cert);
5212         return NGX_ERROR;
5213     }
5214 
5215     BIO_read(bio, s->data, len);
5216     BIO_free(bio);
5217     X509_free(cert);
5218 
5219     return NGX_OK;
5220 }
5221 
5222 
5223 ngx_int_t
ngx_ssl_get_client_v_end(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5224 ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
5225 {
5226     BIO     *bio;
5227     X509    *cert;
5228     size_t   len;
5229 
5230     s->len = 0;
5231 
5232     cert = SSL_get_peer_certificate(c->ssl->connection);
5233     if (cert == NULL) {
5234         return NGX_OK;
5235     }
5236 
5237     bio = BIO_new(BIO_s_mem());
5238     if (bio == NULL) {
5239         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
5240         X509_free(cert);
5241         return NGX_ERROR;
5242     }
5243 
5244 #if OPENSSL_VERSION_NUMBER > 0x10100000L
5245     ASN1_TIME_print(bio, X509_get0_notAfter(cert));
5246 #else
5247     ASN1_TIME_print(bio, X509_get_notAfter(cert));
5248 #endif
5249 
5250     len = BIO_pending(bio);
5251 
5252     s->len = len;
5253     s->data = ngx_pnalloc(pool, len);
5254     if (s->data == NULL) {
5255         BIO_free(bio);
5256         X509_free(cert);
5257         return NGX_ERROR;
5258     }
5259 
5260     BIO_read(bio, s->data, len);
5261     BIO_free(bio);
5262     X509_free(cert);
5263 
5264     return NGX_OK;
5265 }
5266 
5267 
5268 ngx_int_t
ngx_ssl_get_client_v_remain(ngx_connection_t * c,ngx_pool_t * pool,ngx_str_t * s)5269 ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
5270 {
5271     X509    *cert;
5272     time_t   now, end;
5273 
5274     s->len = 0;
5275 
5276     cert = SSL_get_peer_certificate(c->ssl->connection);
5277     if (cert == NULL) {
5278         return NGX_OK;
5279     }
5280 
5281 #if OPENSSL_VERSION_NUMBER > 0x10100000L
5282     end = ngx_ssl_parse_time(X509_get0_notAfter(cert), c->log);
5283 #else
5284     end = ngx_ssl_parse_time(X509_get_notAfter(cert), c->log);
5285 #endif
5286 
5287     if (end == (time_t) NGX_ERROR) {
5288         X509_free(cert);
5289         return NGX_OK;
5290     }
5291 
5292     now = ngx_time();
5293 
5294     if (end < now + 86400) {
5295         ngx_str_set(s, "0");
5296         X509_free(cert);
5297         return NGX_OK;
5298     }
5299 
5300     s->data = ngx_pnalloc(pool, NGX_TIME_T_LEN);
5301     if (s->data == NULL) {
5302         X509_free(cert);
5303         return NGX_ERROR;
5304     }
5305 
5306     s->len = ngx_sprintf(s->data, "%T", (end - now) / 86400) - s->data;
5307 
5308     X509_free(cert);
5309 
5310     return NGX_OK;
5311 }
5312 
5313 
5314 static time_t
ngx_ssl_parse_time(const ASN1_TIME * asn1time,ngx_log_t * log)5315 ngx_ssl_parse_time(
5316 #if OPENSSL_VERSION_NUMBER > 0x10100000L
5317     const
5318 #endif
5319     ASN1_TIME *asn1time, ngx_log_t *log)
5320 {
5321     BIO     *bio;
5322     char    *value;
5323     size_t   len;
5324     time_t   time;
5325 
5326     /*
5327      * OpenSSL doesn't provide a way to convert ASN1_TIME
5328      * into time_t.  To do this, we use ASN1_TIME_print(),
5329      * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
5330      * "Feb  3 00:55:52 2015 GMT"), and parse the result.
5331      */
5332 
5333     bio = BIO_new(BIO_s_mem());
5334     if (bio == NULL) {
5335         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "BIO_new() failed");
5336         return NGX_ERROR;
5337     }
5338 
5339     /* fake weekday prepended to match C asctime() format */
5340 
5341     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
5342     ASN1_TIME_print(bio, asn1time);
5343     len = BIO_get_mem_data(bio, &value);
5344 
5345     time = ngx_parse_http_time((u_char *) value, len);
5346 
5347     BIO_free(bio);
5348 
5349     return time;
5350 }
5351 
5352 
5353 static void *
ngx_openssl_create_conf(ngx_cycle_t * cycle)5354 ngx_openssl_create_conf(ngx_cycle_t *cycle)
5355 {
5356     ngx_openssl_conf_t  *oscf;
5357 
5358     oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
5359     if (oscf == NULL) {
5360         return NULL;
5361     }
5362 
5363     /*
5364      * set by ngx_pcalloc():
5365      *
5366      *     oscf->engine = 0;
5367      */
5368 
5369     return oscf;
5370 }
5371 
5372 
5373 static char *
ngx_openssl_engine(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)5374 ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5375 {
5376 #ifndef OPENSSL_NO_ENGINE
5377 
5378     ngx_openssl_conf_t *oscf = conf;
5379 
5380     ENGINE     *engine;
5381     ngx_str_t  *value;
5382 
5383     if (oscf->engine) {
5384         return "is duplicate";
5385     }
5386 
5387     oscf->engine = 1;
5388 
5389     value = cf->args->elts;
5390 
5391     engine = ENGINE_by_id((char *) value[1].data);
5392 
5393     if (engine == NULL) {
5394         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
5395                       "ENGINE_by_id(\"%V\") failed", &value[1]);
5396         return NGX_CONF_ERROR;
5397     }
5398 
5399     if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
5400         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
5401                       "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
5402                       &value[1]);
5403 
5404         ENGINE_free(engine);
5405 
5406         return NGX_CONF_ERROR;
5407     }
5408 
5409     ENGINE_free(engine);
5410 
5411     return NGX_CONF_OK;
5412 
5413 #else
5414 
5415     return "is not supported";
5416 
5417 #endif
5418 }
5419 
5420 
5421 static void
ngx_openssl_exit(ngx_cycle_t * cycle)5422 ngx_openssl_exit(ngx_cycle_t *cycle)
5423 {
5424 #if OPENSSL_VERSION_NUMBER < 0x10100003L
5425 
5426     EVP_cleanup();
5427 #ifndef OPENSSL_NO_ENGINE
5428     ENGINE_cleanup();
5429 #endif
5430 
5431 #endif
5432 }
5433