Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / event / ngx_event_openssl.c
blob62ce12c14355267b2031c8cad52abcb77d462b1e
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
13 typedef struct {
14 ngx_uint_t engine; /* unsigned engine:1; */
15 } ngx_openssl_conf_t;
18 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
19 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
20 int ret);
21 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
22 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
23 static void ngx_ssl_write_handler(ngx_event_t *wev);
24 static void ngx_ssl_read_handler(ngx_event_t *rev);
25 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
26 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
27 ngx_err_t err, char *text);
28 static void ngx_ssl_clear_error(ngx_log_t *log);
30 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
31 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
32 ngx_ssl_session_t *sess);
33 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
34 u_char *id, int len, int *copy);
35 static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
36 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
37 ngx_slab_pool_t *shpool, ngx_uint_t n);
38 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
39 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
41 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
42 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
43 static void ngx_openssl_exit(ngx_cycle_t *cycle);
46 static ngx_command_t ngx_openssl_commands[] = {
48 { ngx_string("ssl_engine"),
49 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
50 ngx_openssl_engine,
53 NULL },
55 ngx_null_command
59 static ngx_core_module_t ngx_openssl_module_ctx = {
60 ngx_string("openssl"),
61 ngx_openssl_create_conf,
62 NULL
66 ngx_module_t ngx_openssl_module = {
67 NGX_MODULE_V1,
68 &ngx_openssl_module_ctx, /* module context */
69 ngx_openssl_commands, /* module directives */
70 NGX_CORE_MODULE, /* module type */
71 NULL, /* init master */
72 NULL, /* init module */
73 NULL, /* init process */
74 NULL, /* init thread */
75 NULL, /* exit thread */
76 NULL, /* exit process */
77 ngx_openssl_exit, /* exit master */
78 NGX_MODULE_V1_PADDING
82 int ngx_ssl_connection_index;
83 int ngx_ssl_server_conf_index;
84 int ngx_ssl_session_cache_index;
85 int ngx_ssl_certificate_index;
86 int ngx_ssl_stapling_index;
89 ngx_int_t
90 ngx_ssl_init(ngx_log_t *log)
92 OPENSSL_config(NULL);
94 SSL_library_init();
95 SSL_load_error_strings();
97 OpenSSL_add_all_algorithms();
99 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
100 #ifndef SSL_OP_NO_COMPRESSION
103 * Disable gzip compression in OpenSSL prior to 1.0.0 version,
104 * this saves about 522K per connection.
106 int n;
107 STACK_OF(SSL_COMP) *ssl_comp_methods;
109 ssl_comp_methods = SSL_COMP_get_compression_methods();
110 n = sk_SSL_COMP_num(ssl_comp_methods);
112 while (n--) {
113 (void) sk_SSL_COMP_pop(ssl_comp_methods);
116 #endif
117 #endif
119 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
121 if (ngx_ssl_connection_index == -1) {
122 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
123 return NGX_ERROR;
126 ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
127 NULL);
128 if (ngx_ssl_server_conf_index == -1) {
129 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
130 "SSL_CTX_get_ex_new_index() failed");
131 return NGX_ERROR;
134 ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
135 NULL);
136 if (ngx_ssl_session_cache_index == -1) {
137 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
138 "SSL_CTX_get_ex_new_index() failed");
139 return NGX_ERROR;
142 ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
143 NULL);
144 if (ngx_ssl_certificate_index == -1) {
145 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
146 "SSL_CTX_get_ex_new_index() failed");
147 return NGX_ERROR;
150 ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
151 NULL);
152 if (ngx_ssl_stapling_index == -1) {
153 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
154 "SSL_CTX_get_ex_new_index() failed");
155 return NGX_ERROR;
158 return NGX_OK;
162 ngx_int_t
163 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
165 ssl->ctx = SSL_CTX_new(SSLv23_method());
167 if (ssl->ctx == NULL) {
168 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
169 return NGX_ERROR;
172 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
173 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
174 "SSL_CTX_set_ex_data() failed");
175 return NGX_ERROR;
178 /* client side options */
180 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
181 SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
183 /* server side options */
185 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
186 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
188 /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
189 SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
191 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
192 SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
193 SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
195 SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
197 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
199 if (!(protocols & NGX_SSL_SSLv2)) {
200 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
202 if (!(protocols & NGX_SSL_SSLv3)) {
203 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
205 if (!(protocols & NGX_SSL_TLSv1)) {
206 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
208 #ifdef SSL_OP_NO_TLSv1_1
209 if (!(protocols & NGX_SSL_TLSv1_1)) {
210 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
212 #endif
213 #ifdef SSL_OP_NO_TLSv1_2
214 if (!(protocols & NGX_SSL_TLSv1_2)) {
215 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
217 #endif
219 #ifdef SSL_OP_NO_COMPRESSION
220 SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
221 #endif
223 #ifdef SSL_MODE_RELEASE_BUFFERS
224 SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
225 #endif
227 SSL_CTX_set_read_ahead(ssl->ctx, 1);
229 SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
231 return NGX_OK;
235 ngx_int_t
236 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
237 ngx_str_t *key)
239 BIO *bio;
240 X509 *x509;
241 u_long n;
243 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
244 return NGX_ERROR;
248 * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
249 * allow to access certificate later from SSL_CTX, so we reimplement
250 * it here
253 bio = BIO_new_file((char *) cert->data, "r");
254 if (bio == NULL) {
255 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
256 "BIO_new_file(\"%s\") failed", cert->data);
257 return NGX_ERROR;
260 x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
261 if (x509 == NULL) {
262 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
263 "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
264 BIO_free(bio);
265 return NGX_ERROR;
268 if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
269 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
270 "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
271 X509_free(x509);
272 BIO_free(bio);
273 return NGX_ERROR;
276 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
277 == 0)
279 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
280 "SSL_CTX_set_ex_data() failed");
281 return NGX_ERROR;
284 X509_free(x509);
286 /* read rest of the chain */
288 for ( ;; ) {
290 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
291 if (x509 == NULL) {
292 n = ERR_peek_last_error();
294 if (ERR_GET_LIB(n) == ERR_LIB_PEM
295 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
297 /* end of file */
298 ERR_clear_error();
299 break;
302 /* some real error */
304 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
305 "PEM_read_bio_X509(\"%s\") failed", cert->data);
306 BIO_free(bio);
307 return NGX_ERROR;
310 if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
311 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
312 "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
313 cert->data);
314 X509_free(x509);
315 BIO_free(bio);
316 return NGX_ERROR;
320 BIO_free(bio);
322 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
323 return NGX_ERROR;
326 if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
327 SSL_FILETYPE_PEM)
328 == 0)
330 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
331 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
332 return NGX_ERROR;
335 return NGX_OK;
339 ngx_int_t
340 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
341 ngx_int_t depth)
343 STACK_OF(X509_NAME) *list;
345 SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
347 SSL_CTX_set_verify_depth(ssl->ctx, depth);
349 if (cert->len == 0) {
350 return NGX_OK;
353 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
354 return NGX_ERROR;
357 if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
358 == 0)
360 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
361 "SSL_CTX_load_verify_locations(\"%s\") failed",
362 cert->data);
363 return NGX_ERROR;
366 list = SSL_load_client_CA_file((char *) cert->data);
368 if (list == NULL) {
369 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
370 "SSL_load_client_CA_file(\"%s\") failed", cert->data);
371 return NGX_ERROR;
375 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
376 * always leaved an error in the error queue
379 ERR_clear_error();
381 SSL_CTX_set_client_CA_list(ssl->ctx, list);
383 return NGX_OK;
387 ngx_int_t
388 ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
389 ngx_int_t depth)
391 SSL_CTX_set_verify_depth(ssl->ctx, depth);
393 if (cert->len == 0) {
394 return NGX_OK;
397 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
398 return NGX_ERROR;
401 if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
402 == 0)
404 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
405 "SSL_CTX_load_verify_locations(\"%s\") failed",
406 cert->data);
407 return NGX_ERROR;
410 return NGX_OK;
414 ngx_int_t
415 ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
417 X509_STORE *store;
418 X509_LOOKUP *lookup;
420 if (crl->len == 0) {
421 return NGX_OK;
424 if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
425 return NGX_ERROR;
428 store = SSL_CTX_get_cert_store(ssl->ctx);
430 if (store == NULL) {
431 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
432 "SSL_CTX_get_cert_store() failed");
433 return NGX_ERROR;
436 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
438 if (lookup == NULL) {
439 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
440 "X509_STORE_add_lookup() failed");
441 return NGX_ERROR;
444 if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
445 == 0)
447 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
448 "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
449 return NGX_ERROR;
452 X509_STORE_set_flags(store,
453 X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
455 return NGX_OK;
459 static int
460 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
462 #if (NGX_DEBUG)
463 char *subject, *issuer;
464 int err, depth;
465 X509 *cert;
466 X509_NAME *sname, *iname;
467 ngx_connection_t *c;
468 ngx_ssl_conn_t *ssl_conn;
470 ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
471 SSL_get_ex_data_X509_STORE_CTX_idx());
473 c = ngx_ssl_get_connection(ssl_conn);
475 cert = X509_STORE_CTX_get_current_cert(x509_store);
476 err = X509_STORE_CTX_get_error(x509_store);
477 depth = X509_STORE_CTX_get_error_depth(x509_store);
479 sname = X509_get_subject_name(cert);
480 subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
482 iname = X509_get_issuer_name(cert);
483 issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
485 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
486 "verify:%d, error:%d, depth:%d, "
487 "subject:\"%s\",issuer: \"%s\"",
488 ok, err, depth, subject, issuer);
490 if (sname) {
491 OPENSSL_free(subject);
494 if (iname) {
495 OPENSSL_free(issuer);
497 #endif
499 return 1;
503 static void
504 ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
506 ngx_connection_t *c;
508 if (where & SSL_CB_HANDSHAKE_START) {
509 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
511 if (c->ssl->handshaked) {
512 c->ssl->renegotiation = 1;
513 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
519 RSA *
520 ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length)
522 static RSA *key;
524 if (key_length == 512) {
525 if (key == NULL) {
526 key = RSA_generate_key(512, RSA_F4, NULL, NULL);
530 return key;
534 ngx_int_t
535 ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
537 DH *dh;
538 BIO *bio;
541 * -----BEGIN DH PARAMETERS-----
542 * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
543 * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
544 * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
545 * -----END DH PARAMETERS-----
548 static unsigned char dh1024_p[] = {
549 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
550 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
551 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
552 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
553 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
554 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
555 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
556 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
557 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
558 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
559 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
562 static unsigned char dh1024_g[] = { 0x02 };
565 if (file->len == 0) {
567 dh = DH_new();
568 if (dh == NULL) {
569 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
570 return NGX_ERROR;
573 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
574 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
576 if (dh->p == NULL || dh->g == NULL) {
577 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
578 DH_free(dh);
579 return NGX_ERROR;
582 SSL_CTX_set_tmp_dh(ssl->ctx, dh);
584 DH_free(dh);
586 return NGX_OK;
589 if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
590 return NGX_ERROR;
593 bio = BIO_new_file((char *) file->data, "r");
594 if (bio == NULL) {
595 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
596 "BIO_new_file(\"%s\") failed", file->data);
597 return NGX_ERROR;
600 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
601 if (dh == NULL) {
602 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
603 "PEM_read_bio_DHparams(\"%s\") failed", file->data);
604 BIO_free(bio);
605 return NGX_ERROR;
608 SSL_CTX_set_tmp_dh(ssl->ctx, dh);
610 DH_free(dh);
611 BIO_free(bio);
613 return NGX_OK;
617 ngx_int_t
618 ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
620 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
621 #ifndef OPENSSL_NO_ECDH
622 int nid;
623 EC_KEY *ecdh;
626 * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
627 * from RFC 4492 section 5.1.1, or explicitly described curves over
628 * binary fields. OpenSSL only supports the "named curves", which provide
629 * maximum interoperability.
632 nid = OBJ_sn2nid((const char *) name->data);
633 if (nid == 0) {
634 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
635 "Unknown curve name \"%s\"", name->data);
636 return NGX_ERROR;
639 ecdh = EC_KEY_new_by_curve_name(nid);
640 if (ecdh == NULL) {
641 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
642 "Unable to create curve \"%s\"", name->data);
643 return NGX_ERROR;
646 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
648 SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
650 EC_KEY_free(ecdh);
651 #endif
652 #endif
654 return NGX_OK;
658 ngx_int_t
659 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
661 ngx_ssl_connection_t *sc;
663 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
664 if (sc == NULL) {
665 return NGX_ERROR;
668 sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
670 sc->connection = SSL_new(ssl->ctx);
672 if (sc->connection == NULL) {
673 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
674 return NGX_ERROR;
677 if (SSL_set_fd(sc->connection, c->fd) == 0) {
678 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
679 return NGX_ERROR;
682 if (flags & NGX_SSL_CLIENT) {
683 SSL_set_connect_state(sc->connection);
685 } else {
686 SSL_set_accept_state(sc->connection);
689 if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
690 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
691 return NGX_ERROR;
694 c->ssl = sc;
696 return NGX_OK;
700 ngx_int_t
701 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
703 if (session) {
704 if (SSL_set_session(c->ssl->connection, session) == 0) {
705 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
706 return NGX_ERROR;
710 return NGX_OK;
714 ngx_int_t
715 ngx_ssl_handshake(ngx_connection_t *c)
717 int n, sslerr;
718 ngx_err_t err;
720 ngx_ssl_clear_error(c->log);
722 n = SSL_do_handshake(c->ssl->connection);
724 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
726 if (n == 1) {
728 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
729 return NGX_ERROR;
732 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
733 return NGX_ERROR;
736 #if (NGX_DEBUG)
738 char buf[129], *s, *d;
739 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
740 const
741 #endif
742 SSL_CIPHER *cipher;
744 cipher = SSL_get_current_cipher(c->ssl->connection);
746 if (cipher) {
747 SSL_CIPHER_description(cipher, &buf[1], 128);
749 for (s = &buf[1], d = buf; *s; s++) {
750 if (*s == ' ' && *d == ' ') {
751 continue;
754 if (*s == LF || *s == CR) {
755 continue;
758 *++d = *s;
761 if (*d != ' ') {
762 d++;
765 *d = '\0';
767 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
768 "SSL: %s, cipher: \"%s\"",
769 SSL_get_version(c->ssl->connection), &buf[1]);
771 if (SSL_session_reused(c->ssl->connection)) {
772 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
773 "SSL reused session");
776 } else {
777 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
778 "SSL no shared ciphers");
781 #endif
783 c->ssl->handshaked = 1;
785 c->recv = ngx_ssl_recv;
786 c->send = ngx_ssl_write;
787 c->recv_chain = ngx_ssl_recv_chain;
788 c->send_chain = ngx_ssl_send_chain;
790 /* initial handshake done, disable renegotiation (CVE-2009-3555) */
791 if (c->ssl->connection->s3) {
792 c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
795 return NGX_OK;
798 sslerr = SSL_get_error(c->ssl->connection, n);
800 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
802 if (sslerr == SSL_ERROR_WANT_READ) {
803 c->read->ready = 0;
804 c->read->handler = ngx_ssl_handshake_handler;
805 c->write->handler = ngx_ssl_handshake_handler;
807 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
808 return NGX_ERROR;
811 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
812 return NGX_ERROR;
815 return NGX_AGAIN;
818 if (sslerr == SSL_ERROR_WANT_WRITE) {
819 c->write->ready = 0;
820 c->read->handler = ngx_ssl_handshake_handler;
821 c->write->handler = ngx_ssl_handshake_handler;
823 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
824 return NGX_ERROR;
827 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
828 return NGX_ERROR;
831 return NGX_AGAIN;
834 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
836 c->ssl->no_wait_shutdown = 1;
837 c->ssl->no_send_shutdown = 1;
838 c->read->eof = 1;
840 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
841 ngx_log_error(NGX_LOG_INFO, c->log, err,
842 "peer closed connection in SSL handshake");
844 return NGX_ERROR;
847 c->read->error = 1;
849 ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
851 return NGX_ERROR;
855 static void
856 ngx_ssl_handshake_handler(ngx_event_t *ev)
858 ngx_connection_t *c;
860 c = ev->data;
862 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
863 "SSL handshake handler: %d", ev->write);
865 if (ev->timedout) {
866 c->ssl->handler(c);
867 return;
870 if (ngx_ssl_handshake(c) == NGX_AGAIN) {
871 return;
874 c->ssl->handler(c);
878 ssize_t
879 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl)
881 u_char *last;
882 ssize_t n, bytes;
883 ngx_buf_t *b;
885 bytes = 0;
887 b = cl->buf;
888 last = b->last;
890 for ( ;; ) {
892 n = ngx_ssl_recv(c, last, b->end - last);
894 if (n > 0) {
895 last += n;
896 bytes += n;
898 if (last == b->end) {
899 cl = cl->next;
901 if (cl == NULL) {
902 return bytes;
905 b = cl->buf;
906 last = b->last;
909 continue;
912 if (bytes) {
914 if (n == 0 || n == NGX_ERROR) {
915 c->read->ready = 1;
918 return bytes;
921 return n;
926 ssize_t
927 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
929 int n, bytes;
931 if (c->ssl->last == NGX_ERROR) {
932 c->read->error = 1;
933 return NGX_ERROR;
936 if (c->ssl->last == NGX_DONE) {
937 c->read->ready = 0;
938 c->read->eof = 1;
939 return 0;
942 bytes = 0;
944 ngx_ssl_clear_error(c->log);
947 * SSL_read() may return data in parts, so try to read
948 * until SSL_read() would return no data
951 for ( ;; ) {
953 n = SSL_read(c->ssl->connection, buf, size);
955 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
957 if (n > 0) {
958 bytes += n;
961 c->ssl->last = ngx_ssl_handle_recv(c, n);
963 if (c->ssl->last == NGX_OK) {
965 size -= n;
967 if (size == 0) {
968 return bytes;
971 buf += n;
973 continue;
976 if (bytes) {
977 return bytes;
980 switch (c->ssl->last) {
982 case NGX_DONE:
983 c->read->ready = 0;
984 c->read->eof = 1;
985 return 0;
987 case NGX_ERROR:
988 c->read->error = 1;
990 /* fall through */
992 case NGX_AGAIN:
993 return c->ssl->last;
999 static ngx_int_t
1000 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
1002 int sslerr;
1003 ngx_err_t err;
1005 if (c->ssl->renegotiation) {
1007 * disable renegotiation (CVE-2009-3555):
1008 * OpenSSL (at least up to 0.9.8l) does not handle disabled
1009 * renegotiation gracefully, so drop connection here
1012 ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
1014 while (ERR_peek_error()) {
1015 ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
1016 "ignoring stale global SSL error");
1019 ERR_clear_error();
1021 c->ssl->no_wait_shutdown = 1;
1022 c->ssl->no_send_shutdown = 1;
1024 return NGX_ERROR;
1027 if (n > 0) {
1029 if (c->ssl->saved_write_handler) {
1031 c->write->handler = c->ssl->saved_write_handler;
1032 c->ssl->saved_write_handler = NULL;
1033 c->write->ready = 1;
1035 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1036 return NGX_ERROR;
1039 ngx_post_event(c->write, &ngx_posted_events);
1042 return NGX_OK;
1045 sslerr = SSL_get_error(c->ssl->connection, n);
1047 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1049 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1051 if (sslerr == SSL_ERROR_WANT_READ) {
1052 c->read->ready = 0;
1053 return NGX_AGAIN;
1056 if (sslerr == SSL_ERROR_WANT_WRITE) {
1058 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1059 "peer started SSL renegotiation");
1061 c->write->ready = 0;
1063 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1064 return NGX_ERROR;
1068 * we do not set the timer because there is already the read event timer
1071 if (c->ssl->saved_write_handler == NULL) {
1072 c->ssl->saved_write_handler = c->write->handler;
1073 c->write->handler = ngx_ssl_write_handler;
1076 return NGX_AGAIN;
1079 c->ssl->no_wait_shutdown = 1;
1080 c->ssl->no_send_shutdown = 1;
1082 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
1083 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1084 "peer shutdown SSL cleanly");
1085 return NGX_DONE;
1088 ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
1090 return NGX_ERROR;
1094 static void
1095 ngx_ssl_write_handler(ngx_event_t *wev)
1097 ngx_connection_t *c;
1099 c = wev->data;
1101 c->read->handler(c->read);
1106 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
1107 * before the SSL_write() call to decrease a SSL overhead.
1109 * Besides for protocols such as HTTP it is possible to always buffer
1110 * the output to decrease a SSL overhead some more.
1113 ngx_chain_t *
1114 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
1116 int n;
1117 ngx_uint_t flush;
1118 ssize_t send, size;
1119 ngx_buf_t *buf;
1121 if (!c->ssl->buffer) {
1123 while (in) {
1124 if (ngx_buf_special(in->buf)) {
1125 in = in->next;
1126 continue;
1129 n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
1131 if (n == NGX_ERROR) {
1132 return NGX_CHAIN_ERROR;
1135 if (n == NGX_AGAIN) {
1136 return in;
1139 in->buf->pos += n;
1140 c->sent += n;
1142 if (in->buf->pos == in->buf->last) {
1143 in = in->next;
1147 return in;
1151 /* the maximum limit size is the maximum int32_t value - the page size */
1153 if (limit == 0 || limit > (off_t) (NGX_MAX_INT32_VALUE - ngx_pagesize)) {
1154 limit = NGX_MAX_INT32_VALUE - ngx_pagesize;
1157 buf = c->ssl->buf;
1159 if (buf == NULL) {
1160 buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
1161 if (buf == NULL) {
1162 return NGX_CHAIN_ERROR;
1165 c->ssl->buf = buf;
1168 if (buf->start == NULL) {
1169 buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
1170 if (buf->start == NULL) {
1171 return NGX_CHAIN_ERROR;
1174 buf->pos = buf->start;
1175 buf->last = buf->start;
1176 buf->end = buf->start + NGX_SSL_BUFSIZE;
1179 send = buf->last - buf->pos;
1180 flush = (in == NULL) ? 1 : buf->flush;
1182 for ( ;; ) {
1184 while (in && buf->last < buf->end && send < limit) {
1185 if (in->buf->last_buf || in->buf->flush) {
1186 flush = 1;
1189 if (ngx_buf_special(in->buf)) {
1190 in = in->next;
1191 continue;
1194 size = in->buf->last - in->buf->pos;
1196 if (size > buf->end - buf->last) {
1197 size = buf->end - buf->last;
1200 if (send + size > limit) {
1201 size = (ssize_t) (limit - send);
1204 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1205 "SSL buf copy: %d", size);
1207 ngx_memcpy(buf->last, in->buf->pos, size);
1209 buf->last += size;
1210 in->buf->pos += size;
1211 send += size;
1213 if (in->buf->pos == in->buf->last) {
1214 in = in->next;
1218 if (!flush && send < limit && buf->last < buf->end) {
1219 break;
1222 size = buf->last - buf->pos;
1224 if (size == 0) {
1225 buf->flush = 0;
1226 c->buffered &= ~NGX_SSL_BUFFERED;
1227 return in;
1230 n = ngx_ssl_write(c, buf->pos, size);
1232 if (n == NGX_ERROR) {
1233 return NGX_CHAIN_ERROR;
1236 if (n == NGX_AGAIN) {
1237 break;
1240 buf->pos += n;
1241 c->sent += n;
1243 if (n < size) {
1244 break;
1247 flush = 0;
1249 buf->pos = buf->start;
1250 buf->last = buf->start;
1252 if (in == NULL || send == limit) {
1253 break;
1257 buf->flush = flush;
1259 if (buf->pos < buf->last) {
1260 c->buffered |= NGX_SSL_BUFFERED;
1262 } else {
1263 c->buffered &= ~NGX_SSL_BUFFERED;
1266 return in;
1270 ssize_t
1271 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
1273 int n, sslerr;
1274 ngx_err_t err;
1276 ngx_ssl_clear_error(c->log);
1278 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
1280 n = SSL_write(c->ssl->connection, data, size);
1282 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
1284 if (n > 0) {
1286 if (c->ssl->saved_read_handler) {
1288 c->read->handler = c->ssl->saved_read_handler;
1289 c->ssl->saved_read_handler = NULL;
1290 c->read->ready = 1;
1292 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1293 return NGX_ERROR;
1296 ngx_post_event(c->read, &ngx_posted_events);
1299 return n;
1302 sslerr = SSL_get_error(c->ssl->connection, n);
1304 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1306 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1308 if (sslerr == SSL_ERROR_WANT_WRITE) {
1309 c->write->ready = 0;
1310 return NGX_AGAIN;
1313 if (sslerr == SSL_ERROR_WANT_READ) {
1315 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1316 "peer started SSL renegotiation");
1318 c->read->ready = 0;
1320 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1321 return NGX_ERROR;
1325 * we do not set the timer because there is already
1326 * the write event timer
1329 if (c->ssl->saved_read_handler == NULL) {
1330 c->ssl->saved_read_handler = c->read->handler;
1331 c->read->handler = ngx_ssl_read_handler;
1334 return NGX_AGAIN;
1337 c->ssl->no_wait_shutdown = 1;
1338 c->ssl->no_send_shutdown = 1;
1339 c->write->error = 1;
1341 ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
1343 return NGX_ERROR;
1347 static void
1348 ngx_ssl_read_handler(ngx_event_t *rev)
1350 ngx_connection_t *c;
1352 c = rev->data;
1354 c->write->handler(c->write);
1358 void
1359 ngx_ssl_free_buffer(ngx_connection_t *c)
1361 if (c->ssl->buf && c->ssl->buf->start) {
1362 if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1363 c->ssl->buf->start = NULL;
1369 ngx_int_t
1370 ngx_ssl_shutdown(ngx_connection_t *c)
1372 int n, sslerr, mode;
1373 ngx_err_t err;
1375 if (c->timedout) {
1376 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1377 SSL_set_quiet_shutdown(c->ssl->connection, 1);
1379 } else {
1380 mode = SSL_get_shutdown(c->ssl->connection);
1382 if (c->ssl->no_wait_shutdown) {
1383 mode |= SSL_RECEIVED_SHUTDOWN;
1386 if (c->ssl->no_send_shutdown) {
1387 mode |= SSL_SENT_SHUTDOWN;
1390 if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
1391 SSL_set_quiet_shutdown(c->ssl->connection, 1);
1395 SSL_set_shutdown(c->ssl->connection, mode);
1397 ngx_ssl_clear_error(c->log);
1399 n = SSL_shutdown(c->ssl->connection);
1401 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1403 sslerr = 0;
1405 /* SSL_shutdown() never returns -1, on error it returns 0 */
1407 if (n != 1 && ERR_peek_error()) {
1408 sslerr = SSL_get_error(c->ssl->connection, n);
1410 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1411 "SSL_get_error: %d", sslerr);
1414 if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1415 SSL_free(c->ssl->connection);
1416 c->ssl = NULL;
1418 return NGX_OK;
1421 if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1422 c->read->handler = ngx_ssl_shutdown_handler;
1423 c->write->handler = ngx_ssl_shutdown_handler;
1425 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1426 return NGX_ERROR;
1429 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1430 return NGX_ERROR;
1433 if (sslerr == SSL_ERROR_WANT_READ) {
1434 ngx_add_timer(c->read, 30000);
1437 return NGX_AGAIN;
1440 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1442 ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1444 SSL_free(c->ssl->connection);
1445 c->ssl = NULL;
1447 return NGX_ERROR;
1451 static void
1452 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1454 ngx_connection_t *c;
1455 ngx_connection_handler_pt handler;
1457 c = ev->data;
1458 handler = c->ssl->handler;
1460 if (ev->timedout) {
1461 c->timedout = 1;
1464 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
1466 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1467 return;
1470 handler(c);
1474 static void
1475 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
1476 char *text)
1478 int n;
1479 ngx_uint_t level;
1481 level = NGX_LOG_CRIT;
1483 if (sslerr == SSL_ERROR_SYSCALL) {
1485 if (err == NGX_ECONNRESET
1486 || err == NGX_EPIPE
1487 || err == NGX_ENOTCONN
1488 || err == NGX_ETIMEDOUT
1489 || err == NGX_ECONNREFUSED
1490 || err == NGX_ENETDOWN
1491 || err == NGX_ENETUNREACH
1492 || err == NGX_EHOSTDOWN
1493 || err == NGX_EHOSTUNREACH)
1495 switch (c->log_error) {
1497 case NGX_ERROR_IGNORE_ECONNRESET:
1498 case NGX_ERROR_INFO:
1499 level = NGX_LOG_INFO;
1500 break;
1502 case NGX_ERROR_ERR:
1503 level = NGX_LOG_ERR;
1504 break;
1506 default:
1507 break;
1511 } else if (sslerr == SSL_ERROR_SSL) {
1513 n = ERR_GET_REASON(ERR_peek_error());
1515 /* handshake failures */
1516 if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC /* 103 */
1517 || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */
1518 || n == SSL_R_DIGEST_CHECK_FAILED /* 149 */
1519 || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST /* 151 */
1520 || n == SSL_R_EXCESSIVE_MESSAGE_SIZE /* 152 */
1521 || n == SSL_R_LENGTH_MISMATCH /* 159 */
1522 || n == SSL_R_NO_CIPHERS_PASSED /* 182 */
1523 || n == SSL_R_NO_CIPHERS_SPECIFIED /* 183 */
1524 || n == SSL_R_NO_COMPRESSION_SPECIFIED /* 187 */
1525 || n == SSL_R_NO_SHARED_CIPHER /* 193 */
1526 || n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */
1527 #ifdef SSL_R_PARSE_TLSEXT
1528 || n == SSL_R_PARSE_TLSEXT /* 227 */
1529 #endif
1530 || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */
1531 || n == SSL_R_UNEXPECTED_RECORD /* 245 */
1532 || n == SSL_R_UNKNOWN_ALERT_TYPE /* 246 */
1533 || n == SSL_R_UNKNOWN_PROTOCOL /* 252 */
1534 || n == SSL_R_WRONG_VERSION_NUMBER /* 267 */
1535 || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */
1536 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
1537 || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG /* 335 */
1538 || n == SSL_R_RENEGOTIATION_ENCODING_ERR /* 336 */
1539 || n == SSL_R_RENEGOTIATION_MISMATCH /* 337 */
1540 #endif
1541 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
1542 || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED /* 338 */
1543 #endif
1544 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
1545 || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING /* 345 */
1546 #endif
1547 || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
1548 || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */
1549 || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */
1550 || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED /* 1021 */
1551 || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW /* 1022 */
1552 || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE /* 1030 */
1553 || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE /* 1040 */
1554 || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE /* 1041 */
1555 || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE /* 1042 */
1556 || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE /* 1043 */
1557 || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED /* 1044 */
1558 || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED /* 1045 */
1559 || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN /* 1046 */
1560 || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER /* 1047 */
1561 || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA /* 1048 */
1562 || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED /* 1049 */
1563 || n == SSL_R_TLSV1_ALERT_DECODE_ERROR /* 1050 */
1564 || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR /* 1051 */
1565 || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION /* 1060 */
1566 || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION /* 1070 */
1567 || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY /* 1071 */
1568 || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR /* 1080 */
1569 || n == SSL_R_TLSV1_ALERT_USER_CANCELLED /* 1090 */
1570 || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION) /* 1100 */
1572 switch (c->log_error) {
1574 case NGX_ERROR_IGNORE_ECONNRESET:
1575 case NGX_ERROR_INFO:
1576 level = NGX_LOG_INFO;
1577 break;
1579 case NGX_ERROR_ERR:
1580 level = NGX_LOG_ERR;
1581 break;
1583 default:
1584 break;
1589 ngx_ssl_error(level, c->log, err, text);
1593 static void
1594 ngx_ssl_clear_error(ngx_log_t *log)
1596 while (ERR_peek_error()) {
1597 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
1600 ERR_clear_error();
1604 void ngx_cdecl
1605 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1607 int flags;
1608 u_long n;
1609 va_list args;
1610 u_char *p, *last;
1611 u_char errstr[NGX_MAX_CONF_ERRSTR];
1612 const char *data;
1614 last = errstr + NGX_MAX_CONF_ERRSTR;
1616 va_start(args, fmt);
1617 p = ngx_vslprintf(errstr, last - 1, fmt, args);
1618 va_end(args);
1620 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
1622 for ( ;; ) {
1624 n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
1626 if (n == 0) {
1627 break;
1630 if (p >= last) {
1631 goto next;
1634 *p++ = ' ';
1636 ERR_error_string_n(n, (char *) p, last - p);
1638 while (p < last && *p) {
1639 p++;
1642 if (p < last && *data && (flags & ERR_TXT_STRING)) {
1643 *p++ = ':';
1644 p = ngx_cpystrn(p, (u_char *) data, last - p);
1647 next:
1649 (void) ERR_get_error();
1652 ngx_log_error(level, log, err, "%s)", errstr);
1656 ngx_int_t
1657 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
1658 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
1660 long cache_mode;
1662 if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1663 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1664 return NGX_OK;
1667 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
1669 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
1672 * If the server explicitly says that it does not support
1673 * session reuse (see SSL_SESS_CACHE_OFF above), then
1674 * Outlook Express fails to upload a sent email to
1675 * the Sent Items folder on the IMAP server via a separate IMAP
1676 * connection in the background. Therefore we have a special
1677 * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
1678 * where the server pretends that it supports session reuse,
1679 * but it does not actually store any session.
1682 SSL_CTX_set_session_cache_mode(ssl->ctx,
1683 SSL_SESS_CACHE_SERVER
1684 |SSL_SESS_CACHE_NO_AUTO_CLEAR
1685 |SSL_SESS_CACHE_NO_INTERNAL_STORE);
1687 SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
1689 return NGX_OK;
1692 cache_mode = SSL_SESS_CACHE_SERVER;
1694 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
1695 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
1698 SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
1700 if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
1702 if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
1703 SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
1707 SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
1709 if (shm_zone) {
1710 SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
1711 SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
1712 SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
1714 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
1715 == 0)
1717 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1718 "SSL_CTX_set_ex_data() failed");
1719 return NGX_ERROR;
1723 return NGX_OK;
1727 ngx_int_t
1728 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
1730 size_t len;
1731 ngx_slab_pool_t *shpool;
1732 ngx_ssl_session_cache_t *cache;
1734 if (data) {
1735 shm_zone->data = data;
1736 return NGX_OK;
1739 if (shm_zone->shm.exists) {
1740 shm_zone->data = data;
1741 return NGX_OK;
1744 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1746 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
1747 if (cache == NULL) {
1748 return NGX_ERROR;
1751 shpool->data = cache;
1752 shm_zone->data = cache;
1754 ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
1755 ngx_ssl_session_rbtree_insert_value);
1757 ngx_queue_init(&cache->expire_queue);
1759 len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
1761 shpool->log_ctx = ngx_slab_alloc(shpool, len);
1762 if (shpool->log_ctx == NULL) {
1763 return NGX_ERROR;
1766 ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
1767 &shm_zone->shm.name);
1769 return NGX_OK;
1774 * The length of the session id is 16 bytes for SSLv2 sessions and
1775 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1776 * It seems that the typical length of the external ASN1 representation
1777 * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1779 * Thus on 32-bit platforms we allocate separately an rbtree node,
1780 * a session id, and an ASN1 representation, they take accordingly
1781 * 64, 32, and 128 bytes.
1783 * On 64-bit platforms we allocate separately an rbtree node + session_id,
1784 * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1786 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1787 * so they are outside the code locked by shared pool mutex
1790 static int
1791 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1793 int len;
1794 u_char *p, *id, *cached_sess;
1795 uint32_t hash;
1796 SSL_CTX *ssl_ctx;
1797 ngx_shm_zone_t *shm_zone;
1798 ngx_connection_t *c;
1799 ngx_slab_pool_t *shpool;
1800 ngx_ssl_sess_id_t *sess_id;
1801 ngx_ssl_session_cache_t *cache;
1802 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1804 len = i2d_SSL_SESSION(sess, NULL);
1806 /* do not cache too big session */
1808 if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
1809 return 0;
1812 p = buf;
1813 i2d_SSL_SESSION(sess, &p);
1815 c = ngx_ssl_get_connection(ssl_conn);
1817 ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
1818 shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
1820 cache = shm_zone->data;
1821 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1823 ngx_shmtx_lock(&shpool->mutex);
1825 /* drop one or two expired sessions */
1826 ngx_ssl_expire_sessions(cache, shpool, 1);
1828 cached_sess = ngx_slab_alloc_locked(shpool, len);
1830 if (cached_sess == NULL) {
1832 /* drop the oldest non-expired session and try once more */
1834 ngx_ssl_expire_sessions(cache, shpool, 0);
1836 cached_sess = ngx_slab_alloc_locked(shpool, len);
1838 if (cached_sess == NULL) {
1839 sess_id = NULL;
1840 goto failed;
1844 sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1846 if (sess_id == NULL) {
1848 /* drop the oldest non-expired session and try once more */
1850 ngx_ssl_expire_sessions(cache, shpool, 0);
1852 sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1854 if (sess_id == NULL) {
1855 goto failed;
1859 #if (NGX_PTR_SIZE == 8)
1861 id = sess_id->sess_id;
1863 #else
1865 id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1867 if (id == NULL) {
1869 /* drop the oldest non-expired session and try once more */
1871 ngx_ssl_expire_sessions(cache, shpool, 0);
1873 id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1875 if (id == NULL) {
1876 goto failed;
1880 #endif
1882 ngx_memcpy(cached_sess, buf, len);
1884 ngx_memcpy(id, sess->session_id, sess->session_id_length);
1886 hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
1888 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1889 "ssl new session: %08XD:%d:%d",
1890 hash, sess->session_id_length, len);
1892 sess_id->node.key = hash;
1893 sess_id->node.data = (u_char) sess->session_id_length;
1894 sess_id->id = id;
1895 sess_id->len = len;
1896 sess_id->session = cached_sess;
1898 sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
1900 ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
1902 ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
1904 ngx_shmtx_unlock(&shpool->mutex);
1906 return 0;
1908 failed:
1910 if (cached_sess) {
1911 ngx_slab_free_locked(shpool, cached_sess);
1914 if (sess_id) {
1915 ngx_slab_free_locked(shpool, sess_id);
1918 ngx_shmtx_unlock(&shpool->mutex);
1920 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1921 "could not add new SSL session to the session cache");
1923 return 0;
1927 static ngx_ssl_session_t *
1928 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
1929 int *copy)
1931 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1932 const
1933 #endif
1934 u_char *p;
1935 uint32_t hash;
1936 ngx_int_t rc;
1937 ngx_shm_zone_t *shm_zone;
1938 ngx_slab_pool_t *shpool;
1939 ngx_rbtree_node_t *node, *sentinel;
1940 ngx_ssl_session_t *sess;
1941 ngx_ssl_sess_id_t *sess_id;
1942 ngx_ssl_session_cache_t *cache;
1943 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1944 #if (NGX_DEBUG)
1945 ngx_connection_t *c;
1946 #endif
1948 hash = ngx_crc32_short(id, (size_t) len);
1949 *copy = 0;
1951 #if (NGX_DEBUG)
1952 c = ngx_ssl_get_connection(ssl_conn);
1954 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1955 "ssl get session: %08XD:%d", hash, len);
1956 #endif
1958 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
1959 ngx_ssl_session_cache_index);
1961 cache = shm_zone->data;
1963 sess = NULL;
1965 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1967 ngx_shmtx_lock(&shpool->mutex);
1969 node = cache->session_rbtree.root;
1970 sentinel = cache->session_rbtree.sentinel;
1972 while (node != sentinel) {
1974 if (hash < node->key) {
1975 node = node->left;
1976 continue;
1979 if (hash > node->key) {
1980 node = node->right;
1981 continue;
1984 /* hash == node->key */
1986 sess_id = (ngx_ssl_sess_id_t *) node;
1988 rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data);
1990 if (rc == 0) {
1992 if (sess_id->expire > ngx_time()) {
1993 ngx_memcpy(buf, sess_id->session, sess_id->len);
1995 ngx_shmtx_unlock(&shpool->mutex);
1997 p = buf;
1998 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
2000 return sess;
2003 ngx_queue_remove(&sess_id->queue);
2005 ngx_rbtree_delete(&cache->session_rbtree, node);
2007 ngx_slab_free_locked(shpool, sess_id->session);
2008 #if (NGX_PTR_SIZE == 4)
2009 ngx_slab_free_locked(shpool, sess_id->id);
2010 #endif
2011 ngx_slab_free_locked(shpool, sess_id);
2013 sess = NULL;
2015 goto done;
2018 node = (rc < 0) ? node->left : node->right;
2021 done:
2023 ngx_shmtx_unlock(&shpool->mutex);
2025 return sess;
2029 void
2030 ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
2032 SSL_CTX_remove_session(ssl, sess);
2034 ngx_ssl_remove_session(ssl, sess);
2038 static void
2039 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
2041 size_t len;
2042 u_char *id;
2043 uint32_t hash;
2044 ngx_int_t rc;
2045 ngx_shm_zone_t *shm_zone;
2046 ngx_slab_pool_t *shpool;
2047 ngx_rbtree_node_t *node, *sentinel;
2048 ngx_ssl_sess_id_t *sess_id;
2049 ngx_ssl_session_cache_t *cache;
2051 shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
2053 if (shm_zone == NULL) {
2054 return;
2057 cache = shm_zone->data;
2059 id = sess->session_id;
2060 len = (size_t) sess->session_id_length;
2062 hash = ngx_crc32_short(id, len);
2064 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
2065 "ssl remove session: %08XD:%uz", hash, len);
2067 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2069 ngx_shmtx_lock(&shpool->mutex);
2071 node = cache->session_rbtree.root;
2072 sentinel = cache->session_rbtree.sentinel;
2074 while (node != sentinel) {
2076 if (hash < node->key) {
2077 node = node->left;
2078 continue;
2081 if (hash > node->key) {
2082 node = node->right;
2083 continue;
2086 /* hash == node->key */
2088 sess_id = (ngx_ssl_sess_id_t *) node;
2090 rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
2092 if (rc == 0) {
2094 ngx_queue_remove(&sess_id->queue);
2096 ngx_rbtree_delete(&cache->session_rbtree, node);
2098 ngx_slab_free_locked(shpool, sess_id->session);
2099 #if (NGX_PTR_SIZE == 4)
2100 ngx_slab_free_locked(shpool, sess_id->id);
2101 #endif
2102 ngx_slab_free_locked(shpool, sess_id);
2104 goto done;
2107 node = (rc < 0) ? node->left : node->right;
2110 done:
2112 ngx_shmtx_unlock(&shpool->mutex);
2116 static void
2117 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
2118 ngx_slab_pool_t *shpool, ngx_uint_t n)
2120 time_t now;
2121 ngx_queue_t *q;
2122 ngx_ssl_sess_id_t *sess_id;
2124 now = ngx_time();
2126 while (n < 3) {
2128 if (ngx_queue_empty(&cache->expire_queue)) {
2129 return;
2132 q = ngx_queue_last(&cache->expire_queue);
2134 sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
2136 if (n++ != 0 && sess_id->expire > now) {
2137 return;
2140 ngx_queue_remove(q);
2142 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
2143 "expire session: %08Xi", sess_id->node.key);
2145 ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
2147 ngx_slab_free_locked(shpool, sess_id->session);
2148 #if (NGX_PTR_SIZE == 4)
2149 ngx_slab_free_locked(shpool, sess_id->id);
2150 #endif
2151 ngx_slab_free_locked(shpool, sess_id);
2156 static void
2157 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
2158 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
2160 ngx_rbtree_node_t **p;
2161 ngx_ssl_sess_id_t *sess_id, *sess_id_temp;
2163 for ( ;; ) {
2165 if (node->key < temp->key) {
2167 p = &temp->left;
2169 } else if (node->key > temp->key) {
2171 p = &temp->right;
2173 } else { /* node->key == temp->key */
2175 sess_id = (ngx_ssl_sess_id_t *) node;
2176 sess_id_temp = (ngx_ssl_sess_id_t *) temp;
2178 p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
2179 (size_t) node->data, (size_t) temp->data)
2180 < 0) ? &temp->left : &temp->right;
2183 if (*p == sentinel) {
2184 break;
2187 temp = *p;
2190 *p = node;
2191 node->parent = temp;
2192 node->left = sentinel;
2193 node->right = sentinel;
2194 ngx_rbt_red(node);
2198 void
2199 ngx_ssl_cleanup_ctx(void *data)
2201 ngx_ssl_t *ssl = data;
2203 SSL_CTX_free(ssl->ctx);
2207 ngx_int_t
2208 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2210 s->data = (u_char *) SSL_get_version(c->ssl->connection);
2211 return NGX_OK;
2215 ngx_int_t
2216 ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2218 s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
2219 return NGX_OK;
2223 ngx_int_t
2224 ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2226 int len;
2227 u_char *p, *buf;
2228 SSL_SESSION *sess;
2230 sess = SSL_get0_session(c->ssl->connection);
2232 len = i2d_SSL_SESSION(sess, NULL);
2234 buf = ngx_alloc(len, c->log);
2235 if (buf == NULL) {
2236 return NGX_ERROR;
2239 s->len = 2 * len;
2240 s->data = ngx_pnalloc(pool, 2 * len);
2241 if (s->data == NULL) {
2242 ngx_free(buf);
2243 return NGX_ERROR;
2246 p = buf;
2247 i2d_SSL_SESSION(sess, &p);
2249 ngx_hex_dump(s->data, buf, len);
2251 ngx_free(buf);
2253 return NGX_OK;
2257 ngx_int_t
2258 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2260 size_t len;
2261 BIO *bio;
2262 X509 *cert;
2264 s->len = 0;
2266 cert = SSL_get_peer_certificate(c->ssl->connection);
2267 if (cert == NULL) {
2268 return NGX_OK;
2271 bio = BIO_new(BIO_s_mem());
2272 if (bio == NULL) {
2273 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
2274 X509_free(cert);
2275 return NGX_ERROR;
2278 if (PEM_write_bio_X509(bio, cert) == 0) {
2279 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
2280 goto failed;
2283 len = BIO_pending(bio);
2284 s->len = len;
2286 s->data = ngx_pnalloc(pool, len);
2287 if (s->data == NULL) {
2288 goto failed;
2291 BIO_read(bio, s->data, len);
2293 BIO_free(bio);
2294 X509_free(cert);
2296 return NGX_OK;
2298 failed:
2300 BIO_free(bio);
2301 X509_free(cert);
2303 return NGX_ERROR;
2307 ngx_int_t
2308 ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2310 u_char *p;
2311 size_t len;
2312 ngx_uint_t i;
2313 ngx_str_t cert;
2315 if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
2316 return NGX_ERROR;
2319 if (cert.len == 0) {
2320 s->len = 0;
2321 return NGX_OK;
2324 len = cert.len - 1;
2326 for (i = 0; i < cert.len - 1; i++) {
2327 if (cert.data[i] == LF) {
2328 len++;
2332 s->len = len;
2333 s->data = ngx_pnalloc(pool, len);
2334 if (s->data == NULL) {
2335 return NGX_ERROR;
2338 p = s->data;
2340 for (i = 0; i < cert.len - 1; i++) {
2341 *p++ = cert.data[i];
2342 if (cert.data[i] == LF) {
2343 *p++ = '\t';
2347 return NGX_OK;
2351 ngx_int_t
2352 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2354 char *p;
2355 size_t len;
2356 X509 *cert;
2357 X509_NAME *name;
2359 s->len = 0;
2361 cert = SSL_get_peer_certificate(c->ssl->connection);
2362 if (cert == NULL) {
2363 return NGX_OK;
2366 name = X509_get_subject_name(cert);
2367 if (name == NULL) {
2368 X509_free(cert);
2369 return NGX_ERROR;
2372 p = X509_NAME_oneline(name, NULL, 0);
2374 for (len = 0; p[len]; len++) { /* void */ }
2376 s->len = len;
2377 s->data = ngx_pnalloc(pool, len);
2378 if (s->data == NULL) {
2379 OPENSSL_free(p);
2380 X509_free(cert);
2381 return NGX_ERROR;
2384 ngx_memcpy(s->data, p, len);
2386 OPENSSL_free(p);
2387 X509_free(cert);
2389 return NGX_OK;
2393 ngx_int_t
2394 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2396 char *p;
2397 size_t len;
2398 X509 *cert;
2399 X509_NAME *name;
2401 s->len = 0;
2403 cert = SSL_get_peer_certificate(c->ssl->connection);
2404 if (cert == NULL) {
2405 return NGX_OK;
2408 name = X509_get_issuer_name(cert);
2409 if (name == NULL) {
2410 X509_free(cert);
2411 return NGX_ERROR;
2414 p = X509_NAME_oneline(name, NULL, 0);
2416 for (len = 0; p[len]; len++) { /* void */ }
2418 s->len = len;
2419 s->data = ngx_pnalloc(pool, len);
2420 if (s->data == NULL) {
2421 OPENSSL_free(p);
2422 X509_free(cert);
2423 return NGX_ERROR;
2426 ngx_memcpy(s->data, p, len);
2428 OPENSSL_free(p);
2429 X509_free(cert);
2431 return NGX_OK;
2435 ngx_int_t
2436 ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2438 size_t len;
2439 X509 *cert;
2440 BIO *bio;
2442 s->len = 0;
2444 cert = SSL_get_peer_certificate(c->ssl->connection);
2445 if (cert == NULL) {
2446 return NGX_OK;
2449 bio = BIO_new(BIO_s_mem());
2450 if (bio == NULL) {
2451 X509_free(cert);
2452 return NGX_ERROR;
2455 i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
2456 len = BIO_pending(bio);
2458 s->len = len;
2459 s->data = ngx_pnalloc(pool, len);
2460 if (s->data == NULL) {
2461 BIO_free(bio);
2462 X509_free(cert);
2463 return NGX_ERROR;
2466 BIO_read(bio, s->data, len);
2467 BIO_free(bio);
2468 X509_free(cert);
2470 return NGX_OK;
2474 ngx_int_t
2475 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2477 X509 *cert;
2479 if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
2480 ngx_str_set(s, "FAILED");
2481 return NGX_OK;
2484 cert = SSL_get_peer_certificate(c->ssl->connection);
2486 if (cert) {
2487 ngx_str_set(s, "SUCCESS");
2489 } else {
2490 ngx_str_set(s, "NONE");
2493 X509_free(cert);
2495 return NGX_OK;
2499 static void *
2500 ngx_openssl_create_conf(ngx_cycle_t *cycle)
2502 ngx_openssl_conf_t *oscf;
2504 oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
2505 if (oscf == NULL) {
2506 return NULL;
2510 * set by ngx_pcalloc():
2512 * oscf->engine = 0;
2515 return oscf;
2519 static char *
2520 ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2522 ngx_openssl_conf_t *oscf = conf;
2524 ENGINE *engine;
2525 ngx_str_t *value;
2527 if (oscf->engine) {
2528 return "is duplicate";
2531 oscf->engine = 1;
2533 value = cf->args->elts;
2535 engine = ENGINE_by_id((const char *) value[1].data);
2537 if (engine == NULL) {
2538 ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2539 "ENGINE_by_id(\"%V\") failed", &value[1]);
2540 return NGX_CONF_ERROR;
2543 if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
2544 ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2545 "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
2546 &value[1]);
2548 ENGINE_free(engine);
2550 return NGX_CONF_ERROR;
2553 ENGINE_free(engine);
2555 return NGX_CONF_OK;
2559 static void
2560 ngx_openssl_exit(ngx_cycle_t *cycle)
2562 EVP_cleanup();
2563 ENGINE_cleanup();