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