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