src/http/modules/ngx_http_ssl_module.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_http.h>


  8. typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
  9.     ngx_pool_t *pool, ngx_str_t *s);


  10. #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
  11. #define NGX_DEFAULT_ECDH_CURVE  "prime256v1"

  12. #define NGX_HTTP_NPN_ADVERTISE  "\x08http/1.1"


  13. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
  14. static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
  15.     const unsigned char **out, unsigned char *outlen,
  16.     const unsigned char *in, unsigned int inlen, void *arg);
  17. #endif

  18. #ifdef TLSEXT_TYPE_next_proto_neg
  19. static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
  20.     const unsigned char **out, unsigned int *outlen, void *arg);
  21. #endif

  22. static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
  23.     ngx_http_variable_value_t *v, uintptr_t data);
  24. static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
  25.     ngx_http_variable_value_t *v, uintptr_t data);

  26. static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
  27. static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
  28. static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
  29.     void *parent, void *child);

  30. static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
  31.     void *conf);
  32. static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
  33.     void *conf);
  34. static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
  35.     void *conf);

  36. static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);


  37. static ngx_conf_bitmask_t  ngx_http_ssl_protocols[] = {
  38.     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
  39.     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
  40.     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
  41.     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
  42.     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
  43.     { ngx_null_string, 0 }
  44. };


  45. static ngx_conf_enum_t  ngx_http_ssl_verify[] = {
  46.     { ngx_string("off"), 0 },
  47.     { ngx_string("on"), 1 },
  48.     { ngx_string("optional"), 2 },
  49.     { ngx_string("optional_no_ca"), 3 },
  50.     { ngx_null_string, 0 }
  51. };


  52. static ngx_command_t  ngx_http_ssl_commands[] = {

  53.     { ngx_string("ssl"),
  54.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  55.       ngx_http_ssl_enable,
  56.       NGX_HTTP_SRV_CONF_OFFSET,
  57.       offsetof(ngx_http_ssl_srv_conf_t, enable),
  58.       NULL },

  59.     { ngx_string("ssl_certificate"),
  60.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  61.       ngx_conf_set_str_slot,
  62.       NGX_HTTP_SRV_CONF_OFFSET,
  63.       offsetof(ngx_http_ssl_srv_conf_t, certificate),
  64.       NULL },

  65.     { ngx_string("ssl_certificate_key"),
  66.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  67.       ngx_conf_set_str_slot,
  68.       NGX_HTTP_SRV_CONF_OFFSET,
  69.       offsetof(ngx_http_ssl_srv_conf_t, certificate_key),
  70.       NULL },

  71.     { ngx_string("ssl_password_file"),
  72.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  73.       ngx_http_ssl_password_file,
  74.       NGX_HTTP_SRV_CONF_OFFSET,
  75.       0,
  76.       NULL },

  77.     { ngx_string("ssl_dhparam"),
  78.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  79.       ngx_conf_set_str_slot,
  80.       NGX_HTTP_SRV_CONF_OFFSET,
  81.       offsetof(ngx_http_ssl_srv_conf_t, dhparam),
  82.       NULL },

  83.     { ngx_string("ssl_ecdh_curve"),
  84.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  85.       ngx_conf_set_str_slot,
  86.       NGX_HTTP_SRV_CONF_OFFSET,
  87.       offsetof(ngx_http_ssl_srv_conf_t, ecdh_curve),
  88.       NULL },

  89.     { ngx_string("ssl_protocols"),
  90.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
  91.       ngx_conf_set_bitmask_slot,
  92.       NGX_HTTP_SRV_CONF_OFFSET,
  93.       offsetof(ngx_http_ssl_srv_conf_t, protocols),
  94.       &ngx_http_ssl_protocols },

  95.     { ngx_string("ssl_ciphers"),
  96.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  97.       ngx_conf_set_str_slot,
  98.       NGX_HTTP_SRV_CONF_OFFSET,
  99.       offsetof(ngx_http_ssl_srv_conf_t, ciphers),
  100.       NULL },

  101.     { ngx_string("ssl_buffer_size"),
  102.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  103.       ngx_conf_set_size_slot,
  104.       NGX_HTTP_SRV_CONF_OFFSET,
  105.       offsetof(ngx_http_ssl_srv_conf_t, buffer_size),
  106.       NULL },

  107.     { ngx_string("ssl_verify_client"),
  108.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  109.       ngx_conf_set_enum_slot,
  110.       NGX_HTTP_SRV_CONF_OFFSET,
  111.       offsetof(ngx_http_ssl_srv_conf_t, verify),
  112.       &ngx_http_ssl_verify },

  113.     { ngx_string("ssl_verify_depth"),
  114.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  115.       ngx_conf_set_num_slot,
  116.       NGX_HTTP_SRV_CONF_OFFSET,
  117.       offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
  118.       NULL },

  119.     { ngx_string("ssl_client_certificate"),
  120.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  121.       ngx_conf_set_str_slot,
  122.       NGX_HTTP_SRV_CONF_OFFSET,
  123.       offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
  124.       NULL },

  125.     { ngx_string("ssl_trusted_certificate"),
  126.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  127.       ngx_conf_set_str_slot,
  128.       NGX_HTTP_SRV_CONF_OFFSET,
  129.       offsetof(ngx_http_ssl_srv_conf_t, trusted_certificate),
  130.       NULL },

  131.     { ngx_string("ssl_prefer_server_ciphers"),
  132.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  133.       ngx_conf_set_flag_slot,
  134.       NGX_HTTP_SRV_CONF_OFFSET,
  135.       offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers),
  136.       NULL },

  137.     { ngx_string("ssl_session_cache"),
  138.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
  139.       ngx_http_ssl_session_cache,
  140.       NGX_HTTP_SRV_CONF_OFFSET,
  141.       0,
  142.       NULL },

  143.     { ngx_string("ssl_session_tickets"),
  144.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  145.       ngx_conf_set_flag_slot,
  146.       NGX_HTTP_SRV_CONF_OFFSET,
  147.       offsetof(ngx_http_ssl_srv_conf_t, session_tickets),
  148.       NULL },

  149.     { ngx_string("ssl_session_ticket_key"),
  150.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  151.       ngx_conf_set_str_array_slot,
  152.       NGX_HTTP_SRV_CONF_OFFSET,
  153.       offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys),
  154.       NULL },

  155.     { ngx_string("ssl_session_timeout"),
  156.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  157.       ngx_conf_set_sec_slot,
  158.       NGX_HTTP_SRV_CONF_OFFSET,
  159.       offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
  160.       NULL },

  161.     { ngx_string("ssl_crl"),
  162.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  163.       ngx_conf_set_str_slot,
  164.       NGX_HTTP_SRV_CONF_OFFSET,
  165.       offsetof(ngx_http_ssl_srv_conf_t, crl),
  166.       NULL },

  167.     { ngx_string("ssl_stapling"),
  168.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  169.       ngx_conf_set_flag_slot,
  170.       NGX_HTTP_SRV_CONF_OFFSET,
  171.       offsetof(ngx_http_ssl_srv_conf_t, stapling),
  172.       NULL },

  173.     { ngx_string("ssl_stapling_file"),
  174.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  175.       ngx_conf_set_str_slot,
  176.       NGX_HTTP_SRV_CONF_OFFSET,
  177.       offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
  178.       NULL },

  179.     { ngx_string("ssl_stapling_responder"),
  180.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  181.       ngx_conf_set_str_slot,
  182.       NGX_HTTP_SRV_CONF_OFFSET,
  183.       offsetof(ngx_http_ssl_srv_conf_t, stapling_responder),
  184.       NULL },

  185.     { ngx_string("ssl_stapling_verify"),
  186.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  187.       ngx_conf_set_flag_slot,
  188.       NGX_HTTP_SRV_CONF_OFFSET,
  189.       offsetof(ngx_http_ssl_srv_conf_t, stapling_verify),
  190.       NULL },

  191.       ngx_null_command
  192. };


  193. static ngx_http_module_t  ngx_http_ssl_module_ctx = {
  194.     ngx_http_ssl_add_variables,            /* preconfiguration */
  195.     ngx_http_ssl_init,                     /* postconfiguration */

  196.     NULL,                                  /* create main configuration */
  197.     NULL,                                  /* init main configuration */

  198.     ngx_http_ssl_create_srv_conf,          /* create server configuration */
  199.     ngx_http_ssl_merge_srv_conf,           /* merge server configuration */

  200.     NULL,                                  /* create location configuration */
  201.     NULL                                   /* merge location configuration */
  202. };


  203. ngx_module_t  ngx_http_ssl_module = {
  204.     NGX_MODULE_V1,
  205.     &ngx_http_ssl_module_ctx,              /* module context */
  206.     ngx_http_ssl_commands,                 /* module directives */
  207.     NGX_HTTP_MODULE,                       /* module type */
  208.     NULL,                                  /* init master */
  209.     NULL,                                  /* init module */
  210.     NULL,                                  /* init process */
  211.     NULL,                                  /* init thread */
  212.     NULL,                                  /* exit thread */
  213.     NULL,                                  /* exit process */
  214.     NULL,                                  /* exit master */
  215.     NGX_MODULE_V1_PADDING
  216. };


  217. static ngx_http_variable_t  ngx_http_ssl_vars[] = {

  218.     { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
  219.       (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },

  220.     { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
  221.       (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },

  222.     { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
  223.       (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },

  224.     { ngx_string("ssl_session_reused"), NULL, ngx_http_ssl_variable,
  225.       (uintptr_t) ngx_ssl_get_session_reused, NGX_HTTP_VAR_CHANGEABLE, 0 },

  226.     { ngx_string("ssl_server_name"), NULL, ngx_http_ssl_variable,
  227.       (uintptr_t) ngx_ssl_get_server_name, NGX_HTTP_VAR_CHANGEABLE, 0 },

  228.     { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
  229.       (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },

  230.     { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
  231.       (uintptr_t) ngx_ssl_get_raw_certificate,
  232.       NGX_HTTP_VAR_CHANGEABLE, 0 },

  233.     { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
  234.       (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },

  235.     { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
  236.       (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },

  237.     { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
  238.       (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },

  239.     { ngx_string("ssl_client_fingerprint"), NULL, ngx_http_ssl_variable,
  240.       (uintptr_t) ngx_ssl_get_fingerprint, NGX_HTTP_VAR_CHANGEABLE, 0 },

  241.     { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable,
  242.       (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 },

  243.     { ngx_null_string, NULL, NULL, 0, 0, 0 }
  244. };


  245. static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");


  246. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation

  247. static int
  248. ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
  249.     unsigned char *outlen, const unsigned char *in, unsigned int inlen,
  250.     void *arg)
  251. {
  252.     unsigned int            srvlen;
  253.     unsigned char          *srv;
  254. #if (NGX_DEBUG)
  255.     unsigned int            i;
  256. #endif
  257. #if (NGX_HTTP_SPDY)
  258.     ngx_http_connection_t  *hc;
  259. #endif
  260. #if (NGX_HTTP_SPDY || NGX_DEBUG)
  261.     ngx_connection_t       *c;

  262.     c = ngx_ssl_get_connection(ssl_conn);
  263. #endif

  264. #if (NGX_DEBUG)
  265.     for (i = 0; i < inlen; i += in[i] + 1) {
  266.          ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  267.                         "SSL ALPN supported by client: %*s", in[i], &in[i + 1]);
  268.     }
  269. #endif

  270. #if (NGX_HTTP_SPDY)
  271.     hc = c->data;

  272.     if (hc->addr_conf->spdy) {
  273.         srv = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
  274.         srvlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;

  275.     } else
  276. #endif
  277.     {
  278.         srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
  279.         srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
  280.     }

  281.     if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
  282.                               in, inlen)
  283.         != OPENSSL_NPN_NEGOTIATED)
  284.     {
  285.         return SSL_TLSEXT_ERR_NOACK;
  286.     }

  287.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  288.                    "SSL ALPN selected: %*s", *outlen, *out);

  289.     return SSL_TLSEXT_ERR_OK;
  290. }

  291. #endif


  292. #ifdef TLSEXT_TYPE_next_proto_neg

  293. static int
  294. ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
  295.     const unsigned char **out, unsigned int *outlen, void *arg)
  296. {
  297. #if (NGX_HTTP_SPDY || NGX_DEBUG)
  298.     ngx_connection_t  *c;

  299.     c = ngx_ssl_get_connection(ssl_conn);
  300.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised");
  301. #endif

  302. #if (NGX_HTTP_SPDY)
  303.     {
  304.     ngx_http_connection_t  *hc;

  305.     hc = c->data;

  306.     if (hc->addr_conf->spdy) {
  307.         *out = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
  308.         *outlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;

  309.         return SSL_TLSEXT_ERR_OK;
  310.     }
  311.     }
  312. #endif

  313.     *out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
  314.     *outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;

  315.     return SSL_TLSEXT_ERR_OK;
  316. }

  317. #endif


  318. static ngx_int_t
  319. ngx_http_ssl_static_variable(ngx_http_request_t *r,
  320.     ngx_http_variable_value_t *v, uintptr_t data)
  321. {
  322.     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;

  323.     size_t     len;
  324.     ngx_str_t  s;

  325.     if (r->connection->ssl) {

  326.         (void) handler(r->connection, NULL, &s);

  327.         v->data = s.data;

  328.         for (len = 0; v->data[len]; len++) { /* void */ }

  329.         v->len = len;
  330.         v->valid = 1;
  331.         v->no_cacheable = 0;
  332.         v->not_found = 0;

  333.         return NGX_OK;
  334.     }

  335.     v->not_found = 1;

  336.     return NGX_OK;
  337. }


  338. static ngx_int_t
  339. ngx_http_ssl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  340.     uintptr_t data)
  341. {
  342.     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;

  343.     ngx_str_t  s;

  344.     if (r->connection->ssl) {

  345.         if (handler(r->connection, r->pool, &s) != NGX_OK) {
  346.             return NGX_ERROR;
  347.         }

  348.         v->len = s.len;
  349.         v->data = s.data;

  350.         if (v->len) {
  351.             v->valid = 1;
  352.             v->no_cacheable = 0;
  353.             v->not_found = 0;

  354.             return NGX_OK;
  355.         }
  356.     }

  357.     v->not_found = 1;

  358.     return NGX_OK;
  359. }


  360. static ngx_int_t
  361. ngx_http_ssl_add_variables(ngx_conf_t *cf)
  362. {
  363.     ngx_http_variable_t  *var, *v;

  364.     for (v = ngx_http_ssl_vars; v->name.len; v++) {
  365.         var = ngx_http_add_variable(cf, &v->name, v->flags);
  366.         if (var == NULL) {
  367.             return NGX_ERROR;
  368.         }

  369.         var->get_handler = v->get_handler;
  370.         var->data = v->data;
  371.     }

  372.     return NGX_OK;
  373. }


  374. static void *
  375. ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
  376. {
  377.     ngx_http_ssl_srv_conf_t  *sscf;

  378.     sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
  379.     if (sscf == NULL) {
  380.         return NULL;
  381.     }

  382.     /*
  383.      * set by ngx_pcalloc():
  384.      *
  385.      *     sscf->protocols = 0;
  386.      *     sscf->certificate = { 0, NULL };
  387.      *     sscf->certificate_key = { 0, NULL };
  388.      *     sscf->dhparam = { 0, NULL };
  389.      *     sscf->ecdh_curve = { 0, NULL };
  390.      *     sscf->client_certificate = { 0, NULL };
  391.      *     sscf->trusted_certificate = { 0, NULL };
  392.      *     sscf->crl = { 0, NULL };
  393.      *     sscf->ciphers = { 0, NULL };
  394.      *     sscf->shm_zone = NULL;
  395.      *     sscf->stapling_file = { 0, NULL };
  396.      *     sscf->stapling_responder = { 0, NULL };
  397.      */

  398.     sscf->enable = NGX_CONF_UNSET;
  399.     sscf->prefer_server_ciphers = NGX_CONF_UNSET;
  400.     sscf->buffer_size = NGX_CONF_UNSET_SIZE;
  401.     sscf->verify = NGX_CONF_UNSET_UINT;
  402.     sscf->verify_depth = NGX_CONF_UNSET_UINT;
  403.     sscf->passwords = NGX_CONF_UNSET_PTR;
  404.     sscf->builtin_session_cache = NGX_CONF_UNSET;
  405.     sscf->session_timeout = NGX_CONF_UNSET;
  406.     sscf->session_tickets = NGX_CONF_UNSET;
  407.     sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
  408.     sscf->stapling = NGX_CONF_UNSET;
  409.     sscf->stapling_verify = NGX_CONF_UNSET;

  410.     return sscf;
  411. }


  412. static char *
  413. ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
  414. {
  415.     ngx_http_ssl_srv_conf_t *prev = parent;
  416.     ngx_http_ssl_srv_conf_t *conf = child;

  417.     ngx_pool_cleanup_t  *cln;

  418.     if (conf->enable == NGX_CONF_UNSET) {
  419.         if (prev->enable == NGX_CONF_UNSET) {
  420.             conf->enable = 0;

  421.         } else {
  422.             conf->enable = prev->enable;
  423.             conf->file = prev->file;
  424.             conf->line = prev->line;
  425.         }
  426.     }

  427.     ngx_conf_merge_value(conf->session_timeout,
  428.                          prev->session_timeout, 300);

  429.     ngx_conf_merge_value(conf->prefer_server_ciphers,
  430.                          prev->prefer_server_ciphers, 0);

  431.     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
  432.                          (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1
  433.                           |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));

  434.     ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
  435.                          NGX_SSL_BUFSIZE);

  436.     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
  437.     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);

  438.     ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
  439.     ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");

  440.     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);

  441.     ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");

  442.     ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
  443.                          "");
  444.     ngx_conf_merge_str_value(conf->trusted_certificate,
  445.                          prev->trusted_certificate, "");
  446.     ngx_conf_merge_str_value(conf->crl, prev->crl, "");

  447.     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
  448.                          NGX_DEFAULT_ECDH_CURVE);

  449.     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);

  450.     ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
  451.     ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
  452.     ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
  453.     ngx_conf_merge_str_value(conf->stapling_responder,
  454.                          prev->stapling_responder, "");

  455.     conf->ssl.log = cf->log;

  456.     if (conf->enable) {

  457.         if (conf->certificate.len == 0) {
  458.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  459.                           "no \"ssl_certificate\" is defined for "
  460.                           "the \"ssl\" directive in %s:%ui",
  461.                           conf->file, conf->line);
  462.             return NGX_CONF_ERROR;
  463.         }

  464.         if (conf->certificate_key.len == 0) {
  465.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  466.                           "no \"ssl_certificate_key\" is defined for "
  467.                           "the \"ssl\" directive in %s:%ui",
  468.                           conf->file, conf->line);
  469.             return NGX_CONF_ERROR;
  470.         }

  471.     } else {

  472.         if (conf->certificate.len == 0) {
  473.             return NGX_CONF_OK;
  474.         }

  475.         if (conf->certificate_key.len == 0) {
  476.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  477.                           "no \"ssl_certificate_key\" is defined "
  478.                           "for certificate \"%V\"", &conf->certificate);
  479.             return NGX_CONF_ERROR;
  480.         }
  481.     }

  482.     if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
  483.         return NGX_CONF_ERROR;
  484.     }

  485. #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME

  486.     if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
  487.                                                ngx_http_ssl_servername)
  488.         == 0)
  489.     {
  490.         ngx_log_error(NGX_LOG_WARN, cf->log, 0,
  491.             "nginx was built with SNI support, however, now it is linked "
  492.             "dynamically to an OpenSSL library which has no tlsext support, "
  493.             "therefore SNI is not available");
  494.     }

  495. #endif

  496. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
  497.     SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL);
  498. #endif

  499. #ifdef TLSEXT_TYPE_next_proto_neg
  500.     SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx,
  501.                                           ngx_http_ssl_npn_advertised, NULL);
  502. #endif

  503.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  504.     if (cln == NULL) {
  505.         return NGX_CONF_ERROR;
  506.     }

  507.     cln->handler = ngx_ssl_cleanup_ctx;
  508.     cln->data = &conf->ssl;

  509.     if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
  510.                             &conf->certificate_key, conf->passwords)
  511.         != NGX_OK)
  512.     {
  513.         return NGX_CONF_ERROR;
  514.     }

  515.     if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
  516.                                 (const char *) conf->ciphers.data)
  517.         == 0)
  518.     {
  519.         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
  520.                       "SSL_CTX_set_cipher_list(\"%V\") failed",
  521.                       &conf->ciphers);
  522.         return NGX_CONF_ERROR;
  523.     }

  524.     conf->ssl.buffer_size = conf->buffer_size;

  525.     if (conf->verify) {

  526.         if (conf->client_certificate.len == 0 && conf->verify != 3) {
  527.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  528.                           "no ssl_client_certificate for ssl_client_verify");
  529.             return NGX_CONF_ERROR;
  530.         }

  531.         if (ngx_ssl_client_certificate(cf, &conf->ssl,
  532.                                        &conf->client_certificate,
  533.                                        conf->verify_depth)
  534.             != NGX_OK)
  535.         {
  536.             return NGX_CONF_ERROR;
  537.         }
  538.     }

  539.     if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
  540.                                     &conf->trusted_certificate,
  541.                                     conf->verify_depth)
  542.         != NGX_OK)
  543.     {
  544.         return NGX_CONF_ERROR;
  545.     }

  546.     if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
  547.         return NGX_CONF_ERROR;
  548.     }

  549.     if (conf->prefer_server_ciphers) {
  550.         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
  551.     }

  552.     /* a temporary 512-bit RSA key is required for export versions of MSIE */
  553.     SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback);

  554.     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
  555.         return NGX_CONF_ERROR;
  556.     }

  557.     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
  558.         return NGX_CONF_ERROR;
  559.     }

  560.     ngx_conf_merge_value(conf->builtin_session_cache,
  561.                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);

  562.     if (conf->shm_zone == NULL) {
  563.         conf->shm_zone = prev->shm_zone;
  564.     }

  565.     if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
  566.                               conf->builtin_session_cache,
  567.                               conf->shm_zone, conf->session_timeout)
  568.         != NGX_OK)
  569.     {
  570.         return NGX_CONF_ERROR;
  571.     }

  572.     ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1);

  573. #ifdef SSL_OP_NO_TICKET
  574.     if (!conf->session_tickets) {
  575.         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
  576.     }
  577. #endif

  578.     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
  579.                          prev->session_ticket_keys, NULL);

  580.     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
  581.         != NGX_OK)
  582.     {
  583.         return NGX_CONF_ERROR;
  584.     }

  585.     if (conf->stapling) {

  586.         if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
  587.                              &conf->stapling_responder, conf->stapling_verify)
  588.             != NGX_OK)
  589.         {
  590.             return NGX_CONF_ERROR;
  591.         }

  592.     }

  593.     return NGX_CONF_OK;
  594. }


  595. static char *
  596. ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  597. {
  598.     ngx_http_ssl_srv_conf_t *sscf = conf;

  599.     char  *rv;

  600.     rv = ngx_conf_set_flag_slot(cf, cmd, conf);

  601.     if (rv != NGX_CONF_OK) {
  602.         return rv;
  603.     }

  604.     sscf->file = cf->conf_file->file.name.data;
  605.     sscf->line = cf->conf_file->line;

  606.     return NGX_CONF_OK;
  607. }


  608. static char *
  609. ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  610. {
  611.     ngx_http_ssl_srv_conf_t *sscf = conf;

  612.     ngx_str_t  *value;

  613.     if (sscf->passwords != NGX_CONF_UNSET_PTR) {
  614.         return "is duplicate";
  615.     }

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

  617.     sscf->passwords = ngx_ssl_read_password_file(cf, &value[1]);

  618.     if (sscf->passwords == NULL) {
  619.         return NGX_CONF_ERROR;
  620.     }

  621.     return NGX_CONF_OK;
  622. }


  623. static char *
  624. ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  625. {
  626.     ngx_http_ssl_srv_conf_t *sscf = conf;

  627.     size_t       len;
  628.     ngx_str_t   *value, name, size;
  629.     ngx_int_t    n;
  630.     ngx_uint_t   i, j;

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

  632.     for (i = 1; i < cf->args->nelts; i++) {

  633.         if (ngx_strcmp(value[i].data, "off") == 0) {
  634.             sscf->builtin_session_cache = NGX_SSL_NO_SCACHE;
  635.             continue;
  636.         }

  637.         if (ngx_strcmp(value[i].data, "none") == 0) {
  638.             sscf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
  639.             continue;
  640.         }

  641.         if (ngx_strcmp(value[i].data, "builtin") == 0) {
  642.             sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
  643.             continue;
  644.         }

  645.         if (value[i].len > sizeof("builtin:") - 1
  646.             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
  647.                == 0)
  648.         {
  649.             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
  650.                          value[i].len - (sizeof("builtin:") - 1));

  651.             if (n == NGX_ERROR) {
  652.                 goto invalid;
  653.             }

  654.             sscf->builtin_session_cache = n;

  655.             continue;
  656.         }

  657.         if (value[i].len > sizeof("shared:") - 1
  658.             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
  659.                == 0)
  660.         {
  661.             len = 0;

  662.             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
  663.                 if (value[i].data[j] == ':') {
  664.                     break;
  665.                 }

  666.                 len++;
  667.             }

  668.             if (len == 0) {
  669.                 goto invalid;
  670.             }

  671.             name.len = len;
  672.             name.data = value[i].data + sizeof("shared:") - 1;

  673.             size.len = value[i].len - j - 1;
  674.             size.data = name.data + len + 1;

  675.             n = ngx_parse_size(&size);

  676.             if (n == NGX_ERROR) {
  677.                 goto invalid;
  678.             }

  679.             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
  680.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  681.                                    "session cache \"%V\" is too small",
  682.                                    &value[i]);

  683.                 return NGX_CONF_ERROR;
  684.             }

  685.             sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
  686.                                                    &ngx_http_ssl_module);
  687.             if (sscf->shm_zone == NULL) {
  688.                 return NGX_CONF_ERROR;
  689.             }

  690.             sscf->shm_zone->init = ngx_ssl_session_cache_init;

  691.             continue;
  692.         }

  693.         goto invalid;
  694.     }

  695.     if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
  696.         sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
  697.     }

  698.     return NGX_CONF_OK;

  699. invalid:

  700.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  701.                        "invalid session cache \"%V\"", &value[i]);

  702.     return NGX_CONF_ERROR;
  703. }


  704. static ngx_int_t
  705. ngx_http_ssl_init(ngx_conf_t *cf)
  706. {
  707.     ngx_uint_t                   s;
  708.     ngx_http_ssl_srv_conf_t     *sscf;
  709.     ngx_http_core_loc_conf_t    *clcf;
  710.     ngx_http_core_srv_conf_t   **cscfp;
  711.     ngx_http_core_main_conf_t   *cmcf;

  712.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
  713.     cscfp = cmcf->servers.elts;

  714.     for (s = 0; s < cmcf->servers.nelts; s++) {

  715.         sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];

  716.         if (sscf->ssl.ctx == NULL || !sscf->stapling) {
  717.             continue;
  718.         }

  719.         clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

  720.         if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
  721.                                       clcf->resolver_timeout)
  722.             != NGX_OK)
  723.         {
  724.             return NGX_ERROR;
  725.         }
  726.     }

  727.     return NGX_OK;
  728. }