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