src/event/ngx_event_openssl.c - nginx-1.7.10

Global variables defined

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #define NGX_SSL_PASSWORD_BUFFER_SIZE  4096


  9. typedef struct {
  10.     ngx_uint_t  engine;   /* unsigned  engine:1; */
  11. } ngx_openssl_conf_t;


  12. static int ngx_ssl_password_callback(char *buf, int size, int rwflag,
  13.     void *userdata);
  14. static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
  15. static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
  16.     int ret);
  17. static void ngx_ssl_passwords_cleanup(void *data);
  18. static void ngx_ssl_handshake_handler(ngx_event_t *ev);
  19. static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
  20. static void ngx_ssl_write_handler(ngx_event_t *wev);
  21. static void ngx_ssl_read_handler(ngx_event_t *rev);
  22. static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
  23. static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
  24.     ngx_err_t err, char *text);
  25. static void ngx_ssl_clear_error(ngx_log_t *log);

  26. static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
  27.     ngx_str_t *sess_ctx);
  28. ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
  29. static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
  30.     ngx_ssl_session_t *sess);
  31. static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
  32.     u_char *id, int len, int *copy);
  33. static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
  34. static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
  35.     ngx_slab_pool_t *shpool, ngx_uint_t n);
  36. static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
  37.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);

  38. #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
  39. static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
  40.     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
  41.     HMAC_CTX *hctx, int enc);
  42. #endif

  43. #if (OPENSSL_VERSION_NUMBER < 0x10002002L || defined LIBRESSL_VERSION_NUMBER)
  44. static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str);
  45. #endif

  46. static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
  47. static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  48. static void ngx_openssl_exit(ngx_cycle_t *cycle);


  49. static ngx_command_t  ngx_openssl_commands[] = {

  50.     { ngx_string("ssl_engine"),
  51.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  52.       ngx_openssl_engine,
  53.       0,
  54.       0,
  55.       NULL },

  56.       ngx_null_command
  57. };


  58. static ngx_core_module_t  ngx_openssl_module_ctx = {
  59.     ngx_string("openssl"),
  60.     ngx_openssl_create_conf,
  61.     NULL
  62. };


  63. ngx_module_t  ngx_openssl_module = {
  64.     NGX_MODULE_V1,
  65.     &ngx_openssl_module_ctx,               /* module context */
  66.     ngx_openssl_commands,                  /* module directives */
  67.     NGX_CORE_MODULE,                       /* module type */
  68.     NULL,                                  /* init master */
  69.     NULL,                                  /* init module */
  70.     NULL,                                  /* init process */
  71.     NULL,                                  /* init thread */
  72.     NULL,                                  /* exit thread */
  73.     NULL,                                  /* exit process */
  74.     ngx_openssl_exit,                      /* exit master */
  75.     NGX_MODULE_V1_PADDING
  76. };


  77. int  ngx_ssl_connection_index;
  78. int  ngx_ssl_server_conf_index;
  79. int  ngx_ssl_session_cache_index;
  80. int  ngx_ssl_session_ticket_keys_index;
  81. int  ngx_ssl_certificate_index;
  82. int  ngx_ssl_stapling_index;


  83. ngx_int_t
  84. ngx_ssl_init(ngx_log_t *log)
  85. {
  86. #ifndef OPENSSL_IS_BORINGSSL
  87.     OPENSSL_config(NULL);
  88. #endif

  89.     SSL_library_init();
  90.     SSL_load_error_strings();

  91.     OpenSSL_add_all_algorithms();

  92. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
  93. #ifndef SSL_OP_NO_COMPRESSION
  94.     {
  95.     /*
  96.      * Disable gzip compression in OpenSSL prior to 1.0.0 version,
  97.      * this saves about 522K per connection.
  98.      */
  99.     int                  n;
  100.     STACK_OF(SSL_COMP)  *ssl_comp_methods;

  101.     ssl_comp_methods = SSL_COMP_get_compression_methods();
  102.     n = sk_SSL_COMP_num(ssl_comp_methods);

  103.     while (n--) {
  104.         (void) sk_SSL_COMP_pop(ssl_comp_methods);
  105.     }
  106.     }
  107. #endif
  108. #endif

  109.     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);

  110.     if (ngx_ssl_connection_index == -1) {
  111.         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
  112.         return NGX_ERROR;
  113.     }

  114.     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
  115.                                                          NULL);
  116.     if (ngx_ssl_server_conf_index == -1) {
  117.         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
  118.                       "SSL_CTX_get_ex_new_index() failed");
  119.         return NGX_ERROR;
  120.     }

  121.     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
  122.                                                            NULL);
  123.     if (ngx_ssl_session_cache_index == -1) {
  124.         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
  125.                       "SSL_CTX_get_ex_new_index() failed");
  126.         return NGX_ERROR;
  127.     }

  128.     ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
  129.                                                                  NULL, NULL);
  130.     if (ngx_ssl_session_ticket_keys_index == -1) {
  131.         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
  132.                       "SSL_CTX_get_ex_new_index() failed");
  133.         return NGX_ERROR;
  134.     }

  135.     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
  136.                                                          NULL);
  137.     if (ngx_ssl_certificate_index == -1) {
  138.         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
  139.                       "SSL_CTX_get_ex_new_index() failed");
  140.         return NGX_ERROR;
  141.     }

  142.     ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
  143.                                                       NULL);
  144.     if (ngx_ssl_stapling_index == -1) {
  145.         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
  146.                       "SSL_CTX_get_ex_new_index() failed");
  147.         return NGX_ERROR;
  148.     }

  149.     return NGX_OK;
  150. }


  151. ngx_int_t
  152. ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
  153. {
  154.     ssl->ctx = SSL_CTX_new(SSLv23_method());

  155.     if (ssl->ctx == NULL) {
  156.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
  157.         return NGX_ERROR;
  158.     }

  159.     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
  160.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  161.                       "SSL_CTX_set_ex_data() failed");
  162.         return NGX_ERROR;
  163.     }

  164.     ssl->buffer_size = NGX_SSL_BUFSIZE;

  165.     /* client side options */

  166. #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
  167.     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
  168. #endif

  169. #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
  170.     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
  171. #endif

  172.     /* server side options */

  173. #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
  174.     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
  175. #endif

  176. #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
  177.     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
  178. #endif

  179. #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
  180.     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
  181.     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
  182. #endif

  183. #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
  184.     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
  185. #endif

  186. #ifdef SSL_OP_TLS_D5_BUG
  187.     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
  188. #endif

  189. #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
  190.     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
  191. #endif

  192. #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
  193.     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
  194. #endif

  195.     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);

  196.     if (!(protocols & NGX_SSL_SSLv2)) {
  197.         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
  198.     }
  199.     if (!(protocols & NGX_SSL_SSLv3)) {
  200.         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
  201.     }
  202.     if (!(protocols & NGX_SSL_TLSv1)) {
  203.         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
  204.     }
  205. #ifdef SSL_OP_NO_TLSv1_1
  206.     if (!(protocols & NGX_SSL_TLSv1_1)) {
  207.         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
  208.     }
  209. #endif
  210. #ifdef SSL_OP_NO_TLSv1_2
  211.     if (!(protocols & NGX_SSL_TLSv1_2)) {
  212.         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
  213.     }
  214. #endif

  215. #ifdef SSL_OP_NO_COMPRESSION
  216.     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
  217. #endif

  218. #ifdef SSL_MODE_RELEASE_BUFFERS
  219.     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
  220. #endif

  221.     SSL_CTX_set_read_ahead(ssl->ctx, 1);

  222.     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);

  223.     return NGX_OK;
  224. }


  225. ngx_int_t
  226. ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
  227.     ngx_str_t *key, ngx_array_t *passwords)
  228. {
  229.     BIO         *bio;
  230.     X509        *x509;
  231.     u_long       n;
  232.     ngx_str_t   *pwd;
  233.     ngx_uint_t   tries;

  234.     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
  235.         return NGX_ERROR;
  236.     }

  237.     /*
  238.      * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
  239.      * allow to access certificate later from SSL_CTX, so we reimplement
  240.      * it here
  241.      */

  242.     bio = BIO_new_file((char *) cert->data, "r");
  243.     if (bio == NULL) {
  244.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  245.                       "BIO_new_file(\"%s\") failed", cert->data);
  246.         return NGX_ERROR;
  247.     }

  248.     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
  249.     if (x509 == NULL) {
  250.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  251.                       "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
  252.         BIO_free(bio);
  253.         return NGX_ERROR;
  254.     }

  255.     if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
  256.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  257.                       "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
  258.         X509_free(x509);
  259.         BIO_free(bio);
  260.         return NGX_ERROR;
  261.     }

  262.     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
  263.         == 0)
  264.     {
  265.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  266.                       "SSL_CTX_set_ex_data() failed");
  267.         X509_free(x509);
  268.         BIO_free(bio);
  269.         return NGX_ERROR;
  270.     }

  271.     X509_free(x509);

  272.     /* read rest of the chain */

  273.     for ( ;; ) {

  274.         x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
  275.         if (x509 == NULL) {
  276.             n = ERR_peek_last_error();

  277.             if (ERR_GET_LIB(n) == ERR_LIB_PEM
  278.                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
  279.             {
  280.                 /* end of file */
  281.                 ERR_clear_error();
  282.                 break;
  283.             }

  284.             /* some real error */

  285.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  286.                           "PEM_read_bio_X509(\"%s\") failed", cert->data);
  287.             BIO_free(bio);
  288.             return NGX_ERROR;
  289.         }

  290.         if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
  291.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  292.                           "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
  293.                           cert->data);
  294.             X509_free(x509);
  295.             BIO_free(bio);
  296.             return NGX_ERROR;
  297.         }
  298.     }

  299.     BIO_free(bio);

  300.     if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) {

  301. #ifndef OPENSSL_NO_ENGINE

  302.         u_char      *p, *last;
  303.         ENGINE      *engine;
  304.         EVP_PKEY    *pkey;

  305.         p = key->data + sizeof("engine:") - 1;
  306.         last = (u_char *) ngx_strchr(p, ':');

  307.         if (last == NULL) {
  308.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  309.                                "invalid syntax in \"%V\"", key);
  310.             return NGX_ERROR;
  311.         }

  312.         *last = '\0';

  313.         engine = ENGINE_by_id((char *) p);

  314.         if (engine == NULL) {
  315.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  316.                           "ENGINE_by_id(\"%s\") failed", p);
  317.             return NGX_ERROR;
  318.         }

  319.         *last++ = ':';

  320.         pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);

  321.         if (pkey == NULL) {
  322.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  323.                           "ENGINE_load_private_key(\"%s\") failed", last);
  324.             ENGINE_free(engine);
  325.             return NGX_ERROR;
  326.         }

  327.         ENGINE_free(engine);

  328.         if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
  329.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  330.                           "SSL_CTX_use_PrivateKey(\"%s\") failed", last);
  331.             EVP_PKEY_free(pkey);
  332.             return NGX_ERROR;
  333.         }

  334.         EVP_PKEY_free(pkey);

  335.         return NGX_OK;

  336. #else

  337.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  338.                            "loading \"engine:...\" certificate keys "
  339.                            "is not supported");
  340.         return NGX_ERROR;

  341. #endif
  342.     }

  343.     if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
  344.         return NGX_ERROR;
  345.     }

  346.     if (passwords) {
  347.         tries = passwords->nelts;
  348.         pwd = passwords->elts;

  349.         SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_ssl_password_callback);
  350.         SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, pwd);

  351.     } else {
  352.         tries = 1;
  353. #if (NGX_SUPPRESS_WARN)
  354.         pwd = NULL;
  355. #endif
  356.     }

  357.     for ( ;; ) {

  358.         if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
  359.                                         SSL_FILETYPE_PEM)
  360.             != 0)
  361.         {
  362.             break;
  363.         }

  364.         if (--tries) {
  365.             ERR_clear_error();
  366.             SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd);
  367.             continue;
  368.         }

  369.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  370.                       "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
  371.         return NGX_ERROR;
  372.     }

  373.     SSL_CTX_set_default_passwd_cb(ssl->ctx, NULL);

  374.     return NGX_OK;
  375. }


  376. static int
  377. ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
  378. {
  379.     ngx_str_t *pwd = userdata;

  380.     if (rwflag) {
  381.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  382.                       "ngx_ssl_password_callback() is called for encryption");
  383.         return 0;
  384.     }

  385.     if (pwd->len > (size_t) size) {
  386.         ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
  387.                       "password is truncated to %d bytes", size);
  388.     } else {
  389.         size = pwd->len;
  390.     }

  391.     ngx_memcpy(buf, pwd->data, size);

  392.     return size;
  393. }


  394. ngx_int_t
  395. ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
  396.     ngx_int_t depth)
  397. {
  398.     STACK_OF(X509_NAME)  *list;

  399.     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_ssl_verify_callback);

  400.     SSL_CTX_set_verify_depth(ssl->ctx, depth);

  401.     if (cert->len == 0) {
  402.         return NGX_OK;
  403.     }

  404.     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
  405.         return NGX_ERROR;
  406.     }

  407.     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
  408.         == 0)
  409.     {
  410.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  411.                       "SSL_CTX_load_verify_locations(\"%s\") failed",
  412.                       cert->data);
  413.         return NGX_ERROR;
  414.     }

  415.     /*
  416.      * SSL_CTX_load_verify_locations() may leave errors in the error queue
  417.      * while returning success
  418.      */

  419.     ERR_clear_error();

  420.     list = SSL_load_client_CA_file((char *) cert->data);

  421.     if (list == NULL) {
  422.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  423.                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
  424.         return NGX_ERROR;
  425.     }

  426.     /*
  427.      * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
  428.      * always leaved an error in the error queue
  429.      */

  430.     ERR_clear_error();

  431.     SSL_CTX_set_client_CA_list(ssl->ctx, list);

  432.     return NGX_OK;
  433. }


  434. ngx_int_t
  435. ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
  436.     ngx_int_t depth)
  437. {
  438.     SSL_CTX_set_verify_depth(ssl->ctx, depth);

  439.     if (cert->len == 0) {
  440.         return NGX_OK;
  441.     }

  442.     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
  443.         return NGX_ERROR;
  444.     }

  445.     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
  446.         == 0)
  447.     {
  448.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  449.                       "SSL_CTX_load_verify_locations(\"%s\") failed",
  450.                       cert->data);
  451.         return NGX_ERROR;
  452.     }

  453.     /*
  454.      * SSL_CTX_load_verify_locations() may leave errors in the error queue
  455.      * while returning success
  456.      */

  457.     ERR_clear_error();

  458.     return NGX_OK;
  459. }


  460. ngx_int_t
  461. ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
  462. {
  463.     X509_STORE   *store;
  464.     X509_LOOKUP  *lookup;

  465.     if (crl->len == 0) {
  466.         return NGX_OK;
  467.     }

  468.     if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
  469.         return NGX_ERROR;
  470.     }

  471.     store = SSL_CTX_get_cert_store(ssl->ctx);

  472.     if (store == NULL) {
  473.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  474.                       "SSL_CTX_get_cert_store() failed");
  475.         return NGX_ERROR;
  476.     }

  477.     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());

  478.     if (lookup == NULL) {
  479.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  480.                       "X509_STORE_add_lookup() failed");
  481.         return NGX_ERROR;
  482.     }

  483.     if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
  484.         == 0)
  485.     {
  486.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  487.                       "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
  488.         return NGX_ERROR;
  489.     }

  490.     X509_STORE_set_flags(store,
  491.                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);

  492.     return NGX_OK;
  493. }


  494. static int
  495. ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
  496. {
  497. #if (NGX_DEBUG)
  498.     char              *subject, *issuer;
  499.     int                err, depth;
  500.     X509              *cert;
  501.     X509_NAME         *sname, *iname;
  502.     ngx_connection_t  *c;
  503.     ngx_ssl_conn_t    *ssl_conn;

  504.     ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
  505.                                           SSL_get_ex_data_X509_STORE_CTX_idx());

  506.     c = ngx_ssl_get_connection(ssl_conn);

  507.     cert = X509_STORE_CTX_get_current_cert(x509_store);
  508.     err = X509_STORE_CTX_get_error(x509_store);
  509.     depth = X509_STORE_CTX_get_error_depth(x509_store);

  510.     sname = X509_get_subject_name(cert);
  511.     subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";

  512.     iname = X509_get_issuer_name(cert);
  513.     issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";

  514.     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
  515.                    "verify:%d, error:%d, depth:%d, "
  516.                    "subject:\"%s\", issuer:\"%s\"",
  517.                    ok, err, depth, subject, issuer);

  518.     if (sname) {
  519.         OPENSSL_free(subject);
  520.     }

  521.     if (iname) {
  522.         OPENSSL_free(issuer);
  523.     }
  524. #endif

  525.     return 1;
  526. }


  527. static void
  528. ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
  529. {
  530.     BIO               *rbio, *wbio;
  531.     ngx_connection_t  *c;

  532.     if (where & SSL_CB_HANDSHAKE_START) {
  533.         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);

  534.         if (c->ssl->handshaked) {
  535.             c->ssl->renegotiation = 1;
  536.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
  537.         }
  538.     }

  539.     if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
  540.         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);

  541.         if (!c->ssl->handshake_buffer_set) {
  542.             /*
  543.              * By default OpenSSL uses 4k buffer during a handshake,
  544.              * which is too low for long certificate chains and might
  545.              * result in extra round-trips.
  546.              *
  547.              * To adjust a buffer size we detect that buffering was added
  548.              * to write side of the connection by comparing rbio and wbio.
  549.              * If they are different, we assume that it's due to buffering
  550.              * added to wbio, and set buffer size.
  551.              */

  552.             rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn);
  553.             wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn);

  554.             if (rbio != wbio) {
  555.                 (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE);
  556.                 c->ssl->handshake_buffer_set = 1;
  557.             }
  558.         }
  559.     }
  560. }


  561. RSA *
  562. ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
  563.     int key_length)
  564. {
  565.     static RSA  *key;

  566.     if (key_length != 512) {
  567.         return NULL;
  568.     }

  569. #ifndef OPENSSL_NO_DEPRECATED

  570.     if (key == NULL) {
  571.         key = RSA_generate_key(512, RSA_F4, NULL, NULL);
  572.     }

  573. #endif

  574.     return key;
  575. }


  576. ngx_array_t *
  577. ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
  578. {
  579.     u_char              *p, *last, *end;
  580.     size_t               len;
  581.     ssize_t              n;
  582.     ngx_fd_t             fd;
  583.     ngx_str_t           *pwd;
  584.     ngx_array_t         *passwords;
  585.     ngx_pool_cleanup_t  *cln;
  586.     u_char               buf[NGX_SSL_PASSWORD_BUFFER_SIZE];

  587.     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
  588.         return NULL;
  589.     }

  590.     cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
  591.     passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));

  592.     if (cln == NULL || passwords == NULL) {
  593.         return NULL;
  594.     }

  595.     cln->handler = ngx_ssl_passwords_cleanup;
  596.     cln->data = passwords;

  597.     fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
  598.     if (fd == NGX_INVALID_FILE) {
  599.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  600.                            ngx_open_file_n " \"%s\" failed", file->data);
  601.         return NULL;
  602.     }

  603.     len = 0;
  604.     last = buf;

  605.     do {
  606.         n = ngx_read_fd(fd, last, NGX_SSL_PASSWORD_BUFFER_SIZE - len);

  607.         if (n == -1) {
  608.             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  609.                                ngx_read_fd_n " \"%s\" failed", file->data);
  610.             passwords = NULL;
  611.             goto cleanup;
  612.         }

  613.         end = last + n;

  614.         if (len && n == 0) {
  615.             *end++ = LF;
  616.         }

  617.         p = buf;

  618.         for ( ;; ) {
  619.             last = ngx_strlchr(last, end, LF);

  620.             if (last == NULL) {
  621.                 break;
  622.             }

  623.             len = last++ - p;

  624.             if (len && p[len - 1] == CR) {
  625.                 len--;
  626.             }

  627.             if (len) {
  628.                 pwd = ngx_array_push(passwords);
  629.                 if (pwd == NULL) {
  630.                     passwords = NULL;
  631.                     goto cleanup;
  632.                 }

  633.                 pwd->len = len;
  634.                 pwd->data = ngx_pnalloc(cf->temp_pool, len);

  635.                 if (pwd->data == NULL) {
  636.                     passwords->nelts--;
  637.                     passwords = NULL;
  638.                     goto cleanup;
  639.                 }

  640.                 ngx_memcpy(pwd->data, p, len);
  641.             }

  642.             p = last;
  643.         }

  644.         len = end - p;

  645.         if (len == NGX_SSL_PASSWORD_BUFFER_SIZE) {
  646.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  647.                                "too long line in \"%s\"", file->data);
  648.             passwords = NULL;
  649.             goto cleanup;
  650.         }

  651.         ngx_memmove(buf, p, len);
  652.         last = buf + len;

  653.     } while (n != 0);

  654.     if (passwords->nelts == 0) {
  655.         pwd = ngx_array_push(passwords);
  656.         if (pwd == NULL) {
  657.             passwords = NULL;
  658.             goto cleanup;
  659.         }

  660.         ngx_memzero(pwd, sizeof(ngx_str_t));
  661.     }

  662. cleanup:

  663.     if (ngx_close_file(fd) == NGX_FILE_ERROR) {
  664.         ngx_conf_log_error(NGX_LOG_ALERT, cf, ngx_errno,
  665.                            ngx_close_file_n " \"%s\" failed", file->data);
  666.     }

  667.     ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);

  668.     return passwords;
  669. }


  670. static void
  671. ngx_ssl_passwords_cleanup(void *data)
  672. {
  673.     ngx_array_t *passwords = data;

  674.     ngx_str_t   *pwd;
  675.     ngx_uint_t   i;

  676.     pwd = passwords->elts;

  677.     for (i = 0; i < passwords->nelts; i++) {
  678.         ngx_memzero(pwd[i].data, pwd[i].len);
  679.     }
  680. }


  681. ngx_int_t
  682. ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
  683. {
  684.     DH   *dh;
  685.     BIO  *bio;

  686.     /*
  687.      * -----BEGIN DH PARAMETERS-----
  688.      * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
  689.      * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
  690.      * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
  691.      * -----END DH PARAMETERS-----
  692.      */

  693.     static unsigned char dh1024_p[] = {
  694.         0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
  695.         0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
  696.         0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
  697.         0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
  698.         0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
  699.         0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
  700.         0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
  701.         0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
  702.         0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
  703.         0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
  704.         0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
  705.     };

  706.     static unsigned char dh1024_g[] = { 0x02 };


  707.     if (file->len == 0) {

  708.         dh = DH_new();
  709.         if (dh == NULL) {
  710.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
  711.             return NGX_ERROR;
  712.         }

  713.         dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
  714.         dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);

  715.         if (dh->p == NULL || dh->g == NULL) {
  716.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
  717.             DH_free(dh);
  718.             return NGX_ERROR;
  719.         }

  720.         SSL_CTX_set_tmp_dh(ssl->ctx, dh);

  721.         DH_free(dh);

  722.         return NGX_OK;
  723.     }

  724.     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
  725.         return NGX_ERROR;
  726.     }

  727.     bio = BIO_new_file((char *) file->data, "r");
  728.     if (bio == NULL) {
  729.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  730.                       "BIO_new_file(\"%s\") failed", file->data);
  731.         return NGX_ERROR;
  732.     }

  733.     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  734.     if (dh == NULL) {
  735.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  736.                       "PEM_read_bio_DHparams(\"%s\") failed", file->data);
  737.         BIO_free(bio);
  738.         return NGX_ERROR;
  739.     }

  740.     SSL_CTX_set_tmp_dh(ssl->ctx, dh);

  741.     DH_free(dh);
  742.     BIO_free(bio);

  743.     return NGX_OK;
  744. }


  745. ngx_int_t
  746. ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
  747. {
  748. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
  749. #ifndef OPENSSL_NO_ECDH
  750.     int      nid;
  751.     EC_KEY  *ecdh;

  752.     /*
  753.      * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
  754.      * from RFC 4492 section 5.1.1, or explicitly described curves over
  755.      * binary fields. OpenSSL only supports the "named curves", which provide
  756.      * maximum interoperability.
  757.      */

  758.     nid = OBJ_sn2nid((const char *) name->data);
  759.     if (nid == 0) {
  760.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  761.                       "Unknown curve name \"%s\"", name->data);
  762.         return NGX_ERROR;
  763.     }

  764.     ecdh = EC_KEY_new_by_curve_name(nid);
  765.     if (ecdh == NULL) {
  766.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  767.                       "Unable to create curve \"%s\"", name->data);
  768.         return NGX_ERROR;
  769.     }

  770.     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);

  771.     SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);

  772.     EC_KEY_free(ecdh);
  773. #endif
  774. #endif

  775.     return NGX_OK;
  776. }


  777. ngx_int_t
  778. ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
  779. {
  780.     ngx_ssl_connection_t  *sc;

  781.     sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
  782.     if (sc == NULL) {
  783.         return NGX_ERROR;
  784.     }

  785.     sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
  786.     sc->buffer_size = ssl->buffer_size;

  787.     sc->connection = SSL_new(ssl->ctx);

  788.     if (sc->connection == NULL) {
  789.         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
  790.         return NGX_ERROR;
  791.     }

  792.     if (SSL_set_fd(sc->connection, c->fd) == 0) {
  793.         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
  794.         return NGX_ERROR;
  795.     }

  796.     if (flags & NGX_SSL_CLIENT) {
  797.         SSL_set_connect_state(sc->connection);

  798.     } else {
  799.         SSL_set_accept_state(sc->connection);
  800.     }

  801.     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
  802.         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
  803.         return NGX_ERROR;
  804.     }

  805.     c->ssl = sc;

  806.     return NGX_OK;
  807. }


  808. ngx_int_t
  809. ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
  810. {
  811.     if (session) {
  812.         if (SSL_set_session(c->ssl->connection, session) == 0) {
  813.             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
  814.             return NGX_ERROR;
  815.         }
  816.     }

  817.     return NGX_OK;
  818. }


  819. ngx_int_t
  820. ngx_ssl_handshake(ngx_connection_t *c)
  821. {
  822.     int        n, sslerr;
  823.     ngx_err_t  err;

  824.     ngx_ssl_clear_error(c->log);

  825.     n = SSL_do_handshake(c->ssl->connection);

  826.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);

  827.     if (n == 1) {

  828.         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  829.             return NGX_ERROR;
  830.         }

  831.         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  832.             return NGX_ERROR;
  833.         }

  834. #if (NGX_DEBUG)
  835.         {
  836.         char         buf[129], *s, *d;
  837. #if OPENSSL_VERSION_NUMBER >= 0x10000000L
  838.         const
  839. #endif
  840.         SSL_CIPHER  *cipher;

  841.         cipher = SSL_get_current_cipher(c->ssl->connection);

  842.         if (cipher) {
  843.             SSL_CIPHER_description(cipher, &buf[1], 128);

  844.             for (s = &buf[1], d = buf; *s; s++) {
  845.                 if (*s == ' ' && *d == ' ') {
  846.                     continue;
  847.                 }

  848.                 if (*s == LF || *s == CR) {
  849.                     continue;
  850.                 }

  851.                 *++d = *s;
  852.             }

  853.             if (*d != ' ') {
  854.                 d++;
  855.             }

  856.             *d = '\0';

  857.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  858.                            "SSL: %s, cipher: \"%s\"",
  859.                            SSL_get_version(c->ssl->connection), &buf[1]);

  860.             if (SSL_session_reused(c->ssl->connection)) {
  861.                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  862.                                "SSL reused session");
  863.             }

  864.         } else {
  865.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  866.                            "SSL no shared ciphers");
  867.         }
  868.         }
  869. #endif

  870.         c->ssl->handshaked = 1;

  871.         c->recv = ngx_ssl_recv;
  872.         c->send = ngx_ssl_write;
  873.         c->recv_chain = ngx_ssl_recv_chain;
  874.         c->send_chain = ngx_ssl_send_chain;

  875. #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS

  876.         /* initial handshake done, disable renegotiation (CVE-2009-3555) */
  877.         if (c->ssl->connection->s3) {
  878.             c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
  879.         }

  880. #endif

  881.         return NGX_OK;
  882.     }

  883.     sslerr = SSL_get_error(c->ssl->connection, n);

  884.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);

  885.     if (sslerr == SSL_ERROR_WANT_READ) {
  886.         c->read->ready = 0;
  887.         c->read->handler = ngx_ssl_handshake_handler;
  888.         c->write->handler = ngx_ssl_handshake_handler;

  889.         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  890.             return NGX_ERROR;
  891.         }

  892.         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  893.             return NGX_ERROR;
  894.         }

  895.         return NGX_AGAIN;
  896.     }

  897.     if (sslerr == SSL_ERROR_WANT_WRITE) {
  898.         c->write->ready = 0;
  899.         c->read->handler = ngx_ssl_handshake_handler;
  900.         c->write->handler = ngx_ssl_handshake_handler;

  901.         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  902.             return NGX_ERROR;
  903.         }

  904.         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  905.             return NGX_ERROR;
  906.         }

  907.         return NGX_AGAIN;
  908.     }

  909.     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;

  910.     c->ssl->no_wait_shutdown = 1;
  911.     c->ssl->no_send_shutdown = 1;
  912.     c->read->eof = 1;

  913.     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
  914.         ngx_connection_error(c, err,
  915.                              "peer closed connection in SSL handshake");

  916.         return NGX_ERROR;
  917.     }

  918.     c->read->error = 1;

  919.     ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");

  920.     return NGX_ERROR;
  921. }


  922. static void
  923. ngx_ssl_handshake_handler(ngx_event_t *ev)
  924. {
  925.     ngx_connection_t  *c;

  926.     c = ev->data;

  927.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  928.                    "SSL handshake handler: %d", ev->write);

  929.     if (ev->timedout) {
  930.         c->ssl->handler(c);
  931.         return;
  932.     }

  933.     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
  934.         return;
  935.     }

  936.     c->ssl->handler(c);
  937. }


  938. ssize_t
  939. ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit)
  940. {
  941.     u_char     *last;
  942.     ssize_t     n, bytes, size;
  943.     ngx_buf_t  *b;

  944.     bytes = 0;

  945.     b = cl->buf;
  946.     last = b->last;

  947.     for ( ;; ) {
  948.         size = b->end - last;

  949.         if (limit) {
  950.             if (bytes >= limit) {
  951.                 return bytes;
  952.             }

  953.             if (bytes + size > limit) {
  954.                 size = (ssize_t) (limit - bytes);
  955.             }
  956.         }

  957.         n = ngx_ssl_recv(c, last, size);

  958.         if (n > 0) {
  959.             last += n;
  960.             bytes += n;

  961.             if (last == b->end) {
  962.                 cl = cl->next;

  963.                 if (cl == NULL) {
  964.                     return bytes;
  965.                 }

  966.                 b = cl->buf;
  967.                 last = b->last;
  968.             }

  969.             continue;
  970.         }

  971.         if (bytes) {

  972.             if (n == 0 || n == NGX_ERROR) {
  973.                 c->read->ready = 1;
  974.             }

  975.             return bytes;
  976.         }

  977.         return n;
  978.     }
  979. }


  980. ssize_t
  981. ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
  982. {
  983.     int  n, bytes;

  984.     if (c->ssl->last == NGX_ERROR) {
  985.         c->read->error = 1;
  986.         return NGX_ERROR;
  987.     }

  988.     if (c->ssl->last == NGX_DONE) {
  989.         c->read->ready = 0;
  990.         c->read->eof = 1;
  991.         return 0;
  992.     }

  993.     bytes = 0;

  994.     ngx_ssl_clear_error(c->log);

  995.     /*
  996.      * SSL_read() may return data in parts, so try to read
  997.      * until SSL_read() would return no data
  998.      */

  999.     for ( ;; ) {

  1000.         n = SSL_read(c->ssl->connection, buf, size);

  1001.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);

  1002.         if (n > 0) {
  1003.             bytes += n;
  1004.         }

  1005.         c->ssl->last = ngx_ssl_handle_recv(c, n);

  1006.         if (c->ssl->last == NGX_OK) {

  1007.             size -= n;

  1008.             if (size == 0) {
  1009.                 c->read->ready = 1;
  1010.                 return bytes;
  1011.             }

  1012.             buf += n;

  1013.             continue;
  1014.         }

  1015.         if (bytes) {
  1016.             if (c->ssl->last != NGX_AGAIN) {
  1017.                 c->read->ready = 1;
  1018.             }

  1019.             return bytes;
  1020.         }

  1021.         switch (c->ssl->last) {

  1022.         case NGX_DONE:
  1023.             c->read->ready = 0;
  1024.             c->read->eof = 1;
  1025.             return 0;

  1026.         case NGX_ERROR:
  1027.             c->read->error = 1;

  1028.             /* fall through */

  1029.         case NGX_AGAIN:
  1030.             return c->ssl->last;
  1031.         }
  1032.     }
  1033. }


  1034. static ngx_int_t
  1035. ngx_ssl_handle_recv(ngx_connection_t *c, int n)
  1036. {
  1037.     int        sslerr;
  1038.     ngx_err_t  err;

  1039.     if (c->ssl->renegotiation) {
  1040.         /*
  1041.          * disable renegotiation (CVE-2009-3555):
  1042.          * OpenSSL (at least up to 0.9.8l) does not handle disabled
  1043.          * renegotiation gracefully, so drop connection here
  1044.          */

  1045.         ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");

  1046.         while (ERR_peek_error()) {
  1047.             ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
  1048.                           "ignoring stale global SSL error");
  1049.         }

  1050.         ERR_clear_error();

  1051.         c->ssl->no_wait_shutdown = 1;
  1052.         c->ssl->no_send_shutdown = 1;

  1053.         return NGX_ERROR;
  1054.     }

  1055.     if (n > 0) {

  1056.         if (c->ssl->saved_write_handler) {

  1057.             c->write->handler = c->ssl->saved_write_handler;
  1058.             c->ssl->saved_write_handler = NULL;
  1059.             c->write->ready = 1;

  1060.             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  1061.                 return NGX_ERROR;
  1062.             }

  1063.             ngx_post_event(c->write, &ngx_posted_events);
  1064.         }

  1065.         return NGX_OK;
  1066.     }

  1067.     sslerr = SSL_get_error(c->ssl->connection, n);

  1068.     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;

  1069.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);

  1070.     if (sslerr == SSL_ERROR_WANT_READ) {
  1071.         c->read->ready = 0;
  1072.         return NGX_AGAIN;
  1073.     }

  1074.     if (sslerr == SSL_ERROR_WANT_WRITE) {

  1075.         ngx_log_error(NGX_LOG_INFO, c->log, 0,
  1076.                       "peer started SSL renegotiation");

  1077.         c->write->ready = 0;

  1078.         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  1079.             return NGX_ERROR;
  1080.         }

  1081.         /*
  1082.          * we do not set the timer because there is already the read event timer
  1083.          */

  1084.         if (c->ssl->saved_write_handler == NULL) {
  1085.             c->ssl->saved_write_handler = c->write->handler;
  1086.             c->write->handler = ngx_ssl_write_handler;
  1087.         }

  1088.         return NGX_AGAIN;
  1089.     }

  1090.     c->ssl->no_wait_shutdown = 1;
  1091.     c->ssl->no_send_shutdown = 1;

  1092.     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
  1093.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  1094.                        "peer shutdown SSL cleanly");
  1095.         return NGX_DONE;
  1096.     }

  1097.     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");

  1098.     return NGX_ERROR;
  1099. }


  1100. static void
  1101. ngx_ssl_write_handler(ngx_event_t *wev)
  1102. {
  1103.     ngx_connection_t  *c;

  1104.     c = wev->data;

  1105.     c->read->handler(c->read);
  1106. }


  1107. /*
  1108. * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
  1109. * before the SSL_write() call to decrease a SSL overhead.
  1110. *
  1111. * Besides for protocols such as HTTP it is possible to always buffer
  1112. * the output to decrease a SSL overhead some more.
  1113. */

  1114. ngx_chain_t *
  1115. ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
  1116. {
  1117.     int          n;
  1118.     ngx_uint_t   flush;
  1119.     ssize_t      send, size;
  1120.     ngx_buf_t   *buf;

  1121.     if (!c->ssl->buffer) {

  1122.         while (in) {
  1123.             if (ngx_buf_special(in->buf)) {
  1124.                 in = in->next;
  1125.                 continue;
  1126.             }

  1127.             n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);

  1128.             if (n == NGX_ERROR) {
  1129.                 return NGX_CHAIN_ERROR;
  1130.             }

  1131.             if (n == NGX_AGAIN) {
  1132.                 return in;
  1133.             }

  1134.             in->buf->pos += n;
  1135.             c->sent += n;

  1136.             if (in->buf->pos == in->buf->last) {
  1137.                 in = in->next;
  1138.             }
  1139.         }

  1140.         return in;
  1141.     }


  1142.     /* the maximum limit size is the maximum int32_t value - the page size */

  1143.     if (limit == 0 || limit > (off_t) (NGX_MAX_INT32_VALUE - ngx_pagesize)) {
  1144.         limit = NGX_MAX_INT32_VALUE - ngx_pagesize;
  1145.     }

  1146.     buf = c->ssl->buf;

  1147.     if (buf == NULL) {
  1148.         buf = ngx_create_temp_buf(c->pool, c->ssl->buffer_size);
  1149.         if (buf == NULL) {
  1150.             return NGX_CHAIN_ERROR;
  1151.         }

  1152.         c->ssl->buf = buf;
  1153.     }

  1154.     if (buf->start == NULL) {
  1155.         buf->start = ngx_palloc(c->pool, c->ssl->buffer_size);
  1156.         if (buf->start == NULL) {
  1157.             return NGX_CHAIN_ERROR;
  1158.         }

  1159.         buf->pos = buf->start;
  1160.         buf->last = buf->start;
  1161.         buf->end = buf->start + c->ssl->buffer_size;
  1162.     }

  1163.     send = buf->last - buf->pos;
  1164.     flush = (in == NULL) ? 1 : buf->flush;

  1165.     for ( ;; ) {

  1166.         while (in && buf->last < buf->end && send < limit) {
  1167.             if (in->buf->last_buf || in->buf->flush) {
  1168.                 flush = 1;
  1169.             }

  1170.             if (ngx_buf_special(in->buf)) {
  1171.                 in = in->next;
  1172.                 continue;
  1173.             }

  1174.             size = in->buf->last - in->buf->pos;

  1175.             if (size > buf->end - buf->last) {
  1176.                 size = buf->end - buf->last;
  1177.             }

  1178.             if (send + size > limit) {
  1179.                 size = (ssize_t) (limit - send);
  1180.             }

  1181.             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  1182.                            "SSL buf copy: %d", size);

  1183.             ngx_memcpy(buf->last, in->buf->pos, size);

  1184.             buf->last += size;
  1185.             in->buf->pos += size;
  1186.             send += size;

  1187.             if (in->buf->pos == in->buf->last) {
  1188.                 in = in->next;
  1189.             }
  1190.         }

  1191.         if (!flush && send < limit && buf->last < buf->end) {
  1192.             break;
  1193.         }

  1194.         size = buf->last - buf->pos;

  1195.         if (size == 0) {
  1196.             buf->flush = 0;
  1197.             c->buffered &= ~NGX_SSL_BUFFERED;
  1198.             return in;
  1199.         }

  1200.         n = ngx_ssl_write(c, buf->pos, size);

  1201.         if (n == NGX_ERROR) {
  1202.             return NGX_CHAIN_ERROR;
  1203.         }

  1204.         if (n == NGX_AGAIN) {
  1205.             break;
  1206.         }

  1207.         buf->pos += n;
  1208.         c->sent += n;

  1209.         if (n < size) {
  1210.             break;
  1211.         }

  1212.         flush = 0;

  1213.         buf->pos = buf->start;
  1214.         buf->last = buf->start;

  1215.         if (in == NULL || send == limit) {
  1216.             break;
  1217.         }
  1218.     }

  1219.     buf->flush = flush;

  1220.     if (buf->pos < buf->last) {
  1221.         c->buffered |= NGX_SSL_BUFFERED;

  1222.     } else {
  1223.         c->buffered &= ~NGX_SSL_BUFFERED;
  1224.     }

  1225.     return in;
  1226. }


  1227. ssize_t
  1228. ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
  1229. {
  1230.     int        n, sslerr;
  1231.     ngx_err_t  err;

  1232.     ngx_ssl_clear_error(c->log);

  1233.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);

  1234.     n = SSL_write(c->ssl->connection, data, size);

  1235.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);

  1236.     if (n > 0) {

  1237.         if (c->ssl->saved_read_handler) {

  1238.             c->read->handler = c->ssl->saved_read_handler;
  1239.             c->ssl->saved_read_handler = NULL;
  1240.             c->read->ready = 1;

  1241.             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  1242.                 return NGX_ERROR;
  1243.             }

  1244.             ngx_post_event(c->read, &ngx_posted_events);
  1245.         }

  1246.         return n;
  1247.     }

  1248.     sslerr = SSL_get_error(c->ssl->connection, n);

  1249.     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;

  1250.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);

  1251.     if (sslerr == SSL_ERROR_WANT_WRITE) {
  1252.         c->write->ready = 0;
  1253.         return NGX_AGAIN;
  1254.     }

  1255.     if (sslerr == SSL_ERROR_WANT_READ) {

  1256.         ngx_log_error(NGX_LOG_INFO, c->log, 0,
  1257.                       "peer started SSL renegotiation");

  1258.         c->read->ready = 0;

  1259.         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  1260.             return NGX_ERROR;
  1261.         }

  1262.         /*
  1263.          * we do not set the timer because there is already
  1264.          * the write event timer
  1265.          */

  1266.         if (c->ssl->saved_read_handler == NULL) {
  1267.             c->ssl->saved_read_handler = c->read->handler;
  1268.             c->read->handler = ngx_ssl_read_handler;
  1269.         }

  1270.         return NGX_AGAIN;
  1271.     }

  1272.     c->ssl->no_wait_shutdown = 1;
  1273.     c->ssl->no_send_shutdown = 1;
  1274.     c->write->error = 1;

  1275.     ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");

  1276.     return NGX_ERROR;
  1277. }


  1278. static void
  1279. ngx_ssl_read_handler(ngx_event_t *rev)
  1280. {
  1281.     ngx_connection_t  *c;

  1282.     c = rev->data;

  1283.     c->write->handler(c->write);
  1284. }


  1285. void
  1286. ngx_ssl_free_buffer(ngx_connection_t *c)
  1287. {
  1288.     if (c->ssl->buf && c->ssl->buf->start) {
  1289.         if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
  1290.             c->ssl->buf->start = NULL;
  1291.         }
  1292.     }
  1293. }


  1294. ngx_int_t
  1295. ngx_ssl_shutdown(ngx_connection_t *c)
  1296. {
  1297.     int        n, sslerr, mode;
  1298.     ngx_err_t  err;

  1299.     if (c->timedout) {
  1300.         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
  1301.         SSL_set_quiet_shutdown(c->ssl->connection, 1);

  1302.     } else {
  1303.         mode = SSL_get_shutdown(c->ssl->connection);

  1304.         if (c->ssl->no_wait_shutdown) {
  1305.             mode |= SSL_RECEIVED_SHUTDOWN;
  1306.         }

  1307.         if (c->ssl->no_send_shutdown) {
  1308.             mode |= SSL_SENT_SHUTDOWN;
  1309.         }

  1310.         if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
  1311.             SSL_set_quiet_shutdown(c->ssl->connection, 1);
  1312.         }
  1313.     }

  1314.     SSL_set_shutdown(c->ssl->connection, mode);

  1315.     ngx_ssl_clear_error(c->log);

  1316.     n = SSL_shutdown(c->ssl->connection);

  1317.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);

  1318.     sslerr = 0;

  1319.     /* SSL_shutdown() never returns -1, on error it returns 0 */

  1320.     if (n != 1 && ERR_peek_error()) {
  1321.         sslerr = SSL_get_error(c->ssl->connection, n);

  1322.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  1323.                        "SSL_get_error: %d", sslerr);
  1324.     }

  1325.     if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
  1326.         SSL_free(c->ssl->connection);
  1327.         c->ssl = NULL;

  1328.         return NGX_OK;
  1329.     }

  1330.     if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
  1331.         c->read->handler = ngx_ssl_shutdown_handler;
  1332.         c->write->handler = ngx_ssl_shutdown_handler;

  1333.         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  1334.             return NGX_ERROR;
  1335.         }

  1336.         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  1337.             return NGX_ERROR;
  1338.         }

  1339.         if (sslerr == SSL_ERROR_WANT_READ) {
  1340.             ngx_add_timer(c->read, 30000);
  1341.         }

  1342.         return NGX_AGAIN;
  1343.     }

  1344.     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;

  1345.     ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");

  1346.     SSL_free(c->ssl->connection);
  1347.     c->ssl = NULL;

  1348.     return NGX_ERROR;
  1349. }


  1350. static void
  1351. ngx_ssl_shutdown_handler(ngx_event_t *ev)
  1352. {
  1353.     ngx_connection_t           *c;
  1354.     ngx_connection_handler_pt   handler;

  1355.     c = ev->data;
  1356.     handler = c->ssl->handler;

  1357.     if (ev->timedout) {
  1358.         c->timedout = 1;
  1359.     }

  1360.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");

  1361.     if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
  1362.         return;
  1363.     }

  1364.     handler(c);
  1365. }


  1366. static void
  1367. ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
  1368.     char *text)
  1369. {
  1370.     int         n;
  1371.     ngx_uint_t  level;

  1372.     level = NGX_LOG_CRIT;

  1373.     if (sslerr == SSL_ERROR_SYSCALL) {

  1374.         if (err == NGX_ECONNRESET
  1375.             || err == NGX_EPIPE
  1376.             || err == NGX_ENOTCONN
  1377.             || err == NGX_ETIMEDOUT
  1378.             || err == NGX_ECONNREFUSED
  1379.             || err == NGX_ENETDOWN
  1380.             || err == NGX_ENETUNREACH
  1381.             || err == NGX_EHOSTDOWN
  1382.             || err == NGX_EHOSTUNREACH)
  1383.         {
  1384.             switch (c->log_error) {

  1385.             case NGX_ERROR_IGNORE_ECONNRESET:
  1386.             case NGX_ERROR_INFO:
  1387.                 level = NGX_LOG_INFO;
  1388.                 break;

  1389.             case NGX_ERROR_ERR:
  1390.                 level = NGX_LOG_ERR;
  1391.                 break;

  1392.             default:
  1393.                 break;
  1394.             }
  1395.         }

  1396.     } else if (sslerr == SSL_ERROR_SSL) {

  1397.         n = ERR_GET_REASON(ERR_peek_error());

  1398.             /* handshake failures */
  1399.         if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC                        /*  103 */
  1400.             || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  /*  129 */
  1401.             || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
  1402.             || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              /*  151 */
  1403.             || n == SSL_R_EXCESSIVE_MESSAGE_SIZE                     /*  152 */
  1404.             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
  1405.             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
  1406.             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
  1407.             || n == SSL_R_NO_COMPRESSION_SPECIFIED                   /*  187 */
  1408.             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
  1409.             || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
  1410. #ifdef SSL_R_PARSE_TLSEXT
  1411.             || n == SSL_R_PARSE_TLSEXT                               /*  227 */
  1412. #endif
  1413.             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
  1414.             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
  1415.             || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
  1416.             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
  1417.             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
  1418.             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
  1419. #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
  1420.             || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG                   /*  335 */
  1421.             || n == SSL_R_RENEGOTIATION_ENCODING_ERR                 /*  336 */
  1422.             || n == SSL_R_RENEGOTIATION_MISMATCH                     /*  337 */
  1423. #endif
  1424. #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
  1425.             || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED       /*  338 */
  1426. #endif
  1427. #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
  1428.             || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING           /*  345 */
  1429. #endif
  1430. #ifdef SSL_R_INAPPROPRIATE_FALLBACK
  1431.             || n == SSL_R_INAPPROPRIATE_FALLBACK                     /*  373 */
  1432. #endif
  1433.             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
  1434.             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
  1435.             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
  1436.             || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED              /* 1021 */
  1437.             || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW                /* 1022 */
  1438.             || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE          /* 1030 */
  1439.             || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE              /* 1040 */
  1440.             || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE                 /* 1041 */
  1441.             || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE                /* 1042 */
  1442.             || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE        /* 1043 */
  1443.             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED            /* 1044 */
  1444.             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED            /* 1045 */
  1445.             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN            /* 1046 */
  1446.             || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER              /* 1047 */
  1447.             || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA                     /* 1048 */
  1448.             || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED                  /* 1049 */
  1449.             || n == SSL_R_TLSV1_ALERT_DECODE_ERROR                   /* 1050 */
  1450.             || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR                  /* 1051 */
  1451.             || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION             /* 1060 */
  1452.             || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION               /* 1070 */
  1453.             || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY          /* 1071 */
  1454.             || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR                 /* 1080 */
  1455.             || n == SSL_R_TLSV1_ALERT_USER_CANCELLED                 /* 1090 */
  1456.             || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION)              /* 1100 */
  1457.         {
  1458.             switch (c->log_error) {

  1459.             case NGX_ERROR_IGNORE_ECONNRESET:
  1460.             case NGX_ERROR_INFO:
  1461.                 level = NGX_LOG_INFO;
  1462.                 break;

  1463.             case NGX_ERROR_ERR:
  1464.                 level = NGX_LOG_ERR;
  1465.                 break;

  1466.             default:
  1467.                 break;
  1468.             }
  1469.         }
  1470.     }

  1471.     ngx_ssl_error(level, c->log, err, text);
  1472. }


  1473. static void
  1474. ngx_ssl_clear_error(ngx_log_t *log)
  1475. {
  1476.     while (ERR_peek_error()) {
  1477.         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
  1478.     }

  1479.     ERR_clear_error();
  1480. }


  1481. void ngx_cdecl
  1482. ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
  1483. {
  1484.     int          flags;
  1485.     u_long       n;
  1486.     va_list      args;
  1487.     u_char      *p, *last;
  1488.     u_char       errstr[NGX_MAX_CONF_ERRSTR];
  1489.     const char  *data;

  1490.     last = errstr + NGX_MAX_CONF_ERRSTR;

  1491.     va_start(args, fmt);
  1492.     p = ngx_vslprintf(errstr, last - 1, fmt, args);
  1493.     va_end(args);

  1494.     p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);

  1495.     for ( ;; ) {

  1496.         n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);

  1497.         if (n == 0) {
  1498.             break;
  1499.         }

  1500.         if (p >= last) {
  1501.             goto next;
  1502.         }

  1503.         *p++ = ' ';

  1504.         ERR_error_string_n(n, (char *) p, last - p);

  1505.         while (p < last && *p) {
  1506.             p++;
  1507.         }

  1508.         if (p < last && *data && (flags & ERR_TXT_STRING)) {
  1509.             *p++ = ':';
  1510.             p = ngx_cpystrn(p, (u_char *) data, last - p);
  1511.         }

  1512.     next:

  1513.         (void) ERR_get_error();
  1514.     }

  1515.     ngx_log_error(level, log, err, "%s)", errstr);
  1516. }


  1517. ngx_int_t
  1518. ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
  1519.     ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
  1520. {
  1521.     long  cache_mode;

  1522.     SSL_CTX_set_timeout(ssl->ctx, (long) timeout);

  1523.     if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) {
  1524.         return NGX_ERROR;
  1525.     }

  1526.     if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
  1527.         SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
  1528.         return NGX_OK;
  1529.     }

  1530.     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {

  1531.         /*
  1532.          * If the server explicitly says that it does not support
  1533.          * session reuse (see SSL_SESS_CACHE_OFF above), then
  1534.          * Outlook Express fails to upload a sent email to
  1535.          * the Sent Items folder on the IMAP server via a separate IMAP
  1536.          * connection in the background. Therefore we have a special
  1537.          * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
  1538.          * where the server pretends that it supports session reuse,
  1539.          * but it does not actually store any session.
  1540.          */

  1541.         SSL_CTX_set_session_cache_mode(ssl->ctx,
  1542.                                        SSL_SESS_CACHE_SERVER
  1543.                                        |SSL_SESS_CACHE_NO_AUTO_CLEAR
  1544.                                        |SSL_SESS_CACHE_NO_INTERNAL_STORE);

  1545.         SSL_CTX_sess_set_cache_size(ssl->ctx, 1);

  1546.         return NGX_OK;
  1547.     }

  1548.     cache_mode = SSL_SESS_CACHE_SERVER;

  1549.     if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
  1550.         cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
  1551.     }

  1552.     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);

  1553.     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {

  1554.         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
  1555.             SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
  1556.         }
  1557.     }

  1558.     if (shm_zone) {
  1559.         SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
  1560.         SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
  1561.         SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);

  1562.         if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
  1563.             == 0)
  1564.         {
  1565.             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1566.                           "SSL_CTX_set_ex_data() failed");
  1567.             return NGX_ERROR;
  1568.         }
  1569.     }

  1570.     return NGX_OK;
  1571. }


  1572. static ngx_int_t
  1573. ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx)
  1574. {
  1575.     int                   n, i;
  1576.     X509                 *cert;
  1577.     X509_NAME            *name;
  1578.     EVP_MD_CTX            md;
  1579.     unsigned int          len;
  1580.     STACK_OF(X509_NAME)  *list;
  1581.     u_char                buf[EVP_MAX_MD_SIZE];

  1582.     /*
  1583.      * Session ID context is set based on the string provided,
  1584.      * the server certificate, and the client CA list.
  1585.      */

  1586.     EVP_MD_CTX_init(&md);

  1587.     if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) {
  1588.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1589.                       "EVP_DigestInit_ex() failed");
  1590.         goto failed;
  1591.     }

  1592.     if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) {
  1593.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1594.                       "EVP_DigestUpdate() failed");
  1595.         goto failed;
  1596.     }

  1597.     cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);

  1598.     if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
  1599.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1600.                       "X509_digest() failed");
  1601.         goto failed;
  1602.     }

  1603.     if (EVP_DigestUpdate(&md, buf, len) == 0) {
  1604.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1605.                       "EVP_DigestUpdate() failed");
  1606.         goto failed;
  1607.     }

  1608.     list = SSL_CTX_get_client_CA_list(ssl->ctx);

  1609.     if (list != NULL) {
  1610.         n = sk_X509_NAME_num(list);

  1611.         for (i = 0; i < n; i++) {
  1612.             name = sk_X509_NAME_value(list, i);

  1613.             if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) {
  1614.                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1615.                               "X509_NAME_digest() failed");
  1616.                 goto failed;
  1617.             }

  1618.             if (EVP_DigestUpdate(&md, buf, len) == 0) {
  1619.                 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1620.                               "EVP_DigestUpdate() failed");
  1621.                 goto failed;
  1622.             }
  1623.         }
  1624.     }

  1625.     if (EVP_DigestFinal_ex(&md, buf, &len) == 0) {
  1626.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1627.                       "EVP_DigestUpdate() failed");
  1628.         goto failed;
  1629.     }

  1630.     EVP_MD_CTX_cleanup(&md);

  1631.     if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) {
  1632.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  1633.                       "SSL_CTX_set_session_id_context() failed");
  1634.         return NGX_ERROR;
  1635.     }

  1636.     return NGX_OK;

  1637. failed:

  1638.     EVP_MD_CTX_cleanup(&md);

  1639.     return NGX_ERROR;
  1640. }


  1641. ngx_int_t
  1642. ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
  1643. {
  1644.     size_t                    len;
  1645.     ngx_slab_pool_t          *shpool;
  1646.     ngx_ssl_session_cache_t  *cache;

  1647.     if (data) {
  1648.         shm_zone->data = data;
  1649.         return NGX_OK;
  1650.     }

  1651.     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

  1652.     if (shm_zone->shm.exists) {
  1653.         shm_zone->data = shpool->data;
  1654.         return NGX_OK;
  1655.     }

  1656.     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
  1657.     if (cache == NULL) {
  1658.         return NGX_ERROR;
  1659.     }

  1660.     shpool->data = cache;
  1661.     shm_zone->data = cache;

  1662.     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
  1663.                     ngx_ssl_session_rbtree_insert_value);

  1664.     ngx_queue_init(&cache->expire_queue);

  1665.     len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;

  1666.     shpool->log_ctx = ngx_slab_alloc(shpool, len);
  1667.     if (shpool->log_ctx == NULL) {
  1668.         return NGX_ERROR;
  1669.     }

  1670.     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
  1671.                 &shm_zone->shm.name);

  1672.     shpool->log_nomem = 0;

  1673.     return NGX_OK;
  1674. }


  1675. /*
  1676. * The length of the session id is 16 bytes for SSLv2 sessions and
  1677. * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
  1678. * It seems that the typical length of the external ASN1 representation
  1679. * of a session is 118 or 119 bytes for SSLv3/TSLv1.
  1680. *
  1681. * Thus on 32-bit platforms we allocate separately an rbtree node,
  1682. * a session id, and an ASN1 representation, they take accordingly
  1683. * 64, 32, and 128 bytes.
  1684. *
  1685. * On 64-bit platforms we allocate separately an rbtree node + session_id,
  1686. * and an ASN1 representation, they take accordingly 128 and 128 bytes.
  1687. *
  1688. * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
  1689. * so they are outside the code locked by shared pool mutex
  1690. */

  1691. static int
  1692. ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
  1693. {
  1694.     int                       len;
  1695.     u_char                   *p, *id, *cached_sess, *session_id;
  1696.     uint32_t                  hash;
  1697.     SSL_CTX                  *ssl_ctx;
  1698.     unsigned int              session_id_length;
  1699.     ngx_shm_zone_t           *shm_zone;
  1700.     ngx_connection_t         *c;
  1701.     ngx_slab_pool_t          *shpool;
  1702.     ngx_ssl_sess_id_t        *sess_id;
  1703.     ngx_ssl_session_cache_t  *cache;
  1704.     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];

  1705.     len = i2d_SSL_SESSION(sess, NULL);

  1706.     /* do not cache too big session */

  1707.     if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
  1708.         return 0;
  1709.     }

  1710.     p = buf;
  1711.     i2d_SSL_SESSION(sess, &p);

  1712.     c = ngx_ssl_get_connection(ssl_conn);

  1713.     ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
  1714.     shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);

  1715.     cache = shm_zone->data;
  1716.     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

  1717.     ngx_shmtx_lock(&shpool->mutex);

  1718.     /* drop one or two expired sessions */
  1719.     ngx_ssl_expire_sessions(cache, shpool, 1);

  1720.     cached_sess = ngx_slab_alloc_locked(shpool, len);

  1721.     if (cached_sess == NULL) {

  1722.         /* drop the oldest non-expired session and try once more */

  1723.         ngx_ssl_expire_sessions(cache, shpool, 0);

  1724.         cached_sess = ngx_slab_alloc_locked(shpool, len);

  1725.         if (cached_sess == NULL) {
  1726.             sess_id = NULL;
  1727.             goto failed;
  1728.         }
  1729.     }

  1730.     sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));

  1731.     if (sess_id == NULL) {

  1732.         /* drop the oldest non-expired session and try once more */

  1733.         ngx_ssl_expire_sessions(cache, shpool, 0);

  1734.         sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));

  1735.         if (sess_id == NULL) {
  1736.             goto failed;
  1737.         }
  1738.     }

  1739. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL

  1740.     session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);

  1741. #else

  1742.     session_id = sess->session_id;
  1743.     session_id_length = sess->session_id_length;

  1744. #endif

  1745. #if (NGX_PTR_SIZE == 8)

  1746.     id = sess_id->sess_id;

  1747. #else

  1748.     id = ngx_slab_alloc_locked(shpool, session_id_length);

  1749.     if (id == NULL) {

  1750.         /* drop the oldest non-expired session and try once more */

  1751.         ngx_ssl_expire_sessions(cache, shpool, 0);

  1752.         id = ngx_slab_alloc_locked(shpool, session_id_length);

  1753.         if (id == NULL) {
  1754.             goto failed;
  1755.         }
  1756.     }

  1757. #endif

  1758.     ngx_memcpy(cached_sess, buf, len);

  1759.     ngx_memcpy(id, session_id, session_id_length);

  1760.     hash = ngx_crc32_short(session_id, session_id_length);

  1761.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  1762.                    "ssl new session: %08XD:%ud:%d",
  1763.                    hash, session_id_length, len);

  1764.     sess_id->node.key = hash;
  1765.     sess_id->node.data = (u_char) session_id_length;
  1766.     sess_id->id = id;
  1767.     sess_id->len = len;
  1768.     sess_id->session = cached_sess;

  1769.     sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);

  1770.     ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);

  1771.     ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);

  1772.     ngx_shmtx_unlock(&shpool->mutex);

  1773.     return 0;

  1774. failed:

  1775.     if (cached_sess) {
  1776.         ngx_slab_free_locked(shpool, cached_sess);
  1777.     }

  1778.     if (sess_id) {
  1779.         ngx_slab_free_locked(shpool, sess_id);
  1780.     }

  1781.     ngx_shmtx_unlock(&shpool->mutex);

  1782.     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
  1783.                   "could not allocate new session%s", shpool->log_ctx);

  1784.     return 0;
  1785. }


  1786. static ngx_ssl_session_t *
  1787. ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
  1788.     int *copy)
  1789. {
  1790. #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
  1791.     const
  1792. #endif
  1793.     u_char                   *p;
  1794.     uint32_t                  hash;
  1795.     ngx_int_t                 rc;
  1796.     ngx_shm_zone_t           *shm_zone;
  1797.     ngx_slab_pool_t          *shpool;
  1798.     ngx_rbtree_node_t        *node, *sentinel;
  1799.     ngx_ssl_session_t        *sess;
  1800.     ngx_ssl_sess_id_t        *sess_id;
  1801.     ngx_ssl_session_cache_t  *cache;
  1802.     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
  1803. #if (NGX_DEBUG)
  1804.     ngx_connection_t         *c;
  1805. #endif

  1806.     hash = ngx_crc32_short(id, (size_t) len);
  1807.     *copy = 0;

  1808. #if (NGX_DEBUG)
  1809.     c = ngx_ssl_get_connection(ssl_conn);

  1810.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  1811.                    "ssl get session: %08XD:%d", hash, len);
  1812. #endif

  1813.     shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
  1814.                                    ngx_ssl_session_cache_index);

  1815.     cache = shm_zone->data;

  1816.     sess = NULL;

  1817.     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

  1818.     ngx_shmtx_lock(&shpool->mutex);

  1819.     node = cache->session_rbtree.root;
  1820.     sentinel = cache->session_rbtree.sentinel;

  1821.     while (node != sentinel) {

  1822.         if (hash < node->key) {
  1823.             node = node->left;
  1824.             continue;
  1825.         }

  1826.         if (hash > node->key) {
  1827.             node = node->right;
  1828.             continue;
  1829.         }

  1830.         /* hash == node->key */

  1831.         sess_id = (ngx_ssl_sess_id_t *) node;

  1832.         rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data);

  1833.         if (rc == 0) {

  1834.             if (sess_id->expire > ngx_time()) {
  1835.                 ngx_memcpy(buf, sess_id->session, sess_id->len);

  1836.                 ngx_shmtx_unlock(&shpool->mutex);

  1837.                 p = buf;
  1838.                 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);

  1839.                 return sess;
  1840.             }

  1841.             ngx_queue_remove(&sess_id->queue);

  1842.             ngx_rbtree_delete(&cache->session_rbtree, node);

  1843.             ngx_slab_free_locked(shpool, sess_id->session);
  1844. #if (NGX_PTR_SIZE == 4)
  1845.             ngx_slab_free_locked(shpool, sess_id->id);
  1846. #endif
  1847.             ngx_slab_free_locked(shpool, sess_id);

  1848.             sess = NULL;

  1849.             goto done;
  1850.         }

  1851.         node = (rc < 0) ? node->left : node->right;
  1852.     }

  1853. done:

  1854.     ngx_shmtx_unlock(&shpool->mutex);

  1855.     return sess;
  1856. }


  1857. void
  1858. ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
  1859. {
  1860.      SSL_CTX_remove_session(ssl, sess);

  1861.      ngx_ssl_remove_session(ssl, sess);
  1862. }


  1863. static void
  1864. ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
  1865. {
  1866.     u_char                   *id;
  1867.     uint32_t                  hash;
  1868.     ngx_int_t                 rc;
  1869.     unsigned int              len;
  1870.     ngx_shm_zone_t           *shm_zone;
  1871.     ngx_slab_pool_t          *shpool;
  1872.     ngx_rbtree_node_t        *node, *sentinel;
  1873.     ngx_ssl_sess_id_t        *sess_id;
  1874.     ngx_ssl_session_cache_t  *cache;

  1875.     shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);

  1876.     if (shm_zone == NULL) {
  1877.         return;
  1878.     }

  1879.     cache = shm_zone->data;

  1880. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL

  1881.     id = (u_char *) SSL_SESSION_get_id(sess, &len);

  1882. #else

  1883.     id = sess->session_id;
  1884.     len = sess->session_id_length;

  1885. #endif

  1886.     hash = ngx_crc32_short(id, len);

  1887.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
  1888.                    "ssl remove session: %08XD:%ud", hash, len);

  1889.     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

  1890.     ngx_shmtx_lock(&shpool->mutex);

  1891.     node = cache->session_rbtree.root;
  1892.     sentinel = cache->session_rbtree.sentinel;

  1893.     while (node != sentinel) {

  1894.         if (hash < node->key) {
  1895.             node = node->left;
  1896.             continue;
  1897.         }

  1898.         if (hash > node->key) {
  1899.             node = node->right;
  1900.             continue;
  1901.         }

  1902.         /* hash == node->key */

  1903.         sess_id = (ngx_ssl_sess_id_t *) node;

  1904.         rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);

  1905.         if (rc == 0) {

  1906.             ngx_queue_remove(&sess_id->queue);

  1907.             ngx_rbtree_delete(&cache->session_rbtree, node);

  1908.             ngx_slab_free_locked(shpool, sess_id->session);
  1909. #if (NGX_PTR_SIZE == 4)
  1910.             ngx_slab_free_locked(shpool, sess_id->id);
  1911. #endif
  1912.             ngx_slab_free_locked(shpool, sess_id);

  1913.             goto done;
  1914.         }

  1915.         node = (rc < 0) ? node->left : node->right;
  1916.     }

  1917. done:

  1918.     ngx_shmtx_unlock(&shpool->mutex);
  1919. }


  1920. static void
  1921. ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
  1922.     ngx_slab_pool_t *shpool, ngx_uint_t n)
  1923. {
  1924.     time_t              now;
  1925.     ngx_queue_t        *q;
  1926.     ngx_ssl_sess_id_t  *sess_id;

  1927.     now = ngx_time();

  1928.     while (n < 3) {

  1929.         if (ngx_queue_empty(&cache->expire_queue)) {
  1930.             return;
  1931.         }

  1932.         q = ngx_queue_last(&cache->expire_queue);

  1933.         sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);

  1934.         if (n++ != 0 && sess_id->expire > now) {
  1935.             return;
  1936.         }

  1937.         ngx_queue_remove(q);

  1938.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
  1939.                        "expire session: %08Xi", sess_id->node.key);

  1940.         ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);

  1941.         ngx_slab_free_locked(shpool, sess_id->session);
  1942. #if (NGX_PTR_SIZE == 4)
  1943.         ngx_slab_free_locked(shpool, sess_id->id);
  1944. #endif
  1945.         ngx_slab_free_locked(shpool, sess_id);
  1946.     }
  1947. }


  1948. static void
  1949. ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
  1950.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
  1951. {
  1952.     ngx_rbtree_node_t  **p;
  1953.     ngx_ssl_sess_id_t   *sess_id, *sess_id_temp;

  1954.     for ( ;; ) {

  1955.         if (node->key < temp->key) {

  1956.             p = &temp->left;

  1957.         } else if (node->key > temp->key) {

  1958.             p = &temp->right;

  1959.         } else { /* node->key == temp->key */

  1960.             sess_id = (ngx_ssl_sess_id_t *) node;
  1961.             sess_id_temp = (ngx_ssl_sess_id_t *) temp;

  1962.             p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
  1963.                               (size_t) node->data, (size_t) temp->data)
  1964.                  < 0) ? &temp->left : &temp->right;
  1965.         }

  1966.         if (*p == sentinel) {
  1967.             break;
  1968.         }

  1969.         temp = *p;
  1970.     }

  1971.     *p = node;
  1972.     node->parent = temp;
  1973.     node->left = sentinel;
  1974.     node->right = sentinel;
  1975.     ngx_rbt_red(node);
  1976. }


  1977. #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB

  1978. ngx_int_t
  1979. ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
  1980. {
  1981.     u_char                         buf[48];
  1982.     ssize_t                        n;
  1983.     ngx_str_t                     *path;
  1984.     ngx_file_t                     file;
  1985.     ngx_uint_t                     i;
  1986.     ngx_array_t                   *keys;
  1987.     ngx_file_info_t                fi;
  1988.     ngx_ssl_session_ticket_key_t  *key;

  1989.     if (paths == NULL) {
  1990.         return NGX_OK;
  1991.     }

  1992.     keys = ngx_array_create(cf->pool, paths->nelts,
  1993.                             sizeof(ngx_ssl_session_ticket_key_t));
  1994.     if (keys == NULL) {
  1995.         return NGX_ERROR;
  1996.     }

  1997.     path = paths->elts;
  1998.     for (i = 0; i < paths->nelts; i++) {

  1999.         if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) {
  2000.             return NGX_ERROR;
  2001.         }

  2002.         ngx_memzero(&file, sizeof(ngx_file_t));
  2003.         file.name = path[i];
  2004.         file.log = cf->log;

  2005.         file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0);
  2006.         if (file.fd == NGX_INVALID_FILE) {
  2007.             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  2008.                                ngx_open_file_n " \"%V\" failed", &file.name);
  2009.             return NGX_ERROR;
  2010.         }

  2011.         if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
  2012.             ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
  2013.                                ngx_fd_info_n " \"%V\" failed", &file.name);
  2014.             goto failed;
  2015.         }

  2016.         if (ngx_file_size(&fi) != 48) {
  2017.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2018.                                "\"%V\" must be 48 bytes", &file.name);
  2019.             goto failed;
  2020.         }

  2021.         n = ngx_read_file(&file, buf, 48, 0);

  2022.         if (n == NGX_ERROR) {
  2023.             ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
  2024.                                ngx_read_file_n " \"%V\" failed", &file.name);
  2025.             goto failed;
  2026.         }

  2027.         if (n != 48) {
  2028.             ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
  2029.                                ngx_read_file_n " \"%V\" returned only "
  2030.                                "%z bytes instead of 48", &file.name, n);
  2031.             goto failed;
  2032.         }

  2033.         key = ngx_array_push(keys);
  2034.         if (key == NULL) {
  2035.             goto failed;
  2036.         }

  2037.         ngx_memcpy(key->name, buf, 16);
  2038.         ngx_memcpy(key->aes_key, buf + 16, 16);
  2039.         ngx_memcpy(key->hmac_key, buf + 32, 16);

  2040.         if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
  2041.             ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
  2042.                           ngx_close_file_n " \"%V\" failed", &file.name);
  2043.         }
  2044.     }

  2045.     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
  2046.         == 0)
  2047.     {
  2048.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  2049.                       "SSL_CTX_set_ex_data() failed");
  2050.         return NGX_ERROR;
  2051.     }

  2052.     if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
  2053.                                          ngx_ssl_session_ticket_key_callback)
  2054.         == 0)
  2055.     {
  2056.         ngx_log_error(NGX_LOG_WARN, cf->log, 0,
  2057.                       "nginx was built with Session Tickets support, however, "
  2058.                       "now it is linked dynamically to an OpenSSL library "
  2059.                       "which has no tlsext support, therefore Session Tickets "
  2060.                       "are not available");
  2061.     }

  2062.     return NGX_OK;

  2063. failed:

  2064.     if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
  2065.         ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
  2066.                       ngx_close_file_n " \"%V\" failed", &file.name);
  2067.     }

  2068.     return NGX_ERROR;
  2069. }


  2070. #ifdef OPENSSL_NO_SHA256
  2071. #define ngx_ssl_session_ticket_md  EVP_sha1
  2072. #else
  2073. #define ngx_ssl_session_ticket_md  EVP_sha256
  2074. #endif


  2075. static int
  2076. ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
  2077.     unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
  2078.     HMAC_CTX *hctx, int enc)
  2079. {
  2080.     SSL_CTX                       *ssl_ctx;
  2081.     ngx_uint_t                     i;
  2082.     ngx_array_t                   *keys;
  2083.     ngx_ssl_session_ticket_key_t  *key;
  2084. #if (NGX_DEBUG)
  2085.     u_char                         buf[32];
  2086.     ngx_connection_t              *c;
  2087. #endif

  2088.     ssl_ctx = SSL_get_SSL_CTX(ssl_conn);

  2089.     keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
  2090.     if (keys == NULL) {
  2091.         return -1;
  2092.     }

  2093.     key = keys->elts;

  2094. #if (NGX_DEBUG)
  2095.     c = ngx_ssl_get_connection(ssl_conn);
  2096. #endif

  2097.     if (enc == 1) {
  2098.         /* encrypt session ticket */

  2099.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2100.                        "ssl session ticket encrypt, key: \"%*s\" (%s session)",
  2101.                        ngx_hex_dump(buf, key[0].name, 16) - buf, buf,
  2102.                        SSL_session_reused(ssl_conn) ? "reused" : "new");

  2103.         RAND_pseudo_bytes(iv, 16);
  2104.         EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv);
  2105.         HMAC_Init_ex(hctx, key[0].hmac_key, 16,
  2106.                      ngx_ssl_session_ticket_md(), NULL);
  2107.         ngx_memcpy(name, key[0].name, 16);

  2108.         return 0;

  2109.     } else {
  2110.         /* decrypt session ticket */

  2111.         for (i = 0; i < keys->nelts; i++) {
  2112.             if (ngx_memcmp(name, key[i].name, 16) == 0) {
  2113.                 goto found;
  2114.             }
  2115.         }

  2116.         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2117.                        "ssl session ticket decrypt, key: \"%*s\" not found",
  2118.                        ngx_hex_dump(buf, name, 16) - buf, buf);

  2119.         return 0;

  2120.     found:

  2121.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2122.                        "ssl session ticket decrypt, key: \"%*s\"%s",
  2123.                        ngx_hex_dump(buf, key[i].name, 16) - buf, buf,
  2124.                        (i == 0) ? " (default)" : "");

  2125.         HMAC_Init_ex(hctx, key[i].hmac_key, 16,
  2126.                      ngx_ssl_session_ticket_md(), NULL);
  2127.         EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv);

  2128.         return (i == 0) ? 1 : 2 /* renew */;
  2129.     }
  2130. }

  2131. #else

  2132. ngx_int_t
  2133. ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
  2134. {
  2135.     if (paths) {
  2136.         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  2137.                       "\"ssl_session_ticket_keys\" ignored, not supported");
  2138.     }

  2139.     return NGX_OK;
  2140. }

  2141. #endif


  2142. void
  2143. ngx_ssl_cleanup_ctx(void *data)
  2144. {
  2145.     ngx_ssl_t  *ssl = data;

  2146.     SSL_CTX_free(ssl->ctx);
  2147. }


  2148. ngx_int_t
  2149. ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name)
  2150. {
  2151.     X509   *cert;

  2152.     cert = SSL_get_peer_certificate(c->ssl->connection);
  2153.     if (cert == NULL) {
  2154.         return NGX_ERROR;
  2155.     }

  2156. #if (OPENSSL_VERSION_NUMBER >= 0x10002002L && !defined LIBRESSL_VERSION_NUMBER)

  2157.     /* X509_check_host() is only available in OpenSSL 1.0.2+ */

  2158.     if (name->len == 0) {
  2159.         goto failed;
  2160.     }

  2161.     if (X509_check_host(cert, (char *) name->data, name->len, 0, NULL) != 1) {
  2162.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2163.                        "X509_check_host(): no match");
  2164.         goto failed;
  2165.     }

  2166.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2167.                    "X509_check_host(): match");

  2168.     goto found;

  2169. #else
  2170.     {
  2171.     int                      n, i;
  2172.     X509_NAME               *sname;
  2173.     ASN1_STRING             *str;
  2174.     X509_NAME_ENTRY         *entry;
  2175.     GENERAL_NAME            *altname;
  2176.     STACK_OF(GENERAL_NAME)  *altnames;

  2177.     /*
  2178.      * As per RFC6125 and RFC2818, we check subjectAltName extension,
  2179.      * and if it's not present - commonName in Subject is checked.
  2180.      */

  2181.     altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);

  2182.     if (altnames) {
  2183.         n = sk_GENERAL_NAME_num(altnames);

  2184.         for (i = 0; i < n; i++) {
  2185.             altname = sk_GENERAL_NAME_value(altnames, i);

  2186.             if (altname->type != GEN_DNS) {
  2187.                 continue;
  2188.             }

  2189.             str = altname->d.dNSName;

  2190.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2191.                            "SSL subjectAltName: \"%*s\"",
  2192.                            ASN1_STRING_length(str), ASN1_STRING_data(str));

  2193.             if (ngx_ssl_check_name(name, str) == NGX_OK) {
  2194.                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2195.                                "SSL subjectAltName: match");
  2196.                 GENERAL_NAMES_free(altnames);
  2197.                 goto found;
  2198.             }
  2199.         }

  2200.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2201.                        "SSL subjectAltName: no match");

  2202.         GENERAL_NAMES_free(altnames);
  2203.         goto failed;
  2204.     }

  2205.     /*
  2206.      * If there is no subjectAltName extension, check commonName
  2207.      * in Subject.  While RFC2818 requires to only check "most specific"
  2208.      * CN, both Apache and OpenSSL check all CNs, and so do we.
  2209.      */

  2210.     sname = X509_get_subject_name(cert);

  2211.     if (sname == NULL) {
  2212.         goto failed;
  2213.     }

  2214.     i = -1;
  2215.     for ( ;; ) {
  2216.         i = X509_NAME_get_index_by_NID(sname, NID_commonName, i);

  2217.         if (i < 0) {
  2218.             break;
  2219.         }

  2220.         entry = X509_NAME_get_entry(sname, i);
  2221.         str = X509_NAME_ENTRY_get_data(entry);

  2222.         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2223.                        "SSL commonName: \"%*s\"",
  2224.                        ASN1_STRING_length(str), ASN1_STRING_data(str));

  2225.         if (ngx_ssl_check_name(name, str) == NGX_OK) {
  2226.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2227.                            "SSL commonName: match");
  2228.             goto found;
  2229.         }
  2230.     }

  2231.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  2232.                    "SSL commonName: no match");
  2233.     }
  2234. #endif

  2235. failed:

  2236.     X509_free(cert);
  2237.     return NGX_ERROR;

  2238. found:

  2239.     X509_free(cert);
  2240.     return NGX_OK;
  2241. }


  2242. #if (OPENSSL_VERSION_NUMBER < 0x10002002L || defined LIBRESSL_VERSION_NUMBER)

  2243. static ngx_int_t
  2244. ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *pattern)
  2245. {
  2246.     u_char  *s, *p, *end;
  2247.     size_t   slen, plen;

  2248.     s = name->data;
  2249.     slen = name->len;

  2250.     p = ASN1_STRING_data(pattern);
  2251.     plen = ASN1_STRING_length(pattern);

  2252.     if (slen == plen && ngx_strncasecmp(s, p, plen) == 0) {
  2253.         return NGX_OK;
  2254.     }

  2255.     if (plen > 2 && p[0] == '*' && p[1] == '.') {
  2256.         plen -= 1;
  2257.         p += 1;

  2258.         end = s + slen;
  2259.         s = ngx_strlchr(s, end, '.');

  2260.         if (s == NULL) {
  2261.             return NGX_ERROR;
  2262.         }

  2263.         slen = end - s;

  2264.         if (plen == slen && ngx_strncasecmp(s, p, plen) == 0) {
  2265.             return NGX_OK;
  2266.         }
  2267.     }

  2268.     return NGX_ERROR;
  2269. }

  2270. #endif


  2271. ngx_int_t
  2272. ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2273. {
  2274.     s->data = (u_char *) SSL_get_version(c->ssl->connection);
  2275.     return NGX_OK;
  2276. }


  2277. ngx_int_t
  2278. ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2279. {
  2280.     s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
  2281.     return NGX_OK;
  2282. }


  2283. ngx_int_t
  2284. ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2285. {
  2286.     u_char        *buf;
  2287.     SSL_SESSION   *sess;
  2288.     unsigned int   len;

  2289.     sess = SSL_get0_session(c->ssl->connection);
  2290.     if (sess == NULL) {
  2291.         s->len = 0;
  2292.         return NGX_OK;
  2293.     }

  2294. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL

  2295.     buf = (u_char *) SSL_SESSION_get_id(sess, &len);

  2296. #else

  2297.     buf = sess->session_id;
  2298.     len = sess->session_id_length;

  2299. #endif

  2300.     s->len = 2 * len;
  2301.     s->data = ngx_pnalloc(pool, 2 * len);
  2302.     if (s->data == NULL) {
  2303.         return NGX_ERROR;
  2304.     }

  2305.     ngx_hex_dump(s->data, buf, len);

  2306.     return NGX_OK;
  2307. }


  2308. ngx_int_t
  2309. ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2310. {
  2311.     if (SSL_session_reused(c->ssl->connection)) {
  2312.         ngx_str_set(s, "r");

  2313.     } else {
  2314.         ngx_str_set(s, ".");
  2315.     }

  2316.     return NGX_OK;
  2317. }


  2318. ngx_int_t
  2319. ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2320. {
  2321. #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME

  2322.     const char  *servername;

  2323.     servername = SSL_get_servername(c->ssl->connection,
  2324.                                     TLSEXT_NAMETYPE_host_name);
  2325.     if (servername) {
  2326.         s->data = (u_char *) servername;
  2327.         s->len = ngx_strlen(servername);
  2328.         return NGX_OK;
  2329.     }

  2330. #endif

  2331.     s->len = 0;
  2332.     return NGX_OK;
  2333. }


  2334. ngx_int_t
  2335. ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2336. {
  2337.     size_t   len;
  2338.     BIO     *bio;
  2339.     X509    *cert;

  2340.     s->len = 0;

  2341.     cert = SSL_get_peer_certificate(c->ssl->connection);
  2342.     if (cert == NULL) {
  2343.         return NGX_OK;
  2344.     }

  2345.     bio = BIO_new(BIO_s_mem());
  2346.     if (bio == NULL) {
  2347.         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
  2348.         X509_free(cert);
  2349.         return NGX_ERROR;
  2350.     }

  2351.     if (PEM_write_bio_X509(bio, cert) == 0) {
  2352.         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
  2353.         goto failed;
  2354.     }

  2355.     len = BIO_pending(bio);
  2356.     s->len = len;

  2357.     s->data = ngx_pnalloc(pool, len);
  2358.     if (s->data == NULL) {
  2359.         goto failed;
  2360.     }

  2361.     BIO_read(bio, s->data, len);

  2362.     BIO_free(bio);
  2363.     X509_free(cert);

  2364.     return NGX_OK;

  2365. failed:

  2366.     BIO_free(bio);
  2367.     X509_free(cert);

  2368.     return NGX_ERROR;
  2369. }


  2370. ngx_int_t
  2371. ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2372. {
  2373.     u_char      *p;
  2374.     size_t       len;
  2375.     ngx_uint_t   i;
  2376.     ngx_str_t    cert;

  2377.     if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
  2378.         return NGX_ERROR;
  2379.     }

  2380.     if (cert.len == 0) {
  2381.         s->len = 0;
  2382.         return NGX_OK;
  2383.     }

  2384.     len = cert.len - 1;

  2385.     for (i = 0; i < cert.len - 1; i++) {
  2386.         if (cert.data[i] == LF) {
  2387.             len++;
  2388.         }
  2389.     }

  2390.     s->len = len;
  2391.     s->data = ngx_pnalloc(pool, len);
  2392.     if (s->data == NULL) {
  2393.         return NGX_ERROR;
  2394.     }

  2395.     p = s->data;

  2396.     for (i = 0; i < cert.len - 1; i++) {
  2397.         *p++ = cert.data[i];
  2398.         if (cert.data[i] == LF) {
  2399.             *p++ = '\t';
  2400.         }
  2401.     }

  2402.     return NGX_OK;
  2403. }


  2404. ngx_int_t
  2405. ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2406. {
  2407.     char       *p;
  2408.     size_t      len;
  2409.     X509       *cert;
  2410.     X509_NAME  *name;

  2411.     s->len = 0;

  2412.     cert = SSL_get_peer_certificate(c->ssl->connection);
  2413.     if (cert == NULL) {
  2414.         return NGX_OK;
  2415.     }

  2416.     name = X509_get_subject_name(cert);
  2417.     if (name == NULL) {
  2418.         X509_free(cert);
  2419.         return NGX_ERROR;
  2420.     }

  2421.     p = X509_NAME_oneline(name, NULL, 0);

  2422.     for (len = 0; p[len]; len++) { /* void */ }

  2423.     s->len = len;
  2424.     s->data = ngx_pnalloc(pool, len);
  2425.     if (s->data == NULL) {
  2426.         OPENSSL_free(p);
  2427.         X509_free(cert);
  2428.         return NGX_ERROR;
  2429.     }

  2430.     ngx_memcpy(s->data, p, len);

  2431.     OPENSSL_free(p);
  2432.     X509_free(cert);

  2433.     return NGX_OK;
  2434. }


  2435. ngx_int_t
  2436. ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2437. {
  2438.     char       *p;
  2439.     size_t      len;
  2440.     X509       *cert;
  2441.     X509_NAME  *name;

  2442.     s->len = 0;

  2443.     cert = SSL_get_peer_certificate(c->ssl->connection);
  2444.     if (cert == NULL) {
  2445.         return NGX_OK;
  2446.     }

  2447.     name = X509_get_issuer_name(cert);
  2448.     if (name == NULL) {
  2449.         X509_free(cert);
  2450.         return NGX_ERROR;
  2451.     }

  2452.     p = X509_NAME_oneline(name, NULL, 0);

  2453.     for (len = 0; p[len]; len++) { /* void */ }

  2454.     s->len = len;
  2455.     s->data = ngx_pnalloc(pool, len);
  2456.     if (s->data == NULL) {
  2457.         OPENSSL_free(p);
  2458.         X509_free(cert);
  2459.         return NGX_ERROR;
  2460.     }

  2461.     ngx_memcpy(s->data, p, len);

  2462.     OPENSSL_free(p);
  2463.     X509_free(cert);

  2464.     return NGX_OK;
  2465. }


  2466. ngx_int_t
  2467. ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2468. {
  2469.     size_t   len;
  2470.     X509    *cert;
  2471.     BIO     *bio;

  2472.     s->len = 0;

  2473.     cert = SSL_get_peer_certificate(c->ssl->connection);
  2474.     if (cert == NULL) {
  2475.         return NGX_OK;
  2476.     }

  2477.     bio = BIO_new(BIO_s_mem());
  2478.     if (bio == NULL) {
  2479.         X509_free(cert);
  2480.         return NGX_ERROR;
  2481.     }

  2482.     i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
  2483.     len = BIO_pending(bio);

  2484.     s->len = len;
  2485.     s->data = ngx_pnalloc(pool, len);
  2486.     if (s->data == NULL) {
  2487.         BIO_free(bio);
  2488.         X509_free(cert);
  2489.         return NGX_ERROR;
  2490.     }

  2491.     BIO_read(bio, s->data, len);
  2492.     BIO_free(bio);
  2493.     X509_free(cert);

  2494.     return NGX_OK;
  2495. }


  2496. ngx_int_t
  2497. ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2498. {
  2499.     X509          *cert;
  2500.     unsigned int   len;
  2501.     u_char         buf[EVP_MAX_MD_SIZE];

  2502.     s->len = 0;

  2503.     cert = SSL_get_peer_certificate(c->ssl->connection);
  2504.     if (cert == NULL) {
  2505.         return NGX_OK;
  2506.     }

  2507.     if (!X509_digest(cert, EVP_sha1(), buf, &len)) {
  2508.         X509_free(cert);
  2509.         return NGX_ERROR;
  2510.     }

  2511.     s->len = 2 * len;
  2512.     s->data = ngx_pnalloc(pool, 2 * len);
  2513.     if (s->data == NULL) {
  2514.         X509_free(cert);
  2515.         return NGX_ERROR;
  2516.     }

  2517.     ngx_hex_dump(s->data, buf, len);

  2518.     X509_free(cert);

  2519.     return NGX_OK;
  2520. }


  2521. ngx_int_t
  2522. ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
  2523. {
  2524.     X509  *cert;

  2525.     if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
  2526.         ngx_str_set(s, "FAILED");
  2527.         return NGX_OK;
  2528.     }

  2529.     cert = SSL_get_peer_certificate(c->ssl->connection);

  2530.     if (cert) {
  2531.         ngx_str_set(s, "SUCCESS");

  2532.     } else {
  2533.         ngx_str_set(s, "NONE");
  2534.     }

  2535.     X509_free(cert);

  2536.     return NGX_OK;
  2537. }


  2538. static void *
  2539. ngx_openssl_create_conf(ngx_cycle_t *cycle)
  2540. {
  2541.     ngx_openssl_conf_t  *oscf;

  2542.     oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
  2543.     if (oscf == NULL) {
  2544.         return NULL;
  2545.     }

  2546.     /*
  2547.      * set by ngx_pcalloc():
  2548.      *
  2549.      *     oscf->engine = 0;
  2550.      */

  2551.     return oscf;
  2552. }


  2553. static char *
  2554. ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  2555. {
  2556. #ifndef OPENSSL_NO_ENGINE

  2557.     ngx_openssl_conf_t *oscf = conf;

  2558.     ENGINE     *engine;
  2559.     ngx_str_t  *value;

  2560.     if (oscf->engine) {
  2561.         return "is duplicate";
  2562.     }

  2563.     oscf->engine = 1;

  2564.     value = cf->args->elts;

  2565.     engine = ENGINE_by_id((const char *) value[1].data);

  2566.     if (engine == NULL) {
  2567.         ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
  2568.                       "ENGINE_by_id(\"%V\") failed", &value[1]);
  2569.         return NGX_CONF_ERROR;
  2570.     }

  2571.     if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
  2572.         ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
  2573.                       "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
  2574.                       &value[1]);

  2575.         ENGINE_free(engine);

  2576.         return NGX_CONF_ERROR;
  2577.     }

  2578.     ENGINE_free(engine);

  2579.     return NGX_CONF_OK;

  2580. #else

  2581.     return "is not supported";

  2582. #endif
  2583. }


  2584. static void
  2585. ngx_openssl_exit(ngx_cycle_t *cycle)
  2586. {
  2587.     EVP_cleanup();
  2588. #ifndef OPENSSL_NO_ENGINE
  2589.     ENGINE_cleanup();
  2590. #endif
  2591. }