Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 #define NGX_SSL_PASSWORD_BUFFER_SIZE  4096
0014 
0015 
0016 typedef struct {
0017     ngx_uint_t  engine;   /* unsigned  engine:1; */
0018 } ngx_openssl_conf_t;
0019 
0020 
0021 static X509 *ngx_ssl_load_certificate(ngx_pool_t *pool, char **err,
0022     ngx_str_t *cert, STACK_OF(X509) **chain);
0023 static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
0024     ngx_str_t *key, ngx_array_t *passwords);
0025 static int ngx_ssl_password_callback(char *buf, int size, int rwflag,
0026     void *userdata);
0027 static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
0028 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
0029     int ret);
0030 static void ngx_ssl_passwords_cleanup(void *data);
0031 static int ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn,
0032     ngx_ssl_session_t *sess);
0033 #ifdef SSL_READ_EARLY_DATA_SUCCESS
0034 static ngx_int_t ngx_ssl_try_early_data(ngx_connection_t *c);
0035 #endif
0036 #if (NGX_DEBUG)
0037 static void ngx_ssl_handshake_log(ngx_connection_t *c);
0038 #endif
0039 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
0040 #ifdef SSL_READ_EARLY_DATA_SUCCESS
0041 static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf,
0042     size_t size);
0043 #endif
0044 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
0045 static void ngx_ssl_write_handler(ngx_event_t *wev);
0046 #ifdef SSL_READ_EARLY_DATA_SUCCESS
0047 static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data,
0048     size_t size);
0049 #endif
0050 static void ngx_ssl_read_handler(ngx_event_t *rev);
0051 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
0052 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
0053     ngx_err_t err, char *text);
0054 static void ngx_ssl_clear_error(ngx_log_t *log);
0055 
0056 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
0057     ngx_str_t *sess_ctx, ngx_array_t *certificates);
0058 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
0059     ngx_ssl_session_t *sess);
0060 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
0061 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
0062     const
0063 #endif
0064     u_char *id, int len, int *copy);
0065 static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
0066 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
0067     ngx_slab_pool_t *shpool, ngx_uint_t n);
0068 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
0069     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
0070 
0071 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
0072 static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
0073     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
0074     HMAC_CTX *hctx, int enc);
0075 static void ngx_ssl_session_ticket_keys_cleanup(void *data);
0076 #endif
0077 
0078 #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
0079 static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str);
0080 #endif
0081 
0082 static time_t ngx_ssl_parse_time(
0083 #if OPENSSL_VERSION_NUMBER > 0x10100000L
0084     const
0085 #endif
0086     ASN1_TIME *asn1time);
0087 
0088 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
0089 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0090 static void ngx_openssl_exit(ngx_cycle_t *cycle);
0091 
0092 
0093 static ngx_command_t  ngx_openssl_commands[] = {
0094 
0095     { ngx_string("ssl_engine"),
0096       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0097       ngx_openssl_engine,
0098       0,
0099       0,
0100       NULL },
0101 
0102       ngx_null_command
0103 };
0104 
0105 
0106 static ngx_core_module_t  ngx_openssl_module_ctx = {
0107     ngx_string("openssl"),
0108     ngx_openssl_create_conf,
0109     NULL
0110 };
0111 
0112 
0113 ngx_module_t  ngx_openssl_module = {
0114     NGX_MODULE_V1,
0115     &ngx_openssl_module_ctx,               /* module context */
0116     ngx_openssl_commands,                  /* module directives */
0117     NGX_CORE_MODULE,                       /* module type */
0118     NULL,                                  /* init master */
0119     NULL,                                  /* init module */
0120     NULL,                                  /* init process */
0121     NULL,                                  /* init thread */
0122     NULL,                                  /* exit thread */
0123     NULL,                                  /* exit process */
0124     ngx_openssl_exit,                      /* exit master */
0125     NGX_MODULE_V1_PADDING
0126 };
0127 
0128 
0129 int  ngx_ssl_connection_index;
0130 int  ngx_ssl_server_conf_index;
0131 int  ngx_ssl_session_cache_index;
0132 int  ngx_ssl_session_ticket_keys_index;
0133 int  ngx_ssl_certificate_index;
0134 int  ngx_ssl_next_certificate_index;
0135 int  ngx_ssl_certificate_name_index;
0136 int  ngx_ssl_stapling_index;
0137 
0138 
0139 ngx_int_t
0140 ngx_ssl_init(ngx_log_t *log)
0141 {
0142 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
0143 
0144     if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) == 0) {
0145         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "OPENSSL_init_ssl() failed");
0146         return NGX_ERROR;
0147     }
0148 
0149     /*
0150      * OPENSSL_init_ssl() may leave errors in the error queue
0151      * while returning success
0152      */
0153 
0154     ERR_clear_error();
0155 
0156 #else
0157 
0158     OPENSSL_config(NULL);
0159 
0160     SSL_library_init();
0161     SSL_load_error_strings();
0162 
0163     OpenSSL_add_all_algorithms();
0164 
0165 #endif
0166 
0167 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
0168 #ifndef SSL_OP_NO_COMPRESSION
0169     {
0170     /*
0171      * Disable gzip compression in OpenSSL prior to 1.0.0 version,
0172      * this saves about 522K per connection.
0173      */
0174     int                  n;
0175     STACK_OF(SSL_COMP)  *ssl_comp_methods;
0176 
0177     ssl_comp_methods = SSL_COMP_get_compression_methods();
0178     n = sk_SSL_COMP_num(ssl_comp_methods);
0179 
0180     while (n--) {
0181         (void) sk_SSL_COMP_pop(ssl_comp_methods);
0182     }
0183     }
0184 #endif
0185 #endif
0186 
0187     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
0188 
0189     if (ngx_ssl_connection_index == -1) {
0190         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
0191         return NGX_ERROR;
0192     }
0193 
0194     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
0195                                                          NULL);
0196     if (ngx_ssl_server_conf_index == -1) {
0197         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0198                       "SSL_CTX_get_ex_new_index() failed");
0199         return NGX_ERROR;
0200     }
0201 
0202     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
0203                                                            NULL);
0204     if (ngx_ssl_session_cache_index == -1) {
0205         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0206                       "SSL_CTX_get_ex_new_index() failed");
0207         return NGX_ERROR;
0208     }
0209 
0210     ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
0211                                                                  NULL, NULL);
0212     if (ngx_ssl_session_ticket_keys_index == -1) {
0213         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0214                       "SSL_CTX_get_ex_new_index() failed");
0215         return NGX_ERROR;
0216     }
0217 
0218     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
0219                                                          NULL);
0220     if (ngx_ssl_certificate_index == -1) {
0221         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0222                       "SSL_CTX_get_ex_new_index() failed");
0223         return NGX_ERROR;
0224     }
0225 
0226     ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
0227                                                            NULL);
0228     if (ngx_ssl_next_certificate_index == -1) {
0229         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
0230         return NGX_ERROR;
0231     }
0232 
0233     ngx_ssl_certificate_name_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
0234                                                            NULL);
0235 
0236     if (ngx_ssl_certificate_name_index == -1) {
0237         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
0238         return NGX_ERROR;
0239     }
0240 
0241     ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL);
0242 
0243     if (ngx_ssl_stapling_index == -1) {
0244         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
0245         return NGX_ERROR;
0246     }
0247 
0248     return NGX_OK;
0249 }
0250 
0251 
0252 ngx_int_t
0253 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
0254 {
0255     ssl->ctx = SSL_CTX_new(SSLv23_method());
0256 
0257     if (ssl->ctx == NULL) {
0258         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
0259         return NGX_ERROR;
0260     }
0261 
0262     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
0263         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0264                       "SSL_CTX_set_ex_data() failed");
0265         return NGX_ERROR;
0266     }
0267 
0268     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) {
0269         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0270                       "SSL_CTX_set_ex_data() failed");
0271         return NGX_ERROR;
0272     }
0273 
0274     ssl->buffer_size = NGX_SSL_BUFSIZE;
0275 
0276     /* client side options */
0277 
0278 #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
0279     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
0280 #endif
0281 
0282 #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
0283     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
0284 #endif
0285 
0286     /* server side options */
0287 
0288 #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
0289     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
0290 #endif
0291 
0292 #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
0293     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
0294 #endif
0295 
0296 #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
0297     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
0298     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
0299 #endif
0300 
0301 #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
0302     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
0303 #endif
0304 
0305 #ifdef SSL_OP_TLS_D5_BUG
0306     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
0307 #endif
0308 
0309 #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
0310     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
0311 #endif
0312 
0313 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
0314     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
0315 #endif
0316 
0317     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
0318 
0319 #if OPENSSL_VERSION_NUMBER >= 0x009080dfL
0320     /* only in 0.9.8m+ */
0321     SSL_CTX_clear_options(ssl->ctx,
0322                           SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1);
0323 #endif
0324 
0325     if (!(protocols & NGX_SSL_SSLv2)) {
0326         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
0327     }
0328     if (!(protocols & NGX_SSL_SSLv3)) {
0329         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
0330     }
0331     if (!(protocols & NGX_SSL_TLSv1)) {
0332         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
0333     }
0334 #ifdef SSL_OP_NO_TLSv1_1
0335     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
0336     if (!(protocols & NGX_SSL_TLSv1_1)) {
0337         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
0338     }
0339 #endif
0340 #ifdef SSL_OP_NO_TLSv1_2
0341     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
0342     if (!(protocols & NGX_SSL_TLSv1_2)) {
0343         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
0344     }
0345 #endif
0346 #ifdef SSL_OP_NO_TLSv1_3
0347     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_3);
0348     if (!(protocols & NGX_SSL_TLSv1_3)) {
0349         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_3);
0350     }
0351 #endif
0352 
0353 #ifdef SSL_CTX_set_min_proto_version
0354     SSL_CTX_set_min_proto_version(ssl->ctx, 0);
0355     SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_2_VERSION);
0356 #endif
0357 
0358 #ifdef TLS1_3_VERSION
0359     SSL_CTX_set_min_proto_version(ssl->ctx, 0);
0360     SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_3_VERSION);
0361 #endif
0362 
0363 #ifdef SSL_OP_NO_COMPRESSION
0364     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
0365 #endif
0366 
0367 #ifdef SSL_OP_NO_ANTI_REPLAY
0368     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY);
0369 #endif
0370 
0371 #ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
0372     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
0373 #endif
0374 
0375 #ifdef SSL_MODE_RELEASE_BUFFERS
0376     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
0377 #endif
0378 
0379 #ifdef SSL_MODE_NO_AUTO_CHAIN
0380     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_NO_AUTO_CHAIN);
0381 #endif
0382 
0383     SSL_CTX_set_read_ahead(ssl->ctx, 1);
0384 
0385     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
0386 
0387     return NGX_OK;
0388 }
0389 
0390 
0391 ngx_int_t
0392 ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
0393     ngx_array_t *keys, ngx_array_t *passwords)
0394 {
0395     ngx_str_t   *cert, *key;
0396     ngx_uint_t   i;
0397 
0398     cert = certs->elts;
0399     key = keys->elts;
0400 
0401     for (i = 0; i < certs->nelts; i++) {
0402 
0403         if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords)
0404             != NGX_OK)
0405         {
0406             return NGX_ERROR;
0407         }
0408     }
0409 
0410     return NGX_OK;
0411 }
0412 
0413 
0414 ngx_int_t
0415 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
0416     ngx_str_t *key, ngx_array_t *passwords)
0417 {
0418     char            *err;
0419     X509            *x509;
0420     EVP_PKEY        *pkey;
0421     STACK_OF(X509)  *chain;
0422 
0423     x509 = ngx_ssl_load_certificate(cf->pool, &err, cert, &chain);
0424     if (x509 == NULL) {
0425         if (err != NULL) {
0426             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0427                           "cannot load certificate \"%s\": %s",
0428                           cert->data, err);
0429         }
0430 
0431         return NGX_ERROR;
0432     }
0433 
0434     if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
0435         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0436                       "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
0437         X509_free(x509);
0438         sk_X509_pop_free(chain, X509_free);
0439         return NGX_ERROR;
0440     }
0441 
0442     if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data)
0443         == 0)
0444     {
0445         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
0446         X509_free(x509);
0447         sk_X509_pop_free(chain, X509_free);
0448         return NGX_ERROR;
0449     }
0450 
0451     if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index,
0452                       SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index))
0453         == 0)
0454     {
0455         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
0456         X509_free(x509);
0457         sk_X509_pop_free(chain, X509_free);
0458         return NGX_ERROR;
0459     }
0460 
0461     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) {
0462         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0463                       "SSL_CTX_set_ex_data() failed");
0464         X509_free(x509);
0465         sk_X509_pop_free(chain, X509_free);
0466         return NGX_ERROR;
0467     }
0468 
0469     /*
0470      * Note that x509 is not freed here, but will be instead freed in
0471      * ngx_ssl_cleanup_ctx().  This is because we need to preserve all
0472      * certificates to be able to iterate all of them through exdata
0473      * (ngx_ssl_certificate_index, ngx_ssl_next_certificate_index),
0474      * while OpenSSL can free a certificate if it is replaced with another
0475      * certificate of the same type.
0476      */
0477 
0478 #ifdef SSL_CTX_set0_chain
0479 
0480     if (SSL_CTX_set0_chain(ssl->ctx, chain) == 0) {
0481         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0482                       "SSL_CTX_set0_chain(\"%s\") failed", cert->data);
0483         sk_X509_pop_free(chain, X509_free);
0484         return NGX_ERROR;
0485     }
0486 
0487 #else
0488     {
0489     int  n;
0490 
0491     /* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */
0492 
0493     n = sk_X509_num(chain);
0494 
0495     while (n--) {
0496         x509 = sk_X509_shift(chain);
0497 
0498         if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
0499             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0500                           "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
0501                           cert->data);
0502             sk_X509_pop_free(chain, X509_free);
0503             return NGX_ERROR;
0504         }
0505     }
0506 
0507     sk_X509_free(chain);
0508     }
0509 #endif
0510 
0511     pkey = ngx_ssl_load_certificate_key(cf->pool, &err, key, passwords);
0512     if (pkey == NULL) {
0513         if (err != NULL) {
0514             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0515                           "cannot load certificate key \"%s\": %s",
0516                           key->data, err);
0517         }
0518 
0519         return NGX_ERROR;
0520     }
0521 
0522     if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
0523         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0524                       "SSL_CTX_use_PrivateKey(\"%s\") failed", key->data);
0525         EVP_PKEY_free(pkey);
0526         return NGX_ERROR;
0527     }
0528 
0529     EVP_PKEY_free(pkey);
0530 
0531     return NGX_OK;
0532 }
0533 
0534 
0535 ngx_int_t
0536 ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
0537     ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords)
0538 {
0539     char            *err;
0540     X509            *x509;
0541     EVP_PKEY        *pkey;
0542     STACK_OF(X509)  *chain;
0543 
0544     x509 = ngx_ssl_load_certificate(pool, &err, cert, &chain);
0545     if (x509 == NULL) {
0546         if (err != NULL) {
0547             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0548                           "cannot load certificate \"%s\": %s",
0549                           cert->data, err);
0550         }
0551 
0552         return NGX_ERROR;
0553     }
0554 
0555     if (SSL_use_certificate(c->ssl->connection, x509) == 0) {
0556         ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0557                       "SSL_use_certificate(\"%s\") failed", cert->data);
0558         X509_free(x509);
0559         sk_X509_pop_free(chain, X509_free);
0560         return NGX_ERROR;
0561     }
0562 
0563     X509_free(x509);
0564 
0565 #ifdef SSL_set0_chain
0566 
0567     /*
0568      * SSL_set0_chain() is only available in OpenSSL 1.0.2+,
0569      * but this function is only called via certificate callback,
0570      * which is only available in OpenSSL 1.0.2+ as well
0571      */
0572 
0573     if (SSL_set0_chain(c->ssl->connection, chain) == 0) {
0574         ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0575                       "SSL_set0_chain(\"%s\") failed", cert->data);
0576         sk_X509_pop_free(chain, X509_free);
0577         return NGX_ERROR;
0578     }
0579 
0580 #endif
0581 
0582     pkey = ngx_ssl_load_certificate_key(pool, &err, key, passwords);
0583     if (pkey == NULL) {
0584         if (err != NULL) {
0585             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0586                           "cannot load certificate key \"%s\": %s",
0587                           key->data, err);
0588         }
0589 
0590         return NGX_ERROR;
0591     }
0592 
0593     if (SSL_use_PrivateKey(c->ssl->connection, pkey) == 0) {
0594         ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0595                       "SSL_use_PrivateKey(\"%s\") failed", key->data);
0596         EVP_PKEY_free(pkey);
0597         return NGX_ERROR;
0598     }
0599 
0600     EVP_PKEY_free(pkey);
0601 
0602     return NGX_OK;
0603 }
0604 
0605 
0606 static X509 *
0607 ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert,
0608     STACK_OF(X509) **chain)
0609 {
0610     BIO     *bio;
0611     X509    *x509, *temp;
0612     u_long   n;
0613 
0614     if (ngx_strncmp(cert->data, "data:", sizeof("data:") - 1) == 0) {
0615 
0616         bio = BIO_new_mem_buf(cert->data + sizeof("data:") - 1,
0617                               cert->len - (sizeof("data:") - 1));
0618         if (bio == NULL) {
0619             *err = "BIO_new_mem_buf() failed";
0620             return NULL;
0621         }
0622 
0623     } else {
0624 
0625         if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, cert)
0626             != NGX_OK)
0627         {
0628             *err = NULL;
0629             return NULL;
0630         }
0631 
0632         bio = BIO_new_file((char *) cert->data, "r");
0633         if (bio == NULL) {
0634             *err = "BIO_new_file() failed";
0635             return NULL;
0636         }
0637     }
0638 
0639     /* certificate itself */
0640 
0641     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
0642     if (x509 == NULL) {
0643         *err = "PEM_read_bio_X509_AUX() failed";
0644         BIO_free(bio);
0645         return NULL;
0646     }
0647 
0648     /* rest of the chain */
0649 
0650     *chain = sk_X509_new_null();
0651     if (*chain == NULL) {
0652         *err = "sk_X509_new_null() failed";
0653         BIO_free(bio);
0654         X509_free(x509);
0655         return NULL;
0656     }
0657 
0658     for ( ;; ) {
0659 
0660         temp = PEM_read_bio_X509(bio, NULL, NULL, NULL);
0661         if (temp == NULL) {
0662             n = ERR_peek_last_error();
0663 
0664             if (ERR_GET_LIB(n) == ERR_LIB_PEM
0665                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
0666             {
0667                 /* end of file */
0668                 ERR_clear_error();
0669                 break;
0670             }
0671 
0672             /* some real error */
0673 
0674             *err = "PEM_read_bio_X509() failed";
0675             BIO_free(bio);
0676             X509_free(x509);
0677             sk_X509_pop_free(*chain, X509_free);
0678             return NULL;
0679         }
0680 
0681         if (sk_X509_push(*chain, temp) == 0) {
0682             *err = "sk_X509_push() failed";
0683             BIO_free(bio);
0684             X509_free(x509);
0685             sk_X509_pop_free(*chain, X509_free);
0686             return NULL;
0687         }
0688     }
0689 
0690     BIO_free(bio);
0691 
0692     return x509;
0693 }
0694 
0695 
0696 static EVP_PKEY *
0697 ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
0698     ngx_str_t *key, ngx_array_t *passwords)
0699 {
0700     BIO              *bio;
0701     EVP_PKEY         *pkey;
0702     ngx_str_t        *pwd;
0703     ngx_uint_t        tries;
0704     pem_password_cb  *cb;
0705 
0706     if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) {
0707 
0708 #ifndef OPENSSL_NO_ENGINE
0709 
0710         u_char  *p, *last;
0711         ENGINE  *engine;
0712 
0713         p = key->data + sizeof("engine:") - 1;
0714         last = (u_char *) ngx_strchr(p, ':');
0715 
0716         if (last == NULL) {
0717             *err = "invalid syntax";
0718             return NULL;
0719         }
0720 
0721         *last = '\0';
0722 
0723         engine = ENGINE_by_id((char *) p);
0724 
0725         if (engine == NULL) {
0726             *err = "ENGINE_by_id() failed";
0727             return NULL;
0728         }
0729 
0730         *last++ = ':';
0731 
0732         pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);
0733 
0734         if (pkey == NULL) {
0735             *err = "ENGINE_load_private_key() failed";
0736             ENGINE_free(engine);
0737             return NULL;
0738         }
0739 
0740         ENGINE_free(engine);
0741 
0742         return pkey;
0743 
0744 #else
0745 
0746         *err = "loading \"engine:...\" certificate keys is not supported";
0747         return NULL;
0748 
0749 #endif
0750     }
0751 
0752     if (ngx_strncmp(key->data, "data:", sizeof("data:") - 1) == 0) {
0753 
0754         bio = BIO_new_mem_buf(key->data + sizeof("data:") - 1,
0755                               key->len - (sizeof("data:") - 1));
0756         if (bio == NULL) {
0757             *err = "BIO_new_mem_buf() failed";
0758             return NULL;
0759         }
0760 
0761     } else {
0762 
0763         if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, key)
0764             != NGX_OK)
0765         {
0766             *err = NULL;
0767             return NULL;
0768         }
0769 
0770         bio = BIO_new_file((char *) key->data, "r");
0771         if (bio == NULL) {
0772             *err = "BIO_new_file() failed";
0773             return NULL;
0774         }
0775     }
0776 
0777     if (passwords) {
0778         tries = passwords->nelts;
0779         pwd = passwords->elts;
0780         cb = ngx_ssl_password_callback;
0781 
0782     } else {
0783         tries = 1;
0784         pwd = NULL;
0785         cb = NULL;
0786     }
0787 
0788     for ( ;; ) {
0789 
0790         pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
0791         if (pkey != NULL) {
0792             break;
0793         }
0794 
0795         if (tries-- > 1) {
0796             ERR_clear_error();
0797             (void) BIO_reset(bio);
0798             pwd++;
0799             continue;
0800         }
0801 
0802         *err = "PEM_read_bio_PrivateKey() failed";
0803         BIO_free(bio);
0804         return NULL;
0805     }
0806 
0807     BIO_free(bio);
0808 
0809     return pkey;
0810 }
0811 
0812 
0813 static int
0814 ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
0815 {
0816     ngx_str_t *pwd = userdata;
0817 
0818     if (rwflag) {
0819         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
0820                       "ngx_ssl_password_callback() is called for encryption");
0821         return 0;
0822     }
0823 
0824     if (pwd == NULL) {
0825         return 0;
0826     }
0827 
0828     if (pwd->len > (size_t) size) {
0829         ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
0830                       "password is truncated to %d bytes", size);
0831     } else {
0832         size = pwd->len;
0833     }
0834 
0835     ngx_memcpy(buf, pwd->data, size);
0836 
0837     return size;
0838 }
0839 
0840 
0841 ngx_int_t
0842 ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
0843     ngx_uint_t prefer_server_ciphers)
0844 {
0845     if (SSL_CTX_set_cipher_list(ssl->ctx, (char *) ciphers->data) == 0) {
0846         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0847                       "SSL_CTX_set_cipher_list(\"%V\") failed",
0848                       ciphers);
0849         return NGX_ERROR;
0850     }
0851 
0852     if (prefer_server_ciphers) {
0853         SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
0854     }
0855 
0856 #if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
0857     /* a temporary 512-bit RSA key is required for export versions of MSIE */
0858     SSL_CTX_set_tmp_rsa_callback(ssl->ctx, ngx_ssl_rsa512_key_callback);
0859 #endif
0860 
0861     return NGX_OK;
0862 }
0863 
0864 
0865 ngx_int_t
0866 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
0867     ngx_int_t depth)
0868 {
0869     STACK_OF(X509_NAME)  *list;
0870 
0871     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_ssl_verify_callback);
0872 
0873     SSL_CTX_set_verify_depth(ssl->ctx, depth);
0874 
0875     if (cert->len == 0) {
0876         return NGX_OK;
0877     }
0878 
0879     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
0880         return NGX_ERROR;
0881     }
0882 
0883     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
0884         == 0)
0885     {
0886         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0887                       "SSL_CTX_load_verify_locations(\"%s\") failed",
0888                       cert->data);
0889         return NGX_ERROR;
0890     }
0891 
0892     /*
0893      * SSL_CTX_load_verify_locations() may leave errors in the error queue
0894      * while returning success
0895      */
0896 
0897     ERR_clear_error();
0898 
0899     list = SSL_load_client_CA_file((char *) cert->data);
0900 
0901     if (list == NULL) {
0902         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0903                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
0904         return NGX_ERROR;
0905     }
0906 
0907     /*
0908      * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
0909      * always leaved an error in the error queue
0910      */
0911 
0912     ERR_clear_error();
0913 
0914     SSL_CTX_set_client_CA_list(ssl->ctx, list);
0915 
0916     return NGX_OK;
0917 }
0918 
0919 
0920 ngx_int_t
0921 ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
0922     ngx_int_t depth)
0923 {
0924     SSL_CTX_set_verify_depth(ssl->ctx, depth);
0925 
0926     if (cert->len == 0) {
0927         return NGX_OK;
0928     }
0929 
0930     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
0931         return NGX_ERROR;
0932     }
0933 
0934     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
0935         == 0)
0936     {
0937         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0938                       "SSL_CTX_load_verify_locations(\"%s\") failed",
0939                       cert->data);
0940         return NGX_ERROR;
0941     }
0942 
0943     /*
0944      * SSL_CTX_load_verify_locations() may leave errors in the error queue
0945      * while returning success
0946      */
0947 
0948     ERR_clear_error();
0949 
0950     return NGX_OK;
0951 }
0952 
0953 
0954 ngx_int_t
0955 ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
0956 {
0957     X509_STORE   *store;
0958     X509_LOOKUP  *lookup;
0959 
0960     if (crl->len == 0) {
0961         return NGX_OK;
0962     }
0963 
0964     if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
0965         return NGX_ERROR;
0966     }
0967 
0968     store = SSL_CTX_get_cert_store(ssl->ctx);
0969 
0970     if (store == NULL) {
0971         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0972                       "SSL_CTX_get_cert_store() failed");
0973         return NGX_ERROR;
0974     }
0975 
0976     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
0977 
0978     if (lookup == NULL) {
0979         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0980                       "X509_STORE_add_lookup() failed");
0981         return NGX_ERROR;
0982     }
0983 
0984     if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
0985         == 0)
0986     {
0987         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0988                       "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
0989         return NGX_ERROR;
0990     }
0991 
0992     X509_STORE_set_flags(store,
0993                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
0994 
0995     return NGX_OK;
0996 }
0997 
0998 
0999 static int
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
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 *
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 *
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 *
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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 }