Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

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 int ngx_ssl_password_callback(char *buf, int size, int rwflag,
0022     void *userdata);
0023 static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
0024 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
0025     int ret);
0026 static void ngx_ssl_passwords_cleanup(void *data);
0027 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
0028 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
0029 static void ngx_ssl_write_handler(ngx_event_t *wev);
0030 static void ngx_ssl_read_handler(ngx_event_t *rev);
0031 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
0032 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
0033     ngx_err_t err, char *text);
0034 static void ngx_ssl_clear_error(ngx_log_t *log);
0035 
0036 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
0037     ngx_str_t *sess_ctx);
0038 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
0039 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
0040     ngx_ssl_session_t *sess);
0041 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
0042 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
0043     const
0044 #endif
0045     u_char *id, int len, int *copy);
0046 static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
0047 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
0048     ngx_slab_pool_t *shpool, ngx_uint_t n);
0049 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
0050     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
0051 
0052 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
0053 static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
0054     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
0055     HMAC_CTX *hctx, int enc);
0056 #endif
0057 
0058 #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
0059 static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str);
0060 #endif
0061 
0062 static time_t ngx_ssl_parse_time(
0063 #if OPENSSL_VERSION_NUMBER > 0x10100000L
0064     const
0065 #endif
0066     ASN1_TIME *asn1time);
0067 
0068 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
0069 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0070 static void ngx_openssl_exit(ngx_cycle_t *cycle);
0071 
0072 
0073 static ngx_command_t  ngx_openssl_commands[] = {
0074 
0075     { ngx_string("ssl_engine"),
0076       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0077       ngx_openssl_engine,
0078       0,
0079       0,
0080       NULL },
0081 
0082       ngx_null_command
0083 };
0084 
0085 
0086 static ngx_core_module_t  ngx_openssl_module_ctx = {
0087     ngx_string("openssl"),
0088     ngx_openssl_create_conf,
0089     NULL
0090 };
0091 
0092 
0093 ngx_module_t  ngx_openssl_module = {
0094     NGX_MODULE_V1,
0095     &ngx_openssl_module_ctx,               /* module context */
0096     ngx_openssl_commands,                  /* module directives */
0097     NGX_CORE_MODULE,                       /* module type */
0098     NULL,                                  /* init master */
0099     NULL,                                  /* init module */
0100     NULL,                                  /* init process */
0101     NULL,                                  /* init thread */
0102     NULL,                                  /* exit thread */
0103     NULL,                                  /* exit process */
0104     ngx_openssl_exit,                      /* exit master */
0105     NGX_MODULE_V1_PADDING
0106 };
0107 
0108 
0109 int  ngx_ssl_connection_index;
0110 int  ngx_ssl_server_conf_index;
0111 int  ngx_ssl_session_cache_index;
0112 int  ngx_ssl_session_ticket_keys_index;
0113 int  ngx_ssl_certificate_index;
0114 int  ngx_ssl_next_certificate_index;
0115 int  ngx_ssl_certificate_name_index;
0116 int  ngx_ssl_stapling_index;
0117 
0118 
0119 ngx_int_t
0120 ngx_ssl_init(ngx_log_t *log)
0121 {
0122 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
0123 
0124     if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) == 0) {
0125         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "OPENSSL_init_ssl() failed");
0126         return NGX_ERROR;
0127     }
0128 
0129     /*
0130      * OPENSSL_init_ssl() may leave errors in the error queue
0131      * while returning success
0132      */
0133 
0134     ERR_clear_error();
0135 
0136 #else
0137 
0138     OPENSSL_config(NULL);
0139 
0140     SSL_library_init();
0141     SSL_load_error_strings();
0142 
0143     OpenSSL_add_all_algorithms();
0144 
0145 #endif
0146 
0147 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
0148 #ifndef SSL_OP_NO_COMPRESSION
0149     {
0150     /*
0151      * Disable gzip compression in OpenSSL prior to 1.0.0 version,
0152      * this saves about 522K per connection.
0153      */
0154     int                  n;
0155     STACK_OF(SSL_COMP)  *ssl_comp_methods;
0156 
0157     ssl_comp_methods = SSL_COMP_get_compression_methods();
0158     n = sk_SSL_COMP_num(ssl_comp_methods);
0159 
0160     while (n--) {
0161         (void) sk_SSL_COMP_pop(ssl_comp_methods);
0162     }
0163     }
0164 #endif
0165 #endif
0166 
0167     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
0168 
0169     if (ngx_ssl_connection_index == -1) {
0170         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
0171         return NGX_ERROR;
0172     }
0173 
0174     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
0175                                                          NULL);
0176     if (ngx_ssl_server_conf_index == -1) {
0177         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0178                       "SSL_CTX_get_ex_new_index() failed");
0179         return NGX_ERROR;
0180     }
0181 
0182     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
0183                                                            NULL);
0184     if (ngx_ssl_session_cache_index == -1) {
0185         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0186                       "SSL_CTX_get_ex_new_index() failed");
0187         return NGX_ERROR;
0188     }
0189 
0190     ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
0191                                                                  NULL, NULL);
0192     if (ngx_ssl_session_ticket_keys_index == -1) {
0193         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0194                       "SSL_CTX_get_ex_new_index() failed");
0195         return NGX_ERROR;
0196     }
0197 
0198     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
0199                                                          NULL);
0200     if (ngx_ssl_certificate_index == -1) {
0201         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
0202                       "SSL_CTX_get_ex_new_index() failed");
0203         return NGX_ERROR;
0204     }
0205 
0206     ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
0207                                                            NULL);
0208     if (ngx_ssl_next_certificate_index == -1) {
0209         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
0210         return NGX_ERROR;
0211     }
0212 
0213     ngx_ssl_certificate_name_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
0214                                                            NULL);
0215 
0216     if (ngx_ssl_certificate_name_index == -1) {
0217         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
0218         return NGX_ERROR;
0219     }
0220 
0221     ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL);
0222 
0223     if (ngx_ssl_stapling_index == -1) {
0224         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
0225         return NGX_ERROR;
0226     }
0227 
0228     return NGX_OK;
0229 }
0230 
0231 
0232 ngx_int_t
0233 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
0234 {
0235     ssl->ctx = SSL_CTX_new(SSLv23_method());
0236 
0237     if (ssl->ctx == NULL) {
0238         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
0239         return NGX_ERROR;
0240     }
0241 
0242     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
0243         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0244                       "SSL_CTX_set_ex_data() failed");
0245         return NGX_ERROR;
0246     }
0247 
0248     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) {
0249         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0250                       "SSL_CTX_set_ex_data() failed");
0251         return NGX_ERROR;
0252     }
0253 
0254     ssl->buffer_size = NGX_SSL_BUFSIZE;
0255 
0256     /* client side options */
0257 
0258 #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
0259     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
0260 #endif
0261 
0262 #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
0263     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
0264 #endif
0265 
0266     /* server side options */
0267 
0268 #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
0269     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
0270 #endif
0271 
0272 #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
0273     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
0274 #endif
0275 
0276 #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
0277     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
0278     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
0279 #endif
0280 
0281 #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
0282     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
0283 #endif
0284 
0285 #ifdef SSL_OP_TLS_D5_BUG
0286     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
0287 #endif
0288 
0289 #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
0290     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
0291 #endif
0292 
0293 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
0294     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
0295 #endif
0296 
0297     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
0298 
0299 #ifdef SSL_CTRL_CLEAR_OPTIONS
0300     /* only in 0.9.8m+ */
0301     SSL_CTX_clear_options(ssl->ctx,
0302                           SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1);
0303 #endif
0304 
0305     if (!(protocols & NGX_SSL_SSLv2)) {
0306         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
0307     }
0308     if (!(protocols & NGX_SSL_SSLv3)) {
0309         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
0310     }
0311     if (!(protocols & NGX_SSL_TLSv1)) {
0312         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
0313     }
0314 #ifdef SSL_OP_NO_TLSv1_1
0315     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
0316     if (!(protocols & NGX_SSL_TLSv1_1)) {
0317         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
0318     }
0319 #endif
0320 #ifdef SSL_OP_NO_TLSv1_2
0321     SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
0322     if (!(protocols & NGX_SSL_TLSv1_2)) {
0323         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
0324     }
0325 #endif
0326 
0327 #ifdef SSL_OP_NO_COMPRESSION
0328     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
0329 #endif
0330 
0331 #ifdef SSL_MODE_RELEASE_BUFFERS
0332     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
0333 #endif
0334 
0335 #ifdef SSL_MODE_NO_AUTO_CHAIN
0336     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_NO_AUTO_CHAIN);
0337 #endif
0338 
0339     SSL_CTX_set_read_ahead(ssl->ctx, 1);
0340 
0341     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
0342 
0343     return NGX_OK;
0344 }
0345 
0346 
0347 ngx_int_t
0348 ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
0349     ngx_array_t *keys, ngx_array_t *passwords)
0350 {
0351     ngx_str_t   *cert, *key;
0352     ngx_uint_t   i;
0353 
0354     cert = certs->elts;
0355     key = keys->elts;
0356 
0357     for (i = 0; i < certs->nelts; i++) {
0358 
0359         if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords)
0360             != NGX_OK)
0361         {
0362             return NGX_ERROR;
0363         }
0364     }
0365 
0366     return NGX_OK;
0367 }
0368 
0369 
0370 ngx_int_t
0371 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
0372     ngx_str_t *key, ngx_array_t *passwords)
0373 {
0374     BIO         *bio;
0375     X509        *x509;
0376     u_long       n;
0377     ngx_str_t   *pwd;
0378     ngx_uint_t   tries;
0379 
0380     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
0381         return NGX_ERROR;
0382     }
0383 
0384     /*
0385      * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
0386      * allow to access certificate later from SSL_CTX, so we reimplement
0387      * it here
0388      */
0389 
0390     bio = BIO_new_file((char *) cert->data, "r");
0391     if (bio == NULL) {
0392         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0393                       "BIO_new_file(\"%s\") failed", cert->data);
0394         return NGX_ERROR;
0395     }
0396 
0397     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
0398     if (x509 == NULL) {
0399         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0400                       "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
0401         BIO_free(bio);
0402         return NGX_ERROR;
0403     }
0404 
0405     if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
0406         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0407                       "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
0408         X509_free(x509);
0409         BIO_free(bio);
0410         return NGX_ERROR;
0411     }
0412 
0413     if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data)
0414         == 0)
0415     {
0416         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
0417         X509_free(x509);
0418         BIO_free(bio);
0419         return NGX_ERROR;
0420     }
0421 
0422     if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index,
0423                       SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index))
0424         == 0)
0425     {
0426         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
0427         X509_free(x509);
0428         BIO_free(bio);
0429         return NGX_ERROR;
0430     }
0431 
0432     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
0433         == 0)
0434     {
0435         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0436                       "SSL_CTX_set_ex_data() failed");
0437         X509_free(x509);
0438         BIO_free(bio);
0439         return NGX_ERROR;
0440     }
0441 
0442     /* read rest of the chain */
0443 
0444     for ( ;; ) {
0445 
0446         x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
0447         if (x509 == NULL) {
0448             n = ERR_peek_last_error();
0449 
0450             if (ERR_GET_LIB(n) == ERR_LIB_PEM
0451                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
0452             {
0453                 /* end of file */
0454                 ERR_clear_error();
0455                 break;
0456             }
0457 
0458             /* some real error */
0459 
0460             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0461                           "PEM_read_bio_X509(\"%s\") failed", cert->data);
0462             BIO_free(bio);
0463             return NGX_ERROR;
0464         }
0465 
0466 #ifdef SSL_CTRL_CHAIN_CERT
0467 
0468         /*
0469          * SSL_CTX_add0_chain_cert() is needed to add chain to
0470          * a particular certificate when multiple certificates are used;
0471          * only available in OpenSSL 1.0.2+
0472          */
0473 
0474         if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) {
0475             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0476                           "SSL_CTX_add0_chain_cert(\"%s\") failed",
0477                           cert->data);
0478             X509_free(x509);
0479             BIO_free(bio);
0480             return NGX_ERROR;
0481         }
0482 
0483 #else
0484         if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
0485             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0486                           "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
0487                           cert->data);
0488             X509_free(x509);
0489             BIO_free(bio);
0490             return NGX_ERROR;
0491         }
0492 #endif
0493     }
0494 
0495     BIO_free(bio);
0496 
0497     if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) {
0498 
0499 #ifndef OPENSSL_NO_ENGINE
0500 
0501         u_char      *p, *last;
0502         ENGINE      *engine;
0503         EVP_PKEY    *pkey;
0504 
0505         p = key->data + sizeof("engine:") - 1;
0506         last = (u_char *) ngx_strchr(p, ':');
0507 
0508         if (last == NULL) {
0509             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0510                                "invalid syntax in \"%V\"", key);
0511             return NGX_ERROR;
0512         }
0513 
0514         *last = '\0';
0515 
0516         engine = ENGINE_by_id((char *) p);
0517 
0518         if (engine == NULL) {
0519             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0520                           "ENGINE_by_id(\"%s\") failed", p);
0521             return NGX_ERROR;
0522         }
0523 
0524         *last++ = ':';
0525 
0526         pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);
0527 
0528         if (pkey == NULL) {
0529             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0530                           "ENGINE_load_private_key(\"%s\") failed", last);
0531             ENGINE_free(engine);
0532             return NGX_ERROR;
0533         }
0534 
0535         ENGINE_free(engine);
0536 
0537         if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
0538             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0539                           "SSL_CTX_use_PrivateKey(\"%s\") failed", last);
0540             EVP_PKEY_free(pkey);
0541             return NGX_ERROR;
0542         }
0543 
0544         EVP_PKEY_free(pkey);
0545 
0546         return NGX_OK;
0547 
0548 #else
0549 
0550         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0551                            "loading \"engine:...\" certificate keys "
0552                            "is not supported");
0553         return NGX_ERROR;
0554 
0555 #endif
0556     }
0557 
0558     if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
0559         return NGX_ERROR;
0560     }
0561 
0562     if (passwords) {
0563         tries = passwords->nelts;
0564         pwd = passwords->elts;
0565 
0566         SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_ssl_password_callback);
0567         SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, pwd);
0568 
0569     } else {
0570         tries = 1;
0571 #if (NGX_SUPPRESS_WARN)
0572         pwd = NULL;
0573 #endif
0574     }
0575 
0576     for ( ;; ) {
0577 
0578         if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
0579                                         SSL_FILETYPE_PEM)
0580             != 0)
0581         {
0582             break;
0583         }
0584 
0585         if (--tries) {
0586             ERR_clear_error();
0587             SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd);
0588             continue;
0589         }
0590 
0591         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0592                       "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
0593         return NGX_ERROR;
0594     }
0595 
0596     SSL_CTX_set_default_passwd_cb(ssl->ctx, NULL);
0597 
0598     return NGX_OK;
0599 }
0600 
0601 
0602 static int
0603 ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
0604 {
0605     ngx_str_t *pwd = userdata;
0606 
0607     if (rwflag) {
0608         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
0609                       "ngx_ssl_password_callback() is called for encryption");
0610         return 0;
0611     }
0612 
0613     if (pwd->len > (size_t) size) {
0614         ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
0615                       "password is truncated to %d bytes", size);
0616     } else {
0617         size = pwd->len;
0618     }
0619 
0620     ngx_memcpy(buf, pwd->data, size);
0621 
0622     return size;
0623 }
0624 
0625 
0626 ngx_int_t
0627 ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
0628     ngx_uint_t prefer_server_ciphers)
0629 {
0630     if (SSL_CTX_set_cipher_list(ssl->ctx, (char *) ciphers->data) == 0) {
0631         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0632                       "SSL_CTX_set_cipher_list(\"%V\") failed",
0633                       ciphers);
0634         return NGX_ERROR;
0635     }
0636 
0637     if (prefer_server_ciphers) {
0638         SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
0639     }
0640 
0641 #if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
0642     /* a temporary 512-bit RSA key is required for export versions of MSIE */
0643     SSL_CTX_set_tmp_rsa_callback(ssl->ctx, ngx_ssl_rsa512_key_callback);
0644 #endif
0645 
0646     return NGX_OK;
0647 }
0648 
0649 
0650 ngx_int_t
0651 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
0652     ngx_int_t depth)
0653 {
0654     STACK_OF(X509_NAME)  *list;
0655 
0656     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_ssl_verify_callback);
0657 
0658     SSL_CTX_set_verify_depth(ssl->ctx, depth);
0659 
0660     if (cert->len == 0) {
0661         return NGX_OK;
0662     }
0663 
0664     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
0665         return NGX_ERROR;
0666     }
0667 
0668     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
0669         == 0)
0670     {
0671         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0672                       "SSL_CTX_load_verify_locations(\"%s\") failed",
0673                       cert->data);
0674         return NGX_ERROR;
0675     }
0676 
0677     /*
0678      * SSL_CTX_load_verify_locations() may leave errors in the error queue
0679      * while returning success
0680      */
0681 
0682     ERR_clear_error();
0683 
0684     list = SSL_load_client_CA_file((char *) cert->data);
0685 
0686     if (list == NULL) {
0687         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0688                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
0689         return NGX_ERROR;
0690     }
0691 
0692     /*
0693      * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
0694      * always leaved an error in the error queue
0695      */
0696 
0697     ERR_clear_error();
0698 
0699     SSL_CTX_set_client_CA_list(ssl->ctx, list);
0700 
0701     return NGX_OK;
0702 }
0703 
0704 
0705 ngx_int_t
0706 ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
0707     ngx_int_t depth)
0708 {
0709     SSL_CTX_set_verify_depth(ssl->ctx, depth);
0710 
0711     if (cert->len == 0) {
0712         return NGX_OK;
0713     }
0714 
0715     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
0716         return NGX_ERROR;
0717     }
0718 
0719     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
0720         == 0)
0721     {
0722         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0723                       "SSL_CTX_load_verify_locations(\"%s\") failed",
0724                       cert->data);
0725         return NGX_ERROR;
0726     }
0727 
0728     /*
0729      * SSL_CTX_load_verify_locations() may leave errors in the error queue
0730      * while returning success
0731      */
0732 
0733     ERR_clear_error();
0734 
0735     return NGX_OK;
0736 }
0737 
0738 
0739 ngx_int_t
0740 ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
0741 {
0742     X509_STORE   *store;
0743     X509_LOOKUP  *lookup;
0744 
0745     if (crl->len == 0) {
0746         return NGX_OK;
0747     }
0748 
0749     if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
0750         return NGX_ERROR;
0751     }
0752 
0753     store = SSL_CTX_get_cert_store(ssl->ctx);
0754 
0755     if (store == NULL) {
0756         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0757                       "SSL_CTX_get_cert_store() failed");
0758         return NGX_ERROR;
0759     }
0760 
0761     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
0762 
0763     if (lookup == NULL) {
0764         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0765                       "X509_STORE_add_lookup() failed");
0766         return NGX_ERROR;
0767     }
0768 
0769     if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
0770         == 0)
0771     {
0772         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0773                       "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
0774         return NGX_ERROR;
0775     }
0776 
0777     X509_STORE_set_flags(store,
0778                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
0779 
0780     return NGX_OK;
0781 }
0782 
0783 
0784 static int
0785 ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
0786 {
0787 #if (NGX_DEBUG)
0788     char              *subject, *issuer;
0789     int                err, depth;
0790     X509              *cert;
0791     X509_NAME         *sname, *iname;
0792     ngx_connection_t  *c;
0793     ngx_ssl_conn_t    *ssl_conn;
0794 
0795     ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
0796                                           SSL_get_ex_data_X509_STORE_CTX_idx());
0797 
0798     c = ngx_ssl_get_connection(ssl_conn);
0799 
0800     cert = X509_STORE_CTX_get_current_cert(x509_store);
0801     err = X509_STORE_CTX_get_error(x509_store);
0802     depth = X509_STORE_CTX_get_error_depth(x509_store);
0803 
0804     sname = X509_get_subject_name(cert);
0805     subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
0806 
0807     iname = X509_get_issuer_name(cert);
0808     issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
0809 
0810     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
0811                    "verify:%d, error:%d, depth:%d, "
0812                    "subject:\"%s\", issuer:\"%s\"",
0813                    ok, err, depth, subject, issuer);
0814 
0815     if (sname) {
0816         OPENSSL_free(subject);
0817     }
0818 
0819     if (iname) {
0820         OPENSSL_free(issuer);
0821     }
0822 #endif
0823 
0824     return 1;
0825 }
0826 
0827 
0828 static void
0829 ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
0830 {
0831     BIO               *rbio, *wbio;
0832     ngx_connection_t  *c;
0833 
0834     if (where & SSL_CB_HANDSHAKE_START) {
0835         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
0836 
0837         if (c->ssl->handshaked) {
0838             c->ssl->renegotiation = 1;
0839             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
0840         }
0841     }
0842 
0843     if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
0844         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
0845 
0846         if (!c->ssl->handshake_buffer_set) {
0847             /*
0848              * By default OpenSSL uses 4k buffer during a handshake,
0849              * which is too low for long certificate chains and might
0850              * result in extra round-trips.
0851              *
0852              * To adjust a buffer size we detect that buffering was added
0853              * to write side of the connection by comparing rbio and wbio.
0854              * If they are different, we assume that it's due to buffering
0855              * added to wbio, and set buffer size.
0856              */
0857 
0858             rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn);
0859             wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn);
0860 
0861             if (rbio != wbio) {
0862                 (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE);
0863                 c->ssl->handshake_buffer_set = 1;
0864             }
0865         }
0866     }
0867 }
0868 
0869 
0870 RSA *
0871 ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
0872     int key_length)
0873 {
0874     static RSA  *key;
0875 
0876     if (key_length != 512) {
0877         return NULL;
0878     }
0879 
0880 #if (OPENSSL_VERSION_NUMBER < 0x10100003L && !defined OPENSSL_NO_DEPRECATED)
0881 
0882     if (key == NULL) {
0883         key = RSA_generate_key(512, RSA_F4, NULL, NULL);
0884     }
0885 
0886 #endif
0887 
0888     return key;
0889 }
0890 
0891 
0892 ngx_array_t *
0893 ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
0894 {
0895     u_char              *p, *last, *end;
0896     size_t               len;
0897     ssize_t              n;
0898     ngx_fd_t             fd;
0899     ngx_str_t           *pwd;
0900     ngx_array_t         *passwords;
0901     ngx_pool_cleanup_t  *cln;
0902     u_char               buf[NGX_SSL_PASSWORD_BUFFER_SIZE];
0903 
0904     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
0905         return NULL;
0906     }
0907 
0908     cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
0909     passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
0910 
0911     if (cln == NULL || passwords == NULL) {
0912         return NULL;
0913     }
0914 
0915     cln->handler = ngx_ssl_passwords_cleanup;
0916     cln->data = passwords;
0917 
0918     fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
0919     if (fd == NGX_INVALID_FILE) {
0920         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
0921                            ngx_open_file_n " \"%s\" failed", file->data);
0922         return NULL;
0923     }
0924 
0925     len = 0;
0926     last = buf;
0927 
0928     do {
0929         n = ngx_read_fd(fd, last, NGX_SSL_PASSWORD_BUFFER_SIZE - len);
0930 
0931         if (n == -1) {
0932             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
0933                                ngx_read_fd_n " \"%s\" failed", file->data);
0934             passwords = NULL;
0935             goto cleanup;
0936         }
0937 
0938         end = last + n;
0939 
0940         if (len && n == 0) {
0941             *end++ = LF;
0942         }
0943 
0944         p = buf;
0945 
0946         for ( ;; ) {
0947             last = ngx_strlchr(last, end, LF);
0948 
0949             if (last == NULL) {
0950                 break;
0951             }
0952 
0953             len = last++ - p;
0954 
0955             if (len && p[len - 1] == CR) {
0956                 len--;
0957             }
0958 
0959             if (len) {
0960                 pwd = ngx_array_push(passwords);
0961                 if (pwd == NULL) {
0962                     passwords = NULL;
0963                     goto cleanup;
0964                 }
0965 
0966                 pwd->len = len;
0967                 pwd->data = ngx_pnalloc(cf->temp_pool, len);
0968 
0969                 if (pwd->data == NULL) {
0970                     passwords->nelts--;
0971                     passwords = NULL;
0972                     goto cleanup;
0973                 }
0974 
0975                 ngx_memcpy(pwd->data, p, len);
0976             }
0977 
0978             p = last;
0979         }
0980 
0981         len = end - p;
0982 
0983         if (len == NGX_SSL_PASSWORD_BUFFER_SIZE) {
0984             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0985                                "too long line in \"%s\"", file->data);
0986             passwords = NULL;
0987             goto cleanup;
0988         }
0989 
0990         ngx_memmove(buf, p, len);
0991         last = buf + len;
0992 
0993     } while (n != 0);
0994 
0995     if (passwords->nelts == 0) {
0996         pwd = ngx_array_push(passwords);
0997         if (pwd == NULL) {
0998             passwords = NULL;
0999             goto cleanup;
1000         }
1001 
1002         ngx_memzero(pwd, sizeof(ngx_str_t));
1003     }
1004 
1005 cleanup:
1006 
1007     if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1008         ngx_conf_log_error(NGX_LOG_ALERT, cf, ngx_errno,
1009                            ngx_close_file_n " \"%s\" failed", file->data);
1010     }
1011 
1012     ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);
1013 
1014     return passwords;
1015 }
1016 
1017 
1018 static void
1019 ngx_ssl_passwords_cleanup(void *data)
1020 {
1021     ngx_array_t *passwords = data;
1022 
1023     ngx_str_t   *pwd;
1024     ngx_uint_t   i;
1025 
1026     pwd = passwords->elts;
1027 
1028     for (i = 0; i < passwords->nelts; i++) {
1029         ngx_memzero(pwd[i].data, pwd[i].len);
1030     }
1031 }
1032 
1033 
1034 ngx_int_t
1035 ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
1036 {
1037     DH   *dh;
1038     BIO  *bio;
1039 
1040     if (file->len == 0) {
1041         return NGX_OK;
1042     }
1043 
1044     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
1045         return NGX_ERROR;
1046     }
1047 
1048     bio = BIO_new_file((char *) file->data, "r");
1049     if (bio == NULL) {
1050         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1051                       "BIO_new_file(\"%s\") failed", file->data);
1052         return NGX_ERROR;
1053     }
1054 
1055     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1056     if (dh == NULL) {
1057         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1058                       "PEM_read_bio_DHparams(\"%s\") failed", file->data);
1059         BIO_free(bio);
1060         return NGX_ERROR;
1061     }
1062 
1063     SSL_CTX_set_tmp_dh(ssl->ctx, dh);
1064 
1065     DH_free(dh);
1066     BIO_free(bio);
1067 
1068     return NGX_OK;
1069 }
1070 
1071 
1072 ngx_int_t
1073 ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
1074 {
1075 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
1076 #ifndef OPENSSL_NO_ECDH
1077 
1078     /*
1079      * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
1080      * from RFC 4492 section 5.1.1, or explicitly described curves over
1081      * binary fields.  OpenSSL only supports the "named curves", which provide
1082      * maximum interoperability.
1083      */
1084 
1085 #ifdef SSL_CTRL_SET_CURVES_LIST
1086 
1087     /*
1088      * OpenSSL 1.0.2+ allows configuring a curve list instead of a single
1089      * curve previously supported.  By default an internal list is used,
1090      * with prime256v1 being preferred by server in OpenSSL 1.0.2b+
1091      * and X25519 in OpenSSL 1.1.0+.
1092      *
1093      * By default a curve preferred by the client will be used for
1094      * key exchange.  The SSL_OP_CIPHER_SERVER_PREFERENCE option can
1095      * be used to prefer server curves instead, similar to what it
1096      * does for ciphers.
1097      */
1098 
1099     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
1100 
1101 #if SSL_CTRL_SET_ECDH_AUTO
1102     /* not needed in OpenSSL 1.1.0+ */
1103     SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
1104 #endif
1105 
1106     if (ngx_strcmp(name->data, "auto") == 0) {
1107         return NGX_OK;
1108     }
1109 
1110     if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) {
1111         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1112                       "SSL_CTX_set1_curves_list(\"%s\") failed", name->data);
1113         return NGX_ERROR;
1114     }
1115 
1116 #else
1117 
1118     int      nid;
1119     char    *curve;
1120     EC_KEY  *ecdh;
1121 
1122     if (ngx_strcmp(name->data, "auto") == 0) {
1123         curve = "prime256v1";
1124 
1125     } else {
1126         curve = (char *) name->data;
1127     }
1128 
1129     nid = OBJ_sn2nid(curve);
1130     if (nid == 0) {
1131         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1132                       "OBJ_sn2nid(\"%s\") failed: unknown curve", curve);
1133         return NGX_ERROR;
1134     }
1135 
1136     ecdh = EC_KEY_new_by_curve_name(nid);
1137     if (ecdh == NULL) {
1138         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1139                       "EC_KEY_new_by_curve_name(\"%s\") failed", curve);
1140         return NGX_ERROR;
1141     }
1142 
1143     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
1144 
1145     SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
1146 
1147     EC_KEY_free(ecdh);
1148 #endif
1149 #endif
1150 #endif
1151 
1152     return NGX_OK;
1153 }
1154 
1155 
1156 ngx_int_t
1157 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
1158 {
1159     ngx_ssl_connection_t  *sc;
1160 
1161     sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
1162     if (sc == NULL) {
1163         return NGX_ERROR;
1164     }
1165 
1166     sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
1167     sc->buffer_size = ssl->buffer_size;
1168 
1169     sc->session_ctx = ssl->ctx;
1170 
1171     sc->connection = SSL_new(ssl->ctx);
1172 
1173     if (sc->connection == NULL) {
1174         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
1175         return NGX_ERROR;
1176     }
1177 
1178     if (SSL_set_fd(sc->connection, c->fd) == 0) {
1179         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
1180         return NGX_ERROR;
1181     }
1182 
1183     if (flags & NGX_SSL_CLIENT) {
1184         SSL_set_connect_state(sc->connection);
1185 
1186     } else {
1187         SSL_set_accept_state(sc->connection);
1188     }
1189 
1190     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
1191         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
1192         return NGX_ERROR;
1193     }
1194 
1195     c->ssl = sc;
1196 
1197     return NGX_OK;
1198 }
1199 
1200 
1201 ngx_int_t
1202 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
1203 {
1204     if (session) {
1205         if (SSL_set_session(c->ssl->connection, session) == 0) {
1206             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
1207             return NGX_ERROR;
1208         }
1209     }
1210 
1211     return NGX_OK;
1212 }
1213 
1214 
1215 ngx_int_t
1216 ngx_ssl_handshake(ngx_connection_t *c)
1217 {
1218     int        n, sslerr;
1219     ngx_err_t  err;
1220 
1221     ngx_ssl_clear_error(c->log);
1222 
1223     n = SSL_do_handshake(c->ssl->connection);
1224 
1225     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
1226 
1227     if (n == 1) {
1228 
1229         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1230             return NGX_ERROR;
1231         }
1232 
1233         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1234             return NGX_ERROR;
1235         }
1236 
1237 #if (NGX_DEBUG)
1238         {
1239         char         buf[129], *s, *d;
1240 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1241         const
1242 #endif
1243         SSL_CIPHER  *cipher;
1244 
1245         cipher = SSL_get_current_cipher(c->ssl->connection);
1246 
1247         if (cipher) {
1248             SSL_CIPHER_description(cipher, &buf[1], 128);
1249 
1250             for (s = &buf[1], d = buf; *s; s++) {
1251                 if (*s == ' ' && *d == ' ') {
1252                     continue;
1253                 }
1254 
1255                 if (*s == LF || *s == CR) {
1256                     continue;
1257                 }
1258 
1259                 *++d = *s;
1260             }
1261 
1262             if (*d != ' ') {
1263                 d++;
1264             }
1265 
1266             *d = '\0';
1267 
1268             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1269                            "SSL: %s, cipher: \"%s\"",
1270                            SSL_get_version(c->ssl->connection), &buf[1]);
1271 
1272             if (SSL_session_reused(c->ssl->connection)) {
1273                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1274                                "SSL reused session");
1275             }
1276 
1277         } else {
1278             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1279                            "SSL no shared ciphers");
1280         }
1281         }
1282 #endif
1283 
1284         c->ssl->handshaked = 1;
1285 
1286         c->recv = ngx_ssl_recv;
1287         c->send = ngx_ssl_write;
1288         c->recv_chain = ngx_ssl_recv_chain;
1289         c->send_chain = ngx_ssl_send_chain;
1290 
1291 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1292 #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
1293 
1294         /* initial handshake done, disable renegotiation (CVE-2009-3555) */
1295         if (c->ssl->connection->s3) {
1296             c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
1297         }
1298 
1299 #endif
1300 #endif
1301 
1302         return NGX_OK;
1303     }
1304 
1305     sslerr = SSL_get_error(c->ssl->connection, n);
1306 
1307     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1308 
1309     if (sslerr == SSL_ERROR_WANT_READ) {
1310         c->read->ready = 0;
1311         c->read->handler = ngx_ssl_handshake_handler;
1312         c->write->handler = ngx_ssl_handshake_handler;
1313 
1314         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1315             return NGX_ERROR;
1316         }
1317 
1318         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1319             return NGX_ERROR;
1320         }
1321 
1322         return NGX_AGAIN;
1323     }
1324 
1325     if (sslerr == SSL_ERROR_WANT_WRITE) {
1326         c->write->ready = 0;
1327         c->read->handler = ngx_ssl_handshake_handler;
1328         c->write->handler = ngx_ssl_handshake_handler;
1329 
1330         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1331             return NGX_ERROR;
1332         }
1333 
1334         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1335             return NGX_ERROR;
1336         }
1337 
1338         return NGX_AGAIN;
1339     }
1340 
1341     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1342 
1343     c->ssl->no_wait_shutdown = 1;
1344     c->ssl->no_send_shutdown = 1;
1345     c->read->eof = 1;
1346 
1347     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
1348         ngx_connection_error(c, err,
1349                              "peer closed connection in SSL handshake");
1350 
1351         return NGX_ERROR;
1352     }
1353 
1354     c->read->error = 1;
1355 
1356     ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
1357 
1358     return NGX_ERROR;
1359 }
1360 
1361 
1362 static void
1363 ngx_ssl_handshake_handler(ngx_event_t *ev)
1364 {
1365     ngx_connection_t  *c;
1366 
1367     c = ev->data;
1368 
1369     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1370                    "SSL handshake handler: %d", ev->write);
1371 
1372     if (ev->timedout) {
1373         c->ssl->handler(c);
1374         return;
1375     }
1376 
1377     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
1378         return;
1379     }
1380 
1381     c->ssl->handler(c);
1382 }
1383 
1384 
1385 ssize_t
1386 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit)
1387 {
1388     u_char     *last;
1389     ssize_t     n, bytes, size;
1390     ngx_buf_t  *b;
1391 
1392     bytes = 0;
1393 
1394     b = cl->buf;
1395     last = b->last;
1396 
1397     for ( ;; ) {
1398         size = b->end - last;
1399 
1400         if (limit) {
1401             if (bytes >= limit) {
1402                 return bytes;
1403             }
1404 
1405             if (bytes + size > limit) {
1406                 size = (ssize_t) (limit - bytes);
1407             }
1408         }
1409 
1410         n = ngx_ssl_recv(c, last, size);
1411 
1412         if (n > 0) {
1413             last += n;
1414             bytes += n;
1415 
1416             if (last == b->end) {
1417                 cl = cl->next;
1418 
1419                 if (cl == NULL) {
1420                     return bytes;
1421                 }
1422 
1423                 b = cl->buf;
1424                 last = b->last;
1425             }
1426 
1427             continue;
1428         }
1429 
1430         if (bytes) {
1431 
1432             if (n == 0 || n == NGX_ERROR) {
1433                 c->read->ready = 1;
1434             }
1435 
1436             return bytes;
1437         }
1438 
1439         return n;
1440     }
1441 }
1442 
1443 
1444 ssize_t
1445 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
1446 {
1447     int  n, bytes;
1448 
1449     if (c->ssl->last == NGX_ERROR) {
1450         c->read->error = 1;
1451         return NGX_ERROR;
1452     }
1453 
1454     if (c->ssl->last == NGX_DONE) {
1455         c->read->ready = 0;
1456         c->read->eof = 1;
1457         return 0;
1458     }
1459 
1460     bytes = 0;
1461 
1462     ngx_ssl_clear_error(c->log);
1463 
1464     /*
1465      * SSL_read() may return data in parts, so try to read
1466      * until SSL_read() would return no data
1467      */
1468 
1469     for ( ;; ) {
1470 
1471         n = SSL_read(c->ssl->connection, buf, size);
1472 
1473         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
1474 
1475         if (n > 0) {
1476             bytes += n;
1477         }
1478 
1479         c->ssl->last = ngx_ssl_handle_recv(c, n);
1480 
1481         if (c->ssl->last == NGX_OK) {
1482 
1483             size -= n;
1484 
1485             if (size == 0) {
1486                 c->read->ready = 1;
1487                 return bytes;
1488             }
1489 
1490             buf += n;
1491 
1492             continue;
1493         }
1494 
1495         if (bytes) {
1496             if (c->ssl->last != NGX_AGAIN) {
1497                 c->read->ready = 1;
1498             }
1499 
1500             return bytes;
1501         }
1502 
1503         switch (c->ssl->last) {
1504 
1505         case NGX_DONE:
1506             c->read->ready = 0;
1507             c->read->eof = 1;
1508             return 0;
1509 
1510         case NGX_ERROR:
1511             c->read->error = 1;
1512 
1513             /* fall through */
1514 
1515         case NGX_AGAIN:
1516             return c->ssl->last;
1517         }
1518     }
1519 }
1520 
1521 
1522 static ngx_int_t
1523 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
1524 {
1525     int        sslerr;
1526     ngx_err_t  err;
1527 
1528     if (c->ssl->renegotiation) {
1529         /*
1530          * disable renegotiation (CVE-2009-3555):
1531          * OpenSSL (at least up to 0.9.8l) does not handle disabled
1532          * renegotiation gracefully, so drop connection here
1533          */
1534 
1535         ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
1536 
1537         while (ERR_peek_error()) {
1538             ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
1539                           "ignoring stale global SSL error");
1540         }
1541 
1542         ERR_clear_error();
1543 
1544         c->ssl->no_wait_shutdown = 1;
1545         c->ssl->no_send_shutdown = 1;
1546 
1547         return NGX_ERROR;
1548     }
1549 
1550     if (n > 0) {
1551 
1552         if (c->ssl->saved_write_handler) {
1553 
1554             c->write->handler = c->ssl->saved_write_handler;
1555             c->ssl->saved_write_handler = NULL;
1556             c->write->ready = 1;
1557 
1558             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1559                 return NGX_ERROR;
1560             }
1561 
1562             ngx_post_event(c->write, &ngx_posted_events);
1563         }
1564 
1565         return NGX_OK;
1566     }
1567 
1568     sslerr = SSL_get_error(c->ssl->connection, n);
1569 
1570     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1571 
1572     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1573 
1574     if (sslerr == SSL_ERROR_WANT_READ) {
1575         c->read->ready = 0;
1576         return NGX_AGAIN;
1577     }
1578 
1579     if (sslerr == SSL_ERROR_WANT_WRITE) {
1580 
1581         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1582                       "peer started SSL renegotiation");
1583 
1584         c->write->ready = 0;
1585 
1586         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1587             return NGX_ERROR;
1588         }
1589 
1590         /*
1591          * we do not set the timer because there is already the read event timer
1592          */
1593 
1594         if (c->ssl->saved_write_handler == NULL) {
1595             c->ssl->saved_write_handler = c->write->handler;
1596             c->write->handler = ngx_ssl_write_handler;
1597         }
1598 
1599         return NGX_AGAIN;
1600     }
1601 
1602     c->ssl->no_wait_shutdown = 1;
1603     c->ssl->no_send_shutdown = 1;
1604 
1605     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
1606         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1607                        "peer shutdown SSL cleanly");
1608         return NGX_DONE;
1609     }
1610 
1611     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
1612 
1613     return NGX_ERROR;
1614 }
1615 
1616 
1617 static void
1618 ngx_ssl_write_handler(ngx_event_t *wev)
1619 {
1620     ngx_connection_t  *c;
1621 
1622     c = wev->data;
1623 
1624     c->read->handler(c->read);
1625 }
1626 
1627 
1628 /*
1629  * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
1630  * before the SSL_write() call to decrease a SSL overhead.
1631  *
1632  * Besides for protocols such as HTTP it is possible to always buffer
1633  * the output to decrease a SSL overhead some more.
1634  */
1635 
1636 ngx_chain_t *
1637 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
1638 {
1639     int          n;
1640     ngx_uint_t   flush;
1641     ssize_t      send, size;
1642     ngx_buf_t   *buf;
1643 
1644     if (!c->ssl->buffer) {
1645 
1646         while (in) {
1647             if (ngx_buf_special(in->buf)) {
1648                 in = in->next;
1649                 continue;
1650             }
1651 
1652             n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
1653 
1654             if (n == NGX_ERROR) {
1655                 return NGX_CHAIN_ERROR;
1656             }
1657 
1658             if (n == NGX_AGAIN) {
1659                 return in;
1660             }
1661 
1662             in->buf->pos += n;
1663 
1664             if (in->buf->pos == in->buf->last) {
1665                 in = in->next;
1666             }
1667         }
1668 
1669         return in;
1670     }
1671 
1672 
1673     /* the maximum limit size is the maximum int32_t value - the page size */
1674 
1675     if (limit == 0 || limit > (off_t) (NGX_MAX_INT32_VALUE - ngx_pagesize)) {
1676         limit = NGX_MAX_INT32_VALUE - ngx_pagesize;
1677     }
1678 
1679     buf = c->ssl->buf;
1680 
1681     if (buf == NULL) {
1682         buf = ngx_create_temp_buf(c->pool, c->ssl->buffer_size);
1683         if (buf == NULL) {
1684             return NGX_CHAIN_ERROR;
1685         }
1686 
1687         c->ssl->buf = buf;
1688     }
1689 
1690     if (buf->start == NULL) {
1691         buf->start = ngx_palloc(c->pool, c->ssl->buffer_size);
1692         if (buf->start == NULL) {
1693             return NGX_CHAIN_ERROR;
1694         }
1695 
1696         buf->pos = buf->start;
1697         buf->last = buf->start;
1698         buf->end = buf->start + c->ssl->buffer_size;
1699     }
1700 
1701     send = buf->last - buf->pos;
1702     flush = (in == NULL) ? 1 : buf->flush;
1703 
1704     for ( ;; ) {
1705 
1706         while (in && buf->last < buf->end && send < limit) {
1707             if (in->buf->last_buf || in->buf->flush) {
1708                 flush = 1;
1709             }
1710 
1711             if (ngx_buf_special(in->buf)) {
1712                 in = in->next;
1713                 continue;
1714             }
1715 
1716             size = in->buf->last - in->buf->pos;
1717 
1718             if (size > buf->end - buf->last) {
1719                 size = buf->end - buf->last;
1720             }
1721 
1722             if (send + size > limit) {
1723                 size = (ssize_t) (limit - send);
1724             }
1725 
1726             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1727                            "SSL buf copy: %z", size);
1728 
1729             ngx_memcpy(buf->last, in->buf->pos, size);
1730 
1731             buf->last += size;
1732             in->buf->pos += size;
1733             send += size;
1734 
1735             if (in->buf->pos == in->buf->last) {
1736                 in = in->next;
1737             }
1738         }
1739 
1740         if (!flush && send < limit && buf->last < buf->end) {
1741             break;
1742         }
1743 
1744         size = buf->last - buf->pos;
1745 
1746         if (size == 0) {
1747             buf->flush = 0;
1748             c->buffered &= ~NGX_SSL_BUFFERED;
1749             return in;
1750         }
1751 
1752         n = ngx_ssl_write(c, buf->pos, size);
1753 
1754         if (n == NGX_ERROR) {
1755             return NGX_CHAIN_ERROR;
1756         }
1757 
1758         if (n == NGX_AGAIN) {
1759             break;
1760         }
1761 
1762         buf->pos += n;
1763 
1764         if (n < size) {
1765             break;
1766         }
1767 
1768         flush = 0;
1769 
1770         buf->pos = buf->start;
1771         buf->last = buf->start;
1772 
1773         if (in == NULL || send == limit) {
1774             break;
1775         }
1776     }
1777 
1778     buf->flush = flush;
1779 
1780     if (buf->pos < buf->last) {
1781         c->buffered |= NGX_SSL_BUFFERED;
1782 
1783     } else {
1784         c->buffered &= ~NGX_SSL_BUFFERED;
1785     }
1786 
1787     return in;
1788 }
1789 
1790 
1791 ssize_t
1792 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
1793 {
1794     int        n, sslerr;
1795     ngx_err_t  err;
1796 
1797     ngx_ssl_clear_error(c->log);
1798 
1799     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size);
1800 
1801     n = SSL_write(c->ssl->connection, data, size);
1802 
1803     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
1804 
1805     if (n > 0) {
1806 
1807         if (c->ssl->saved_read_handler) {
1808 
1809             c->read->handler = c->ssl->saved_read_handler;
1810             c->ssl->saved_read_handler = NULL;
1811             c->read->ready = 1;
1812 
1813             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1814                 return NGX_ERROR;
1815             }
1816 
1817             ngx_post_event(c->read, &ngx_posted_events);
1818         }
1819 
1820         c->sent += n;
1821 
1822         return n;
1823     }
1824 
1825     sslerr = SSL_get_error(c->ssl->connection, n);
1826 
1827     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1828 
1829     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1830 
1831     if (sslerr == SSL_ERROR_WANT_WRITE) {
1832         c->write->ready = 0;
1833         return NGX_AGAIN;
1834     }
1835 
1836     if (sslerr == SSL_ERROR_WANT_READ) {
1837 
1838         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1839                       "peer started SSL renegotiation");
1840 
1841         c->read->ready = 0;
1842 
1843         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1844             return NGX_ERROR;
1845         }
1846 
1847         /*
1848          * we do not set the timer because there is already
1849          * the write event timer
1850          */
1851 
1852         if (c->ssl->saved_read_handler == NULL) {
1853             c->ssl->saved_read_handler = c->read->handler;
1854             c->read->handler = ngx_ssl_read_handler;
1855         }
1856 
1857         return NGX_AGAIN;
1858     }
1859 
1860     c->ssl->no_wait_shutdown = 1;
1861     c->ssl->no_send_shutdown = 1;
1862     c->write->error = 1;
1863 
1864     ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
1865 
1866     return NGX_ERROR;
1867 }
1868 
1869 
1870 static void
1871 ngx_ssl_read_handler(ngx_event_t *rev)
1872 {
1873     ngx_connection_t  *c;
1874 
1875     c = rev->data;
1876 
1877     c->write->handler(c->write);
1878 }
1879 
1880 
1881 void
1882 ngx_ssl_free_buffer(ngx_connection_t *c)
1883 {
1884     if (c->ssl->buf && c->ssl->buf->start) {
1885         if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1886             c->ssl->buf->start = NULL;
1887         }
1888     }
1889 }
1890 
1891 
1892 ngx_int_t
1893 ngx_ssl_shutdown(ngx_connection_t *c)
1894 {
1895     int        n, sslerr, mode;
1896     ngx_err_t  err;
1897 
1898     if (SSL_in_init(c->ssl->connection)) {
1899         /*
1900          * OpenSSL 1.0.2f complains if SSL_shutdown() is called during
1901          * an SSL handshake, while previous versions always return 0.
1902          * Avoid calling SSL_shutdown() if handshake wasn't completed.
1903          */
1904 
1905         SSL_free(c->ssl->connection);
1906         c->ssl = NULL;
1907 
1908         return NGX_OK;
1909     }
1910 
1911     if (c->timedout) {
1912         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1913         SSL_set_quiet_shutdown(c->ssl->connection, 1);
1914 
1915     } else {
1916         mode = SSL_get_shutdown(c->ssl->connection);
1917 
1918         if (c->ssl->no_wait_shutdown) {
1919             mode |= SSL_RECEIVED_SHUTDOWN;
1920         }
1921 
1922         if (c->ssl->no_send_shutdown) {
1923             mode |= SSL_SENT_SHUTDOWN;
1924         }
1925 
1926         if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
1927             SSL_set_quiet_shutdown(c->ssl->connection, 1);
1928         }
1929     }
1930 
1931     SSL_set_shutdown(c->ssl->connection, mode);
1932 
1933     ngx_ssl_clear_error(c->log);
1934 
1935     n = SSL_shutdown(c->ssl->connection);
1936 
1937     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1938 
1939     sslerr = 0;
1940 
1941     /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
1942 
1943     if (n != 1 && ERR_peek_error()) {
1944         sslerr = SSL_get_error(c->ssl->connection, n);
1945 
1946         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1947                        "SSL_get_error: %d", sslerr);
1948     }
1949 
1950     if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1951         SSL_free(c->ssl->connection);
1952         c->ssl = NULL;
1953 
1954         return NGX_OK;
1955     }
1956 
1957     if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1958         c->read->handler = ngx_ssl_shutdown_handler;
1959         c->write->handler = ngx_ssl_shutdown_handler;
1960 
1961         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1962             return NGX_ERROR;
1963         }
1964 
1965         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1966             return NGX_ERROR;
1967         }
1968 
1969         if (sslerr == SSL_ERROR_WANT_READ) {
1970             ngx_add_timer(c->read, 30000);
1971         }
1972 
1973         return NGX_AGAIN;
1974     }
1975 
1976     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1977 
1978     ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1979 
1980     SSL_free(c->ssl->connection);
1981     c->ssl = NULL;
1982 
1983     return NGX_ERROR;
1984 }
1985 
1986 
1987 static void
1988 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1989 {
1990     ngx_connection_t           *c;
1991     ngx_connection_handler_pt   handler;
1992 
1993     c = ev->data;
1994     handler = c->ssl->handler;
1995 
1996     if (ev->timedout) {
1997         c->timedout = 1;
1998     }
1999 
2000     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
2001 
2002     if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
2003         return;
2004     }
2005 
2006     handler(c);
2007 }
2008 
2009 
2010 static void
2011 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
2012     char *text)
2013 {
2014     int         n;
2015     ngx_uint_t  level;
2016 
2017     level = NGX_LOG_CRIT;
2018 
2019     if (sslerr == SSL_ERROR_SYSCALL) {
2020 
2021         if (err == NGX_ECONNRESET
2022             || err == NGX_EPIPE
2023             || err == NGX_ENOTCONN
2024             || err == NGX_ETIMEDOUT
2025             || err == NGX_ECONNREFUSED
2026             || err == NGX_ENETDOWN
2027             || err == NGX_ENETUNREACH
2028             || err == NGX_EHOSTDOWN
2029             || err == NGX_EHOSTUNREACH)
2030         {
2031             switch (c->log_error) {
2032 
2033             case NGX_ERROR_IGNORE_ECONNRESET:
2034             case NGX_ERROR_INFO:
2035                 level = NGX_LOG_INFO;
2036                 break;
2037 
2038             case NGX_ERROR_ERR:
2039                 level = NGX_LOG_ERR;
2040                 break;
2041 
2042             default:
2043                 break;
2044             }
2045         }
2046 
2047     } else if (sslerr == SSL_ERROR_SSL) {
2048 
2049         n = ERR_GET_REASON(ERR_peek_error());
2050 
2051             /* handshake failures */
2052         if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC                        /*  103 */
2053             || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  /*  129 */
2054             || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
2055             || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              /*  151 */
2056             || n == SSL_R_EXCESSIVE_MESSAGE_SIZE                     /*  152 */
2057             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
2058 #ifdef SSL_R_NO_CIPHERS_PASSED
2059             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
2060 #endif
2061             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
2062             || n == SSL_R_NO_COMPRESSION_SPECIFIED                   /*  187 */
2063             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
2064             || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
2065 #ifdef SSL_R_PARSE_TLSEXT
2066             || n == SSL_R_PARSE_TLSEXT                               /*  227 */
2067 #endif
2068             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
2069             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
2070             || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
2071             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
2072             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
2073             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
2074 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
2075             || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG                   /*  335 */
2076             || n == SSL_R_RENEGOTIATION_ENCODING_ERR                 /*  336 */
2077             || n == SSL_R_RENEGOTIATION_MISMATCH                     /*  337 */
2078 #endif
2079 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
2080             || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED       /*  338 */
2081 #endif
2082 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
2083             || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING           /*  345 */
2084 #endif
2085 #ifdef SSL_R_INAPPROPRIATE_FALLBACK
2086             || n == SSL_R_INAPPROPRIATE_FALLBACK                     /*  373 */
2087 #endif
2088             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
2089 #ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE
2090             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
2091             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
2092             || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED              /* 1021 */
2093             || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW                /* 1022 */
2094             || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE          /* 1030 */
2095             || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE              /* 1040 */
2096             || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE                 /* 1041 */
2097             || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE                /* 1042 */
2098             || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE        /* 1043 */
2099             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED            /* 1044 */
2100             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED            /* 1045 */
2101             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN            /* 1046 */
2102             || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER              /* 1047 */
2103             || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA                     /* 1048 */
2104             || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED                  /* 1049 */
2105             || n == SSL_R_TLSV1_ALERT_DECODE_ERROR                   /* 1050 */
2106             || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR                  /* 1051 */
2107             || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION             /* 1060 */
2108             || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION               /* 1070 */
2109             || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY          /* 1071 */
2110             || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR                 /* 1080 */
2111             || n == SSL_R_TLSV1_ALERT_USER_CANCELLED                 /* 1090 */
2112             || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION               /* 1100 */
2113 #endif
2114             )
2115         {
2116             switch (c->log_error) {
2117 
2118             case NGX_ERROR_IGNORE_ECONNRESET:
2119             case NGX_ERROR_INFO:
2120                 level = NGX_LOG_INFO;
2121                 break;
2122 
2123             case NGX_ERROR_ERR:
2124                 level = NGX_LOG_ERR;
2125                 break;
2126 
2127             default:
2128                 break;
2129             }
2130         }
2131     }
2132 
2133     ngx_ssl_error(level, c->log, err, text);
2134 }
2135 
2136 
2137 static void
2138 ngx_ssl_clear_error(ngx_log_t *log)
2139 {
2140     while (ERR_peek_error()) {
2141         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
2142     }
2143 
2144     ERR_clear_error();
2145 }
2146 
2147 
2148 void ngx_cdecl
2149 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
2150 {
2151     int          flags;
2152     u_long       n;
2153     va_list      args;
2154     u_char      *p, *last;
2155     u_char       errstr[NGX_MAX_CONF_ERRSTR];
2156     const char  *data;
2157 
2158     last = errstr + NGX_MAX_CONF_ERRSTR;
2159 
2160     va_start(args, fmt);
2161     p = ngx_vslprintf(errstr, last - 1, fmt, args);
2162     va_end(args);
2163 
2164     p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
2165 
2166     for ( ;; ) {
2167 
2168         n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
2169 
2170         if (n == 0) {
2171             break;
2172         }
2173 
2174         /* ERR_error_string_n() requires at least one byte */
2175 
2176         if (p >= last - 1) {
2177             goto next;
2178         }
2179 
2180         *p++ = ' ';
2181 
2182         ERR_error_string_n(n, (char *) p, last - p);
2183 
2184         while (p < last && *p) {
2185             p++;
2186         }
2187 
2188         if (p < last && *data && (flags & ERR_TXT_STRING)) {
2189             *p++ = ':';
2190             p = ngx_cpystrn(p, (u_char *) data, last - p);
2191         }
2192 
2193     next:
2194 
2195         (void) ERR_get_error();
2196     }
2197 
2198     ngx_log_error(level, log, err, "%*s)", p - errstr, errstr);
2199 }
2200 
2201 
2202 ngx_int_t
2203 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
2204     ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
2205 {
2206     long  cache_mode;
2207 
2208     SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
2209 
2210     if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) {
2211         return NGX_ERROR;
2212     }
2213 
2214     if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
2215         SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
2216         return NGX_OK;
2217     }
2218 
2219     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
2220 
2221         /*
2222          * If the server explicitly says that it does not support
2223          * session reuse (see SSL_SESS_CACHE_OFF above), then
2224          * Outlook Express fails to upload a sent email to
2225          * the Sent Items folder on the IMAP server via a separate IMAP
2226          * connection in the background.  Therefore we have a special
2227          * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
2228          * where the server pretends that it supports session reuse,
2229          * but it does not actually store any session.
2230          */
2231 
2232         SSL_CTX_set_session_cache_mode(ssl->ctx,
2233                                        SSL_SESS_CACHE_SERVER
2234                                        |SSL_SESS_CACHE_NO_AUTO_CLEAR
2235                                        |SSL_SESS_CACHE_NO_INTERNAL_STORE);
2236 
2237         SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
2238 
2239         return NGX_OK;
2240     }
2241 
2242     cache_mode = SSL_SESS_CACHE_SERVER;
2243 
2244     if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
2245         cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
2246     }
2247 
2248     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
2249 
2250     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
2251 
2252         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
2253             SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
2254         }
2255     }
2256 
2257     if (shm_zone) {
2258         SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
2259         SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
2260         SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
2261 
2262         if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
2263             == 0)
2264         {
2265             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2266                           "SSL_CTX_set_ex_data() failed");
2267             return NGX_ERROR;
2268         }
2269     }
2270 
2271     return NGX_OK;
2272 }
2273 
2274 
2275 static ngx_int_t
2276 ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx)
2277 {
2278     int                   n, i;
2279     X509                 *cert;
2280     X509_NAME            *name;
2281     EVP_MD_CTX           *md;
2282     unsigned int          len;
2283     STACK_OF(X509_NAME)  *list;
2284     u_char                buf[EVP_MAX_MD_SIZE];
2285 
2286     /*
2287      * Session ID context is set based on the string provided,
2288      * the server certificates, and the client CA list.
2289      */
2290 
2291     md = EVP_MD_CTX_create();
2292     if (md == NULL) {
2293         return NGX_ERROR;
2294     }
2295 
2296     if (EVP_DigestInit_ex(md, EVP_sha1(), NULL) == 0) {
2297         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2298                       "EVP_DigestInit_ex() failed");
2299         goto failed;
2300     }
2301 
2302     if (EVP_DigestUpdate(md, sess_ctx->data, sess_ctx->len) == 0) {
2303         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2304                       "EVP_DigestUpdate() failed");
2305         goto failed;
2306     }
2307 
2308     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
2309          cert;
2310          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
2311     {
2312         if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
2313             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2314                           "X509_digest() failed");
2315             goto failed;
2316         }
2317 
2318         if (EVP_DigestUpdate(md, buf, len) == 0) {
2319             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2320                           "EVP_DigestUpdate() failed");
2321             goto failed;
2322         }
2323     }
2324 
2325     list = SSL_CTX_get_client_CA_list(ssl->ctx);
2326 
2327     if (list != NULL) {
2328         n = sk_X509_NAME_num(list);
2329 
2330         for (i = 0; i < n; i++) {
2331             name = sk_X509_NAME_value(list, i);
2332 
2333             if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) {
2334                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2335                               "X509_NAME_digest() failed");
2336                 goto failed;
2337             }
2338 
2339             if (EVP_DigestUpdate(md, buf, len) == 0) {
2340                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2341                               "EVP_DigestUpdate() failed");
2342                 goto failed;
2343             }
2344         }
2345     }
2346 
2347     if (EVP_DigestFinal_ex(md, buf, &len) == 0) {
2348         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2349                       "EVP_DigestUpdate() failed");
2350         goto failed;
2351     }
2352 
2353     EVP_MD_CTX_destroy(md);
2354 
2355     if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) {
2356         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2357                       "SSL_CTX_set_session_id_context() failed");
2358         return NGX_ERROR;
2359     }
2360 
2361     return NGX_OK;
2362 
2363 failed:
2364 
2365     EVP_MD_CTX_destroy(md);
2366 
2367     return NGX_ERROR;
2368 }
2369 
2370 
2371 ngx_int_t
2372 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2373 {
2374     size_t                    len;
2375     ngx_slab_pool_t          *shpool;
2376     ngx_ssl_session_cache_t  *cache;
2377 
2378     if (data) {
2379         shm_zone->data = data;
2380         return NGX_OK;
2381     }
2382 
2383     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2384 
2385     if (shm_zone->shm.exists) {
2386         shm_zone->data = shpool->data;
2387         return NGX_OK;
2388     }
2389 
2390     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
2391     if (cache == NULL) {
2392         return NGX_ERROR;
2393     }
2394 
2395     shpool->data = cache;
2396     shm_zone->data = cache;
2397 
2398     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
2399                     ngx_ssl_session_rbtree_insert_value);
2400 
2401     ngx_queue_init(&cache->expire_queue);
2402 
2403     len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
2404 
2405     shpool->log_ctx = ngx_slab_alloc(shpool, len);
2406     if (shpool->log_ctx == NULL) {
2407         return NGX_ERROR;
2408     }
2409 
2410     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
2411                 &shm_zone->shm.name);
2412 
2413     shpool->log_nomem = 0;
2414 
2415     return NGX_OK;
2416 }
2417 
2418 
2419 /*
2420  * The length of the session id is 16 bytes for SSLv2 sessions and
2421  * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
2422  * It seems that the typical length of the external ASN1 representation
2423  * of a session is 118 or 119 bytes for SSLv3/TSLv1.
2424  *
2425  * Thus on 32-bit platforms we allocate separately an rbtree node,
2426  * a session id, and an ASN1 representation, they take accordingly
2427  * 64, 32, and 128 bytes.
2428  *
2429  * On 64-bit platforms we allocate separately an rbtree node + session_id,
2430  * and an ASN1 representation, they take accordingly 128 and 128 bytes.
2431  *
2432  * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
2433  * so they are outside the code locked by shared pool mutex
2434  */
2435 
2436 static int
2437 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
2438 {
2439     int                       len;
2440     u_char                   *p, *id, *cached_sess, *session_id;
2441     uint32_t                  hash;
2442     SSL_CTX                  *ssl_ctx;
2443     unsigned int              session_id_length;
2444     ngx_shm_zone_t           *shm_zone;
2445     ngx_connection_t         *c;
2446     ngx_slab_pool_t          *shpool;
2447     ngx_ssl_sess_id_t        *sess_id;
2448     ngx_ssl_session_cache_t  *cache;
2449     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
2450 
2451     len = i2d_SSL_SESSION(sess, NULL);
2452 
2453     /* do not cache too big session */
2454 
2455     if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
2456         return 0;
2457     }
2458 
2459     p = buf;
2460     i2d_SSL_SESSION(sess, &p);
2461 
2462     c = ngx_ssl_get_connection(ssl_conn);
2463 
2464     ssl_ctx = c->ssl->session_ctx;
2465     shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
2466 
2467     cache = shm_zone->data;
2468     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2469 
2470     ngx_shmtx_lock(&shpool->mutex);
2471 
2472     /* drop one or two expired sessions */
2473     ngx_ssl_expire_sessions(cache, shpool, 1);
2474 
2475     cached_sess = ngx_slab_alloc_locked(shpool, len);
2476 
2477     if (cached_sess == NULL) {
2478 
2479         /* drop the oldest non-expired session and try once more */
2480 
2481         ngx_ssl_expire_sessions(cache, shpool, 0);
2482 
2483         cached_sess = ngx_slab_alloc_locked(shpool, len);
2484 
2485         if (cached_sess == NULL) {
2486             sess_id = NULL;
2487             goto failed;
2488         }
2489     }
2490 
2491     sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
2492 
2493     if (sess_id == NULL) {
2494 
2495         /* drop the oldest non-expired session and try once more */
2496 
2497         ngx_ssl_expire_sessions(cache, shpool, 0);
2498 
2499         sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
2500 
2501         if (sess_id == NULL) {
2502             goto failed;
2503         }
2504     }
2505 
2506 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
2507 
2508     session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
2509 
2510 #else
2511 
2512     session_id = sess->session_id;
2513     session_id_length = sess->session_id_length;
2514 
2515 #endif
2516 
2517 #if (NGX_PTR_SIZE == 8)
2518 
2519     id = sess_id->sess_id;
2520 
2521 #else
2522 
2523     id = ngx_slab_alloc_locked(shpool, session_id_length);
2524 
2525     if (id == NULL) {
2526 
2527         /* drop the oldest non-expired session and try once more */
2528 
2529         ngx_ssl_expire_sessions(cache, shpool, 0);
2530 
2531         id = ngx_slab_alloc_locked(shpool, session_id_length);
2532 
2533         if (id == NULL) {
2534             goto failed;
2535         }
2536     }
2537 
2538 #endif
2539 
2540     ngx_memcpy(cached_sess, buf, len);
2541 
2542     ngx_memcpy(id, session_id, session_id_length);
2543 
2544     hash = ngx_crc32_short(session_id, session_id_length);
2545 
2546     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
2547                    "ssl new session: %08XD:%ud:%d",
2548                    hash, session_id_length, len);
2549 
2550     sess_id->node.key = hash;
2551     sess_id->node.data = (u_char) session_id_length;
2552     sess_id->id = id;
2553     sess_id->len = len;
2554     sess_id->session = cached_sess;
2555 
2556     sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
2557 
2558     ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
2559 
2560     ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
2561 
2562     ngx_shmtx_unlock(&shpool->mutex);
2563 
2564     return 0;
2565 
2566 failed:
2567 
2568     if (cached_sess) {
2569         ngx_slab_free_locked(shpool, cached_sess);
2570     }
2571 
2572     if (sess_id) {
2573         ngx_slab_free_locked(shpool, sess_id);
2574     }
2575 
2576     ngx_shmtx_unlock(&shpool->mutex);
2577 
2578     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2579                   "could not allocate new session%s", shpool->log_ctx);
2580 
2581     return 0;
2582 }
2583 
2584 
2585 static ngx_ssl_session_t *
2586 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
2587 #if OPENSSL_VERSION_NUMBER >= 0x10100003L
2588     const
2589 #endif
2590     u_char *id, int len, int *copy)
2591 {
2592 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
2593     const
2594 #endif
2595     u_char                   *p;
2596     uint32_t                  hash;
2597     ngx_int_t                 rc;
2598     ngx_shm_zone_t           *shm_zone;
2599     ngx_slab_pool_t          *shpool;
2600     ngx_rbtree_node_t        *node, *sentinel;
2601     ngx_ssl_session_t        *sess;
2602     ngx_ssl_sess_id_t        *sess_id;
2603     ngx_ssl_session_cache_t  *cache;
2604     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
2605     ngx_connection_t         *c;
2606 
2607     hash = ngx_crc32_short((u_char *) (uintptr_t) id, (size_t) len);
2608     *copy = 0;
2609 
2610     c = ngx_ssl_get_connection(ssl_conn);
2611 
2612     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2613                    "ssl get session: %08XD:%d", hash, len);
2614 
2615     shm_zone = SSL_CTX_get_ex_data(c->ssl->session_ctx,
2616                                    ngx_ssl_session_cache_index);
2617 
2618     cache = shm_zone->data;
2619 
2620     sess = NULL;
2621 
2622     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2623 
2624     ngx_shmtx_lock(&shpool->mutex);
2625 
2626     node = cache->session_rbtree.root;
2627     sentinel = cache->session_rbtree.sentinel;
2628 
2629     while (node != sentinel) {
2630 
2631         if (hash < node->key) {
2632             node = node->left;
2633             continue;
2634         }
2635 
2636         if (hash > node->key) {
2637             node = node->right;
2638             continue;
2639         }
2640 
2641         /* hash == node->key */
2642 
2643         sess_id = (ngx_ssl_sess_id_t *) node;
2644 
2645         rc = ngx_memn2cmp((u_char *) (uintptr_t) id, sess_id->id,
2646                           (size_t) len, (size_t) node->data);
2647 
2648         if (rc == 0) {
2649 
2650             if (sess_id->expire > ngx_time()) {
2651                 ngx_memcpy(buf, sess_id->session, sess_id->len);
2652 
2653                 ngx_shmtx_unlock(&shpool->mutex);
2654 
2655                 p = buf;
2656                 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
2657 
2658                 return sess;
2659             }
2660 
2661             ngx_queue_remove(&sess_id->queue);
2662 
2663             ngx_rbtree_delete(&cache->session_rbtree, node);
2664 
2665             ngx_slab_free_locked(shpool, sess_id->session);
2666 #if (NGX_PTR_SIZE == 4)
2667             ngx_slab_free_locked(shpool, sess_id->id);
2668 #endif
2669             ngx_slab_free_locked(shpool, sess_id);
2670 
2671             sess = NULL;
2672 
2673             goto done;
2674         }
2675 
2676         node = (rc < 0) ? node->left : node->right;
2677     }
2678 
2679 done:
2680 
2681     ngx_shmtx_unlock(&shpool->mutex);
2682 
2683     return sess;
2684 }
2685 
2686 
2687 void
2688 ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
2689 {
2690     SSL_CTX_remove_session(ssl, sess);
2691 
2692     ngx_ssl_remove_session(ssl, sess);
2693 }
2694 
2695 
2696 static void
2697 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
2698 {
2699     u_char                   *id;
2700     uint32_t                  hash;
2701     ngx_int_t                 rc;
2702     unsigned int              len;
2703     ngx_shm_zone_t           *shm_zone;
2704     ngx_slab_pool_t          *shpool;
2705     ngx_rbtree_node_t        *node, *sentinel;
2706     ngx_ssl_sess_id_t        *sess_id;
2707     ngx_ssl_session_cache_t  *cache;
2708 
2709     shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
2710 
2711     if (shm_zone == NULL) {
2712         return;
2713     }
2714 
2715     cache = shm_zone->data;
2716 
2717 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
2718 
2719     id = (u_char *) SSL_SESSION_get_id(sess, &len);
2720 
2721 #else
2722 
2723     id = sess->session_id;
2724     len = sess->session_id_length;
2725 
2726 #endif
2727 
2728     hash = ngx_crc32_short(id, len);
2729 
2730     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
2731                    "ssl remove session: %08XD:%ud", hash, len);
2732 
2733     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2734 
2735     ngx_shmtx_lock(&shpool->mutex);
2736 
2737     node = cache->session_rbtree.root;
2738     sentinel = cache->session_rbtree.sentinel;
2739 
2740     while (node != sentinel) {
2741 
2742         if (hash < node->key) {
2743             node = node->left;
2744             continue;
2745         }
2746 
2747         if (hash > node->key) {
2748             node = node->right;
2749             continue;
2750         }
2751 
2752         /* hash == node->key */
2753 
2754         sess_id = (ngx_ssl_sess_id_t *) node;
2755 
2756         rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
2757 
2758         if (rc == 0) {
2759 
2760             ngx_queue_remove(&sess_id->queue);
2761 
2762             ngx_rbtree_delete(&cache->session_rbtree, node);
2763 
2764             ngx_slab_free_locked(shpool, sess_id->session);
2765 #if (NGX_PTR_SIZE == 4)
2766             ngx_slab_free_locked(shpool, sess_id->id);
2767 #endif
2768             ngx_slab_free_locked(shpool, sess_id);
2769 
2770             goto done;
2771         }
2772 
2773         node = (rc < 0) ? node->left : node->right;
2774     }
2775 
2776 done:
2777 
2778     ngx_shmtx_unlock(&shpool->mutex);
2779 }
2780 
2781 
2782 static void
2783 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
2784     ngx_slab_pool_t *shpool, ngx_uint_t n)
2785 {
2786     time_t              now;
2787     ngx_queue_t        *q;
2788     ngx_ssl_sess_id_t  *sess_id;
2789 
2790     now = ngx_time();
2791 
2792     while (n < 3) {
2793 
2794         if (ngx_queue_empty(&cache->expire_queue)) {
2795             return;
2796         }
2797 
2798         q = ngx_queue_last(&cache->expire_queue);
2799 
2800         sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
2801 
2802         if (n++ != 0 && sess_id->expire > now) {
2803             return;
2804         }
2805 
2806         ngx_queue_remove(q);
2807 
2808         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
2809                        "expire session: %08Xi", sess_id->node.key);
2810 
2811         ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
2812 
2813         ngx_slab_free_locked(shpool, sess_id->session);
2814 #if (NGX_PTR_SIZE == 4)
2815         ngx_slab_free_locked(shpool, sess_id->id);
2816 #endif
2817         ngx_slab_free_locked(shpool, sess_id);
2818     }
2819 }
2820 
2821 
2822 static void
2823 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
2824     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
2825 {
2826     ngx_rbtree_node_t  **p;
2827     ngx_ssl_sess_id_t   *sess_id, *sess_id_temp;
2828 
2829     for ( ;; ) {
2830 
2831         if (node->key < temp->key) {
2832 
2833             p = &temp->left;
2834 
2835         } else if (node->key > temp->key) {
2836 
2837             p = &temp->right;
2838 
2839         } else { /* node->key == temp->key */
2840 
2841             sess_id = (ngx_ssl_sess_id_t *) node;
2842             sess_id_temp = (ngx_ssl_sess_id_t *) temp;
2843 
2844             p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
2845                               (size_t) node->data, (size_t) temp->data)
2846                  < 0) ? &temp->left : &temp->right;
2847         }
2848 
2849         if (*p == sentinel) {
2850             break;
2851         }
2852 
2853         temp = *p;
2854     }
2855 
2856     *p = node;
2857     node->parent = temp;
2858     node->left = sentinel;
2859     node->right = sentinel;
2860     ngx_rbt_red(node);
2861 }
2862 
2863 
2864 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
2865 
2866 ngx_int_t
2867 ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
2868 {
2869     u_char                         buf[80];
2870     size_t                         size;
2871     ssize_t                        n;
2872     ngx_str_t                     *path;
2873     ngx_file_t                     file;
2874     ngx_uint_t                     i;
2875     ngx_array_t                   *keys;
2876     ngx_file_info_t                fi;
2877     ngx_ssl_session_ticket_key_t  *key;
2878 
2879     if (paths == NULL) {
2880         return NGX_OK;
2881     }
2882 
2883     keys = ngx_array_create(cf->pool, paths->nelts,
2884                             sizeof(ngx_ssl_session_ticket_key_t));
2885     if (keys == NULL) {
2886         return NGX_ERROR;
2887     }
2888 
2889     path = paths->elts;
2890     for (i = 0; i < paths->nelts; i++) {
2891 
2892         if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) {
2893             return NGX_ERROR;
2894         }
2895 
2896         ngx_memzero(&file, sizeof(ngx_file_t));
2897         file.name = path[i];
2898         file.log = cf->log;
2899 
2900         file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0);
2901         if (file.fd == NGX_INVALID_FILE) {
2902             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
2903                                ngx_open_file_n " \"%V\" failed", &file.name);
2904             return NGX_ERROR;
2905         }
2906 
2907         if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
2908             ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
2909                                ngx_fd_info_n " \"%V\" failed", &file.name);
2910             goto failed;
2911         }
2912 
2913         size = ngx_file_size(&fi);
2914 
2915         if (size != 48 && size != 80) {
2916             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2917                                "\"%V\" must be 48 or 80 bytes", &file.name);
2918             goto failed;
2919         }
2920 
2921         n = ngx_read_file(&file, buf, size, 0);
2922 
2923         if (n == NGX_ERROR) {
2924             ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
2925                                ngx_read_file_n " \"%V\" failed", &file.name);
2926             goto failed;
2927         }
2928 
2929         if ((size_t) n != size) {
2930             ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
2931                                ngx_read_file_n " \"%V\" returned only "
2932                                "%z bytes instead of %uz", &file.name, n, size);
2933             goto failed;
2934         }
2935 
2936         key = ngx_array_push(keys);
2937         if (key == NULL) {
2938             goto failed;
2939         }
2940 
2941         if (size == 48) {
2942             key->size = 48;
2943             ngx_memcpy(key->name, buf, 16);
2944             ngx_memcpy(key->aes_key, buf + 16, 16);
2945             ngx_memcpy(key->hmac_key, buf + 32, 16);
2946 
2947         } else {
2948             key->size = 80;
2949             ngx_memcpy(key->name, buf, 16);
2950             ngx_memcpy(key->hmac_key, buf + 16, 32);
2951             ngx_memcpy(key->aes_key, buf + 48, 32);
2952         }
2953 
2954         if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
2955             ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
2956                           ngx_close_file_n " \"%V\" failed", &file.name);
2957         }
2958     }
2959 
2960     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
2961         == 0)
2962     {
2963         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2964                       "SSL_CTX_set_ex_data() failed");
2965         return NGX_ERROR;
2966     }
2967 
2968     if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
2969                                          ngx_ssl_session_ticket_key_callback)
2970         == 0)
2971     {
2972         ngx_log_error(NGX_LOG_WARN, cf->log, 0,
2973                       "nginx was built with Session Tickets support, however, "
2974                       "now it is linked dynamically to an OpenSSL library "
2975                       "which has no tlsext support, therefore Session Tickets "
2976                       "are not available");
2977     }
2978 
2979     return NGX_OK;
2980 
2981 failed:
2982 
2983     if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
2984         ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
2985                       ngx_close_file_n " \"%V\" failed", &file.name);
2986     }
2987 
2988     return NGX_ERROR;
2989 }
2990 
2991 
2992 static int
2993 ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
2994     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
2995     HMAC_CTX *hctx, int enc)
2996 {
2997     size_t                         size;
2998     SSL_CTX                       *ssl_ctx;
2999     ngx_uint_t                     i;
3000     ngx_array_t                   *keys;
3001     ngx_connection_t              *c;
3002     ngx_ssl_session_ticket_key_t  *key;
3003     const EVP_MD                  *digest;
3004     const EVP_CIPHER              *cipher;
3005 #if (NGX_DEBUG)
3006     u_char                         buf[32];
3007 #endif
3008 
3009     c = ngx_ssl_get_connection(ssl_conn);
3010     ssl_ctx = c->ssl->session_ctx;
3011 
3012 #ifdef OPENSSL_NO_SHA256
3013     digest = EVP_sha1();
3014 #else
3015     digest = EVP_sha256();
3016 #endif
3017 
3018     keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
3019     if (keys == NULL) {
3020         return -1;
3021     }
3022 
3023     key = keys->elts;
3024 
3025     if (enc == 1) {
3026         /* encrypt session ticket */
3027 
3028         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
3029                        "ssl session ticket encrypt, key: \"%*s\" (%s session)",
3030                        ngx_hex_dump(buf, key[0].name, 16) - buf, buf,
3031                        SSL_session_reused(ssl_conn) ? "reused" : "new");
3032 
3033         if (key[0].size == 48) {
3034             cipher = EVP_aes_128_cbc();
3035             size = 16;
3036 
3037         } else {
3038             cipher = EVP_aes_256_cbc();
3039             size = 32;
3040         }
3041 
3042         if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) {
3043             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "RAND_bytes() failed");
3044             return -1;
3045         }
3046 
3047         if (EVP_EncryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1) {
3048             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
3049                           "EVP_EncryptInit_ex() failed");
3050             return -1;
3051         }
3052 
3053 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
3054         if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) {
3055             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed");
3056             return -1;
3057         }
3058 #else
3059         HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL);
3060 #endif
3061 
3062         ngx_memcpy(name, key[0].name, 16);
3063 
3064         return 1;
3065 
3066     } else {
3067         /* decrypt session ticket */
3068 
3069         for (i = 0; i < keys->nelts; i++) {
3070             if (ngx_memcmp(name, key[i].name, 16) == 0) {
3071                 goto found;
3072             }
3073         }
3074 
3075         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3076                        "ssl session ticket decrypt, key: \"%*s\" not found",
3077                        ngx_hex_dump(buf, name, 16) - buf, buf);
3078 
3079         return 0;
3080 
3081     found:
3082 
3083         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
3084                        "ssl session ticket decrypt, key: \"%*s\"%s",
3085                        ngx_hex_dump(buf, key[i].name, 16) - buf, buf,
3086                        (i == 0) ? " (default)" : "");
3087 
3088         if (key[i].size == 48) {
3089             cipher = EVP_aes_128_cbc();
3090             size = 16;
3091 
3092         } else {
3093             cipher = EVP_aes_256_cbc();
3094             size = 32;
3095         }
3096 
3097 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
3098         if (HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL) != 1) {
3099             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed");
3100             return -1;
3101         }
3102 #else
3103         HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL);
3104 #endif
3105 
3106         if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[i].aes_key, iv) != 1) {
3107             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
3108                           "EVP_DecryptInit_ex() failed");
3109             return -1;
3110         }
3111 
3112         return (i == 0) ? 1 : 2 /* renew */;
3113     }
3114 }
3115 
3116 #else
3117 
3118 ngx_int_t
3119 ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
3120 {
3121     if (paths) {
3122         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
3123                       "\"ssl_session_ticket_keys\" ignored, not supported");
3124     }
3125 
3126     return NGX_OK;
3127 }
3128 
3129 #endif
3130 
3131 
3132 void
3133 ngx_ssl_cleanup_ctx(void *data)
3134 {
3135     ngx_ssl_t  *ssl = data;
3136 
3137     X509  *cert, *next;
3138 
3139     cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
3140 
3141     while (cert) {
3142         next = X509_get_ex_data(cert, ngx_ssl_next_certificate_index);
3143         X509_free(cert);
3144         cert = next;
3145     }
3146 
3147     SSL_CTX_free(ssl->ctx);
3148 }
3149 
3150 
3151 ngx_int_t
3152 ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name)
3153 {
3154     X509   *cert;
3155 
3156     cert = SSL_get_peer_certificate(c->ssl->connection);
3157     if (cert == NULL) {
3158         return NGX_ERROR;
3159     }
3160 
3161 #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
3162 
3163     /* X509_check_host() is only available in OpenSSL 1.0.2+ */
3164 
3165     if (name->len == 0) {
3166         goto failed;
3167     }
3168 
3169     if (X509_check_host(cert, (char *) name->data, name->len, 0, NULL) != 1) {
3170         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3171                        "X509_check_host(): no match");
3172         goto failed;
3173     }
3174 
3175     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3176                    "X509_check_host(): match");
3177 
3178     goto found;
3179 
3180 #else
3181     {
3182     int                      n, i;
3183     X509_NAME               *sname;
3184     ASN1_STRING             *str;
3185     X509_NAME_ENTRY         *entry;
3186     GENERAL_NAME            *altname;
3187     STACK_OF(GENERAL_NAME)  *altnames;
3188 
3189     /*
3190      * As per RFC6125 and RFC2818, we check subjectAltName extension,
3191      * and if it's not present - commonName in Subject is checked.
3192      */
3193 
3194     altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
3195 
3196     if (altnames) {
3197         n = sk_GENERAL_NAME_num(altnames);
3198 
3199         for (i = 0; i < n; i++) {
3200             altname = sk_GENERAL_NAME_value(altnames, i);
3201 
3202             if (altname->type != GEN_DNS) {
3203                 continue;
3204             }
3205 
3206             str = altname->d.dNSName;
3207 
3208             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3209                            "SSL subjectAltName: \"%*s\"",
3210                            ASN1_STRING_length(str), ASN1_STRING_data(str));
3211 
3212             if (ngx_ssl_check_name(name, str) == NGX_OK) {
3213                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3214                                "SSL subjectAltName: match");
3215                 GENERAL_NAMES_free(altnames);
3216                 goto found;
3217             }
3218         }
3219 
3220         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3221                        "SSL subjectAltName: no match");
3222 
3223         GENERAL_NAMES_free(altnames);
3224         goto failed;
3225     }
3226 
3227     /*
3228      * If there is no subjectAltName extension, check commonName
3229      * in Subject.  While RFC2818 requires to only check "most specific"
3230      * CN, both Apache and OpenSSL check all CNs, and so do we.
3231      */
3232 
3233     sname = X509_get_subject_name(cert);
3234 
3235     if (sname == NULL) {
3236         goto failed;
3237     }
3238 
3239     i = -1;
3240     for ( ;; ) {
3241         i = X509_NAME_get_index_by_NID(sname, NID_commonName, i);
3242 
3243         if (i < 0) {
3244             break;
3245         }
3246 
3247         entry = X509_NAME_get_entry(sname, i);
3248         str = X509_NAME_ENTRY_get_data(entry);
3249 
3250         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3251                        "SSL commonName: \"%*s\"",
3252                        ASN1_STRING_length(str), ASN1_STRING_data(str));
3253 
3254         if (ngx_ssl_check_name(name, str) == NGX_OK) {
3255             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3256                            "SSL commonName: match");
3257             goto found;
3258         }
3259     }
3260 
3261     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3262                    "SSL commonName: no match");
3263     }
3264 #endif
3265 
3266 failed:
3267 
3268     X509_free(cert);
3269     return NGX_ERROR;
3270 
3271 found:
3272 
3273     X509_free(cert);
3274     return NGX_OK;
3275 }
3276 
3277 
3278 #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
3279 
3280 static ngx_int_t
3281 ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *pattern)
3282 {
3283     u_char  *s, *p, *end;
3284     size_t   slen, plen;
3285 
3286     s = name->data;
3287     slen = name->len;
3288 
3289     p = ASN1_STRING_data(pattern);
3290     plen = ASN1_STRING_length(pattern);
3291 
3292     if (slen == plen && ngx_strncasecmp(s, p, plen) == 0) {
3293         return NGX_OK;
3294     }
3295 
3296     if (plen > 2 && p[0] == '*' && p[1] == '.') {
3297         plen -= 1;
3298         p += 1;
3299 
3300         end = s + slen;
3301         s = ngx_strlchr(s, end, '.');
3302 
3303         if (s == NULL) {
3304             return NGX_ERROR;
3305         }
3306 
3307         slen = end - s;
3308 
3309         if (plen == slen && ngx_strncasecmp(s, p, plen) == 0) {
3310             return NGX_OK;
3311         }
3312     }
3313 
3314     return NGX_ERROR;
3315 }
3316 
3317 #endif
3318 
3319 
3320 ngx_int_t
3321 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3322 {
3323     s->data = (u_char *) SSL_get_version(c->ssl->connection);
3324     return NGX_OK;
3325 }
3326 
3327 
3328 ngx_int_t
3329 ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3330 {
3331     s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
3332     return NGX_OK;
3333 }
3334 
3335 
3336 ngx_int_t
3337 ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3338 {
3339 #ifdef SSL_CTRL_GET_RAW_CIPHERLIST
3340 
3341     int                n, i, bytes;
3342     size_t             len;
3343     u_char            *ciphers, *p;
3344     const SSL_CIPHER  *cipher;
3345 
3346     bytes = SSL_get0_raw_cipherlist(c->ssl->connection, NULL);
3347     n = SSL_get0_raw_cipherlist(c->ssl->connection, &ciphers);
3348 
3349     if (n <= 0) {
3350         s->len = 0;
3351         return NGX_OK;
3352     }
3353 
3354     len = 0;
3355     n /= bytes;
3356 
3357     for (i = 0; i < n; i++) {
3358         cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes);
3359 
3360         if (cipher) {
3361             len += ngx_strlen(SSL_CIPHER_get_name(cipher));
3362 
3363         } else {
3364             len += sizeof("0x") - 1 + bytes * (sizeof("00") - 1);
3365         }
3366 
3367         len += sizeof(":") - 1;
3368     }
3369 
3370     s->data = ngx_pnalloc(pool, len);
3371     if (s->data == NULL) {
3372         return NGX_ERROR;
3373     }
3374 
3375     p = s->data;
3376 
3377     for (i = 0; i < n; i++) {
3378         cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes);
3379 
3380         if (cipher) {
3381             p = ngx_sprintf(p, "%s", SSL_CIPHER_get_name(cipher));
3382 
3383         } else {
3384             p = ngx_sprintf(p, "0x");
3385             p = ngx_hex_dump(p, ciphers + i * bytes, bytes);
3386         }
3387 
3388         *p++ = ':';
3389     }
3390 
3391     p--;
3392 
3393     s->len = p - s->data;
3394 
3395 #else
3396 
3397     u_char  buf[4096];
3398 
3399     if (SSL_get_shared_ciphers(c->ssl->connection, (char *) buf, 4096)
3400         == NULL)
3401     {
3402         s->len = 0;
3403         return NGX_OK;
3404     }
3405 
3406     s->len = ngx_strlen(buf);
3407     s->data = ngx_pnalloc(pool, s->len);
3408     if (s->data == NULL) {
3409         return NGX_ERROR;
3410     }
3411 
3412     ngx_memcpy(s->data, buf, s->len);
3413 
3414 #endif
3415 
3416     return NGX_OK;
3417 }
3418 
3419 
3420 ngx_int_t
3421 ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3422 {
3423 #ifdef SSL_CTRL_GET_CURVES
3424 
3425     int         *curves, n, i, nid;
3426     u_char      *p;
3427     size_t       len;
3428 
3429     n = SSL_get1_curves(c->ssl->connection, NULL);
3430 
3431     if (n <= 0) {
3432         s->len = 0;
3433         return NGX_OK;
3434     }
3435 
3436     curves = ngx_palloc(pool, n * sizeof(int));
3437 
3438     n = SSL_get1_curves(c->ssl->connection, curves);
3439     len = 0;
3440 
3441     for (i = 0; i < n; i++) {
3442         nid = curves[i];
3443 
3444         if (nid & TLSEXT_nid_unknown) {
3445             len += sizeof("0x0000") - 1;
3446 
3447         } else {
3448             len += ngx_strlen(OBJ_nid2sn(nid));
3449         }
3450 
3451         len += sizeof(":") - 1;
3452     }
3453 
3454     s->data = ngx_pnalloc(pool, len);
3455     if (s->data == NULL) {
3456         return NGX_ERROR;
3457     }
3458 
3459     p = s->data;
3460 
3461     for (i = 0; i < n; i++) {
3462         nid = curves[i];
3463 
3464         if (nid & TLSEXT_nid_unknown) {
3465             p = ngx_sprintf(p, "0x%04xd", nid & 0xffff);
3466 
3467         } else {
3468             p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid));
3469         }
3470 
3471         *p++ = ':';
3472     }
3473 
3474     p--;
3475 
3476     s->len = p - s->data;
3477 
3478 #else
3479 
3480     s->len = 0;
3481 
3482 #endif
3483 
3484     return NGX_OK;
3485 }
3486 
3487 
3488 ngx_int_t
3489 ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3490 {
3491     u_char        *buf;
3492     SSL_SESSION   *sess;
3493     unsigned int   len;
3494 
3495     sess = SSL_get0_session(c->ssl->connection);
3496     if (sess == NULL) {
3497         s->len = 0;
3498         return NGX_OK;
3499     }
3500 
3501 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
3502 
3503     buf = (u_char *) SSL_SESSION_get_id(sess, &len);
3504 
3505 #else
3506 
3507     buf = sess->session_id;
3508     len = sess->session_id_length;
3509 
3510 #endif
3511 
3512     s->len = 2 * len;
3513     s->data = ngx_pnalloc(pool, 2 * len);
3514     if (s->data == NULL) {
3515         return NGX_ERROR;
3516     }
3517 
3518     ngx_hex_dump(s->data, buf, len);
3519 
3520     return NGX_OK;
3521 }
3522 
3523 
3524 ngx_int_t
3525 ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3526 {
3527     if (SSL_session_reused(c->ssl->connection)) {
3528         ngx_str_set(s, "r");
3529 
3530     } else {
3531         ngx_str_set(s, ".");
3532     }
3533 
3534     return NGX_OK;
3535 }
3536 
3537 
3538 ngx_int_t
3539 ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3540 {
3541 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3542 
3543     const char  *servername;
3544 
3545     servername = SSL_get_servername(c->ssl->connection,
3546                                     TLSEXT_NAMETYPE_host_name);
3547     if (servername) {
3548         s->data = (u_char *) servername;
3549         s->len = ngx_strlen(servername);
3550         return NGX_OK;
3551     }
3552 
3553 #endif
3554 
3555     s->len = 0;
3556     return NGX_OK;
3557 }
3558 
3559 
3560 ngx_int_t
3561 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3562 {
3563     size_t   len;
3564     BIO     *bio;
3565     X509    *cert;
3566 
3567     s->len = 0;
3568 
3569     cert = SSL_get_peer_certificate(c->ssl->connection);
3570     if (cert == NULL) {
3571         return NGX_OK;
3572     }
3573 
3574     bio = BIO_new(BIO_s_mem());
3575     if (bio == NULL) {
3576         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
3577         X509_free(cert);
3578         return NGX_ERROR;
3579     }
3580 
3581     if (PEM_write_bio_X509(bio, cert) == 0) {
3582         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
3583         goto failed;
3584     }
3585 
3586     len = BIO_pending(bio);
3587     s->len = len;
3588 
3589     s->data = ngx_pnalloc(pool, len);
3590     if (s->data == NULL) {
3591         goto failed;
3592     }
3593 
3594     BIO_read(bio, s->data, len);
3595 
3596     BIO_free(bio);
3597     X509_free(cert);
3598 
3599     return NGX_OK;
3600 
3601 failed:
3602 
3603     BIO_free(bio);
3604     X509_free(cert);
3605 
3606     return NGX_ERROR;
3607 }
3608 
3609 
3610 ngx_int_t
3611 ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3612 {
3613     u_char      *p;
3614     size_t       len;
3615     ngx_uint_t   i;
3616     ngx_str_t    cert;
3617 
3618     if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
3619         return NGX_ERROR;
3620     }
3621 
3622     if (cert.len == 0) {
3623         s->len = 0;
3624         return NGX_OK;
3625     }
3626 
3627     len = cert.len - 1;
3628 
3629     for (i = 0; i < cert.len - 1; i++) {
3630         if (cert.data[i] == LF) {
3631             len++;
3632         }
3633     }
3634 
3635     s->len = len;
3636     s->data = ngx_pnalloc(pool, len);
3637     if (s->data == NULL) {
3638         return NGX_ERROR;
3639     }
3640 
3641     p = s->data;
3642 
3643     for (i = 0; i < cert.len - 1; i++) {
3644         *p++ = cert.data[i];
3645         if (cert.data[i] == LF) {
3646             *p++ = '\t';
3647         }
3648     }
3649 
3650     return NGX_OK;
3651 }
3652 
3653 
3654 ngx_int_t
3655 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3656 {
3657     BIO        *bio;
3658     X509       *cert;
3659     X509_NAME  *name;
3660 
3661     s->len = 0;
3662 
3663     cert = SSL_get_peer_certificate(c->ssl->connection);
3664     if (cert == NULL) {
3665         return NGX_OK;
3666     }
3667 
3668     name = X509_get_subject_name(cert);
3669     if (name == NULL) {
3670         return NGX_ERROR;
3671     }
3672 
3673     bio = BIO_new(BIO_s_mem());
3674     if (bio == NULL) {
3675         X509_free(cert);
3676         return NGX_ERROR;
3677     }
3678 
3679     if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) {
3680         goto failed;
3681     }
3682 
3683     s->len = BIO_pending(bio);
3684     s->data = ngx_pnalloc(pool, s->len);
3685     if (s->data == NULL) {
3686         goto failed;
3687     }
3688 
3689     BIO_read(bio, s->data, s->len);
3690 
3691     BIO_free(bio);
3692     X509_free(cert);
3693 
3694     return NGX_OK;
3695 
3696 failed:
3697 
3698     BIO_free(bio);
3699     X509_free(cert);
3700 
3701     return NGX_ERROR;
3702 }
3703 
3704 
3705 ngx_int_t
3706 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3707 {
3708     BIO        *bio;
3709     X509       *cert;
3710     X509_NAME  *name;
3711 
3712     s->len = 0;
3713 
3714     cert = SSL_get_peer_certificate(c->ssl->connection);
3715     if (cert == NULL) {
3716         return NGX_OK;
3717     }
3718 
3719     name = X509_get_issuer_name(cert);
3720     if (name == NULL) {
3721         return NGX_ERROR;
3722     }
3723 
3724     bio = BIO_new(BIO_s_mem());
3725     if (bio == NULL) {
3726         X509_free(cert);
3727         return NGX_ERROR;
3728     }
3729 
3730     if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) {
3731         goto failed;
3732     }
3733 
3734     s->len = BIO_pending(bio);
3735     s->data = ngx_pnalloc(pool, s->len);
3736     if (s->data == NULL) {
3737         goto failed;
3738     }
3739 
3740     BIO_read(bio, s->data, s->len);
3741 
3742     BIO_free(bio);
3743     X509_free(cert);
3744 
3745     return NGX_OK;
3746 
3747 failed:
3748 
3749     BIO_free(bio);
3750     X509_free(cert);
3751 
3752     return NGX_ERROR;
3753 }
3754 
3755 
3756 ngx_int_t
3757 ngx_ssl_get_subject_dn_legacy(ngx_connection_t *c, ngx_pool_t *pool,
3758     ngx_str_t *s)
3759 {
3760     char       *p;
3761     size_t      len;
3762     X509       *cert;
3763     X509_NAME  *name;
3764 
3765     s->len = 0;
3766 
3767     cert = SSL_get_peer_certificate(c->ssl->connection);
3768     if (cert == NULL) {
3769         return NGX_OK;
3770     }
3771 
3772     name = X509_get_subject_name(cert);
3773     if (name == NULL) {
3774         X509_free(cert);
3775         return NGX_ERROR;
3776     }
3777 
3778     p = X509_NAME_oneline(name, NULL, 0);
3779 
3780     for (len = 0; p[len]; len++) { /* void */ }
3781 
3782     s->len = len;
3783     s->data = ngx_pnalloc(pool, len);
3784     if (s->data == NULL) {
3785         OPENSSL_free(p);
3786         X509_free(cert);
3787         return NGX_ERROR;
3788     }
3789 
3790     ngx_memcpy(s->data, p, len);
3791 
3792     OPENSSL_free(p);
3793     X509_free(cert);
3794 
3795     return NGX_OK;
3796 }
3797 
3798 
3799 ngx_int_t
3800 ngx_ssl_get_issuer_dn_legacy(ngx_connection_t *c, ngx_pool_t *pool,
3801     ngx_str_t *s)
3802 {
3803     char       *p;
3804     size_t      len;
3805     X509       *cert;
3806     X509_NAME  *name;
3807 
3808     s->len = 0;
3809 
3810     cert = SSL_get_peer_certificate(c->ssl->connection);
3811     if (cert == NULL) {
3812         return NGX_OK;
3813     }
3814 
3815     name = X509_get_issuer_name(cert);
3816     if (name == NULL) {
3817         X509_free(cert);
3818         return NGX_ERROR;
3819     }
3820 
3821     p = X509_NAME_oneline(name, NULL, 0);
3822 
3823     for (len = 0; p[len]; len++) { /* void */ }
3824 
3825     s->len = len;
3826     s->data = ngx_pnalloc(pool, len);
3827     if (s->data == NULL) {
3828         OPENSSL_free(p);
3829         X509_free(cert);
3830         return NGX_ERROR;
3831     }
3832 
3833     ngx_memcpy(s->data, p, len);
3834 
3835     OPENSSL_free(p);
3836     X509_free(cert);
3837 
3838     return NGX_OK;
3839 }
3840 
3841 
3842 ngx_int_t
3843 ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3844 {
3845     size_t   len;
3846     X509    *cert;
3847     BIO     *bio;
3848 
3849     s->len = 0;
3850 
3851     cert = SSL_get_peer_certificate(c->ssl->connection);
3852     if (cert == NULL) {
3853         return NGX_OK;
3854     }
3855 
3856     bio = BIO_new(BIO_s_mem());
3857     if (bio == NULL) {
3858         X509_free(cert);
3859         return NGX_ERROR;
3860     }
3861 
3862     i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
3863     len = BIO_pending(bio);
3864 
3865     s->len = len;
3866     s->data = ngx_pnalloc(pool, len);
3867     if (s->data == NULL) {
3868         BIO_free(bio);
3869         X509_free(cert);
3870         return NGX_ERROR;
3871     }
3872 
3873     BIO_read(bio, s->data, len);
3874     BIO_free(bio);
3875     X509_free(cert);
3876 
3877     return NGX_OK;
3878 }
3879 
3880 
3881 ngx_int_t
3882 ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3883 {
3884     X509          *cert;
3885     unsigned int   len;
3886     u_char         buf[EVP_MAX_MD_SIZE];
3887 
3888     s->len = 0;
3889 
3890     cert = SSL_get_peer_certificate(c->ssl->connection);
3891     if (cert == NULL) {
3892         return NGX_OK;
3893     }
3894 
3895     if (!X509_digest(cert, EVP_sha1(), buf, &len)) {
3896         X509_free(cert);
3897         return NGX_ERROR;
3898     }
3899 
3900     s->len = 2 * len;
3901     s->data = ngx_pnalloc(pool, 2 * len);
3902     if (s->data == NULL) {
3903         X509_free(cert);
3904         return NGX_ERROR;
3905     }
3906 
3907     ngx_hex_dump(s->data, buf, len);
3908 
3909     X509_free(cert);
3910 
3911     return NGX_OK;
3912 }
3913 
3914 
3915 ngx_int_t
3916 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3917 {
3918     X509        *cert;
3919     long         rc;
3920     const char  *str;
3921 
3922     cert = SSL_get_peer_certificate(c->ssl->connection);
3923     if (cert == NULL) {
3924         ngx_str_set(s, "NONE");
3925         return NGX_OK;
3926     }
3927 
3928     X509_free(cert);
3929 
3930     rc = SSL_get_verify_result(c->ssl->connection);
3931 
3932     if (rc == X509_V_OK) {
3933         ngx_str_set(s, "SUCCESS");
3934         return NGX_OK;
3935     }
3936 
3937     str = X509_verify_cert_error_string(rc);
3938 
3939     s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
3940     if (s->data == NULL) {
3941         return NGX_ERROR;
3942     }
3943 
3944     s->len = ngx_sprintf(s->data, "FAILED:%s", str) - s->data;
3945 
3946     return NGX_OK;
3947 }
3948 
3949 
3950 ngx_int_t
3951 ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3952 {
3953     BIO     *bio;
3954     X509    *cert;
3955     size_t   len;
3956 
3957     s->len = 0;
3958 
3959     cert = SSL_get_peer_certificate(c->ssl->connection);
3960     if (cert == NULL) {
3961         return NGX_OK;
3962     }
3963 
3964     bio = BIO_new(BIO_s_mem());
3965     if (bio == NULL) {
3966         X509_free(cert);
3967         return NGX_ERROR;
3968     }
3969 
3970 #if OPENSSL_VERSION_NUMBER > 0x10100000L
3971     ASN1_TIME_print(bio, X509_get0_notBefore(cert));
3972 #else
3973     ASN1_TIME_print(bio, X509_get_notBefore(cert));
3974 #endif
3975 
3976     len = BIO_pending(bio);
3977 
3978     s->len = len;
3979     s->data = ngx_pnalloc(pool, len);
3980     if (s->data == NULL) {
3981         BIO_free(bio);
3982         X509_free(cert);
3983         return NGX_ERROR;
3984     }
3985 
3986     BIO_read(bio, s->data, len);
3987     BIO_free(bio);
3988     X509_free(cert);
3989 
3990     return NGX_OK;
3991 }
3992 
3993 
3994 ngx_int_t
3995 ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
3996 {
3997     BIO     *bio;
3998     X509    *cert;
3999     size_t   len;
4000 
4001     s->len = 0;
4002 
4003     cert = SSL_get_peer_certificate(c->ssl->connection);
4004     if (cert == NULL) {
4005         return NGX_OK;
4006     }
4007 
4008     bio = BIO_new(BIO_s_mem());
4009     if (bio == NULL) {
4010         X509_free(cert);
4011         return NGX_ERROR;
4012     }
4013 
4014 #if OPENSSL_VERSION_NUMBER > 0x10100000L
4015     ASN1_TIME_print(bio, X509_get0_notAfter(cert));
4016 #else
4017     ASN1_TIME_print(bio, X509_get_notAfter(cert));
4018 #endif
4019 
4020     len = BIO_pending(bio);
4021 
4022     s->len = len;
4023     s->data = ngx_pnalloc(pool, len);
4024     if (s->data == NULL) {
4025         BIO_free(bio);
4026         X509_free(cert);
4027         return NGX_ERROR;
4028     }
4029 
4030     BIO_read(bio, s->data, len);
4031     BIO_free(bio);
4032     X509_free(cert);
4033 
4034     return NGX_OK;
4035 }
4036 
4037 
4038 ngx_int_t
4039 ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
4040 {
4041     X509    *cert;
4042     time_t   now, end;
4043 
4044     s->len = 0;
4045 
4046     cert = SSL_get_peer_certificate(c->ssl->connection);
4047     if (cert == NULL) {
4048         return NGX_OK;
4049     }
4050 
4051 #if OPENSSL_VERSION_NUMBER > 0x10100000L
4052     end = ngx_ssl_parse_time(X509_get0_notAfter(cert));
4053 #else
4054     end = ngx_ssl_parse_time(X509_get_notAfter(cert));
4055 #endif
4056 
4057     if (end == (time_t) NGX_ERROR) {
4058         X509_free(cert);
4059         return NGX_OK;
4060     }
4061 
4062     now = ngx_time();
4063 
4064     if (end < now + 86400) {
4065         ngx_str_set(s, "0");
4066         X509_free(cert);
4067         return NGX_OK;
4068     }
4069 
4070     s->data = ngx_pnalloc(pool, NGX_TIME_T_LEN);
4071     if (s->data == NULL) {
4072         X509_free(cert);
4073         return NGX_ERROR;
4074     }
4075 
4076     s->len = ngx_sprintf(s->data, "%T", (end - now) / 86400) - s->data;
4077 
4078     X509_free(cert);
4079 
4080     return NGX_OK;
4081 }
4082 
4083 
4084 static time_t
4085 ngx_ssl_parse_time(
4086 #if OPENSSL_VERSION_NUMBER > 0x10100000L
4087     const
4088 #endif
4089     ASN1_TIME *asn1time)
4090 {
4091     BIO     *bio;
4092     char    *value;
4093     size_t   len;
4094     time_t   time;
4095 
4096     /*
4097      * OpenSSL doesn't provide a way to convert ASN1_TIME
4098      * into time_t.  To do this, we use ASN1_TIME_print(),
4099      * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
4100      * "Feb  3 00:55:52 2015 GMT"), and parse the result.
4101      */
4102 
4103     bio = BIO_new(BIO_s_mem());
4104     if (bio == NULL) {
4105         return NGX_ERROR;
4106     }
4107 
4108     /* fake weekday prepended to match C asctime() format */
4109 
4110     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
4111     ASN1_TIME_print(bio, asn1time);
4112     len = BIO_get_mem_data(bio, &value);
4113 
4114     time = ngx_parse_http_time((u_char *) value, len);
4115 
4116     BIO_free(bio);
4117 
4118     return time;
4119 }
4120 
4121 
4122 static void *
4123 ngx_openssl_create_conf(ngx_cycle_t *cycle)
4124 {
4125     ngx_openssl_conf_t  *oscf;
4126 
4127     oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
4128     if (oscf == NULL) {
4129         return NULL;
4130     }
4131 
4132     /*
4133      * set by ngx_pcalloc():
4134      *
4135      *     oscf->engine = 0;
4136      */
4137 
4138     return oscf;
4139 }
4140 
4141 
4142 static char *
4143 ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4144 {
4145 #ifndef OPENSSL_NO_ENGINE
4146 
4147     ngx_openssl_conf_t *oscf = conf;
4148 
4149     ENGINE     *engine;
4150     ngx_str_t  *value;
4151 
4152     if (oscf->engine) {
4153         return "is duplicate";
4154     }
4155 
4156     oscf->engine = 1;
4157 
4158     value = cf->args->elts;
4159 
4160     engine = ENGINE_by_id((char *) value[1].data);
4161 
4162     if (engine == NULL) {
4163         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
4164                       "ENGINE_by_id(\"%V\") failed", &value[1]);
4165         return NGX_CONF_ERROR;
4166     }
4167 
4168     if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
4169         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
4170                       "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
4171                       &value[1]);
4172 
4173         ENGINE_free(engine);
4174 
4175         return NGX_CONF_ERROR;
4176     }
4177 
4178     ENGINE_free(engine);
4179 
4180     return NGX_CONF_OK;
4181 
4182 #else
4183 
4184     return "is not supported";
4185 
4186 #endif
4187 }
4188 
4189 
4190 static void
4191 ngx_openssl_exit(ngx_cycle_t *cycle)
4192 {
4193 #if OPENSSL_VERSION_NUMBER < 0x10100003L
4194 
4195     EVP_cleanup();
4196 #ifndef OPENSSL_NO_ENGINE
4197     ENGINE_cleanup();
4198 #endif
4199 
4200 #endif
4201 }