Back to home page

Nginx displayed by LXR

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

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_stream.h>
0011 
0012 
0013 typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
0014     ngx_pool_t *pool, ngx_str_t *s);
0015 
0016 
0017 #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
0018 #define NGX_DEFAULT_ECDH_CURVE  "auto"
0019 
0020 
0021 static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s);
0022 static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl,
0023     ngx_connection_t *c);
0024 static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
0025 static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
0026     ngx_stream_variable_value_t *v, uintptr_t data);
0027 static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s,
0028     ngx_stream_variable_value_t *v, uintptr_t data);
0029 
0030 static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf);
0031 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf);
0032 static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent,
0033     void *child);
0034 
0035 static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
0036     void *conf);
0037 static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
0038     void *conf);
0039 static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf);
0040 
0041 
0042 static ngx_conf_bitmask_t  ngx_stream_ssl_protocols[] = {
0043     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
0044     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
0045     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
0046     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
0047     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
0048     { ngx_null_string, 0 }
0049 };
0050 
0051 
0052 static ngx_conf_enum_t  ngx_stream_ssl_verify[] = {
0053     { ngx_string("off"), 0 },
0054     { ngx_string("on"), 1 },
0055     { ngx_string("optional"), 2 },
0056     { ngx_string("optional_no_ca"), 3 },
0057     { ngx_null_string, 0 }
0058 };
0059 
0060 
0061 static ngx_command_t  ngx_stream_ssl_commands[] = {
0062 
0063     { ngx_string("ssl_handshake_timeout"),
0064       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0065       ngx_conf_set_msec_slot,
0066       NGX_STREAM_SRV_CONF_OFFSET,
0067       offsetof(ngx_stream_ssl_conf_t, handshake_timeout),
0068       NULL },
0069 
0070     { ngx_string("ssl_certificate"),
0071       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0072       ngx_conf_set_str_array_slot,
0073       NGX_STREAM_SRV_CONF_OFFSET,
0074       offsetof(ngx_stream_ssl_conf_t, certificates),
0075       NULL },
0076 
0077     { ngx_string("ssl_certificate_key"),
0078       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0079       ngx_conf_set_str_array_slot,
0080       NGX_STREAM_SRV_CONF_OFFSET,
0081       offsetof(ngx_stream_ssl_conf_t, certificate_keys),
0082       NULL },
0083 
0084     { ngx_string("ssl_password_file"),
0085       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0086       ngx_stream_ssl_password_file,
0087       NGX_STREAM_SRV_CONF_OFFSET,
0088       0,
0089       NULL },
0090 
0091     { ngx_string("ssl_dhparam"),
0092       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0093       ngx_conf_set_str_slot,
0094       NGX_STREAM_SRV_CONF_OFFSET,
0095       offsetof(ngx_stream_ssl_conf_t, dhparam),
0096       NULL },
0097 
0098     { ngx_string("ssl_ecdh_curve"),
0099       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0100       ngx_conf_set_str_slot,
0101       NGX_STREAM_SRV_CONF_OFFSET,
0102       offsetof(ngx_stream_ssl_conf_t, ecdh_curve),
0103       NULL },
0104 
0105     { ngx_string("ssl_protocols"),
0106       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0107       ngx_conf_set_bitmask_slot,
0108       NGX_STREAM_SRV_CONF_OFFSET,
0109       offsetof(ngx_stream_ssl_conf_t, protocols),
0110       &ngx_stream_ssl_protocols },
0111 
0112     { ngx_string("ssl_ciphers"),
0113       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0114       ngx_conf_set_str_slot,
0115       NGX_STREAM_SRV_CONF_OFFSET,
0116       offsetof(ngx_stream_ssl_conf_t, ciphers),
0117       NULL },
0118 
0119     { ngx_string("ssl_verify_client"),
0120       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0121       ngx_conf_set_enum_slot,
0122       NGX_STREAM_SRV_CONF_OFFSET,
0123       offsetof(ngx_stream_ssl_conf_t, verify),
0124       &ngx_stream_ssl_verify },
0125 
0126     { ngx_string("ssl_verify_depth"),
0127       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0128       ngx_conf_set_num_slot,
0129       NGX_STREAM_SRV_CONF_OFFSET,
0130       offsetof(ngx_stream_ssl_conf_t, verify_depth),
0131       NULL },
0132 
0133     { ngx_string("ssl_client_certificate"),
0134       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0135       ngx_conf_set_str_slot,
0136       NGX_STREAM_SRV_CONF_OFFSET,
0137       offsetof(ngx_stream_ssl_conf_t, client_certificate),
0138       NULL },
0139 
0140     { ngx_string("ssl_trusted_certificate"),
0141       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0142       ngx_conf_set_str_slot,
0143       NGX_STREAM_SRV_CONF_OFFSET,
0144       offsetof(ngx_stream_ssl_conf_t, trusted_certificate),
0145       NULL },
0146 
0147     { ngx_string("ssl_prefer_server_ciphers"),
0148       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
0149       ngx_conf_set_flag_slot,
0150       NGX_STREAM_SRV_CONF_OFFSET,
0151       offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers),
0152       NULL },
0153 
0154     { ngx_string("ssl_session_cache"),
0155       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12,
0156       ngx_stream_ssl_session_cache,
0157       NGX_STREAM_SRV_CONF_OFFSET,
0158       0,
0159       NULL },
0160 
0161     { ngx_string("ssl_session_tickets"),
0162       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
0163       ngx_conf_set_flag_slot,
0164       NGX_STREAM_SRV_CONF_OFFSET,
0165       offsetof(ngx_stream_ssl_conf_t, session_tickets),
0166       NULL },
0167 
0168     { ngx_string("ssl_session_ticket_key"),
0169       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0170       ngx_conf_set_str_array_slot,
0171       NGX_STREAM_SRV_CONF_OFFSET,
0172       offsetof(ngx_stream_ssl_conf_t, session_ticket_keys),
0173       NULL },
0174 
0175     { ngx_string("ssl_session_timeout"),
0176       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0177       ngx_conf_set_sec_slot,
0178       NGX_STREAM_SRV_CONF_OFFSET,
0179       offsetof(ngx_stream_ssl_conf_t, session_timeout),
0180       NULL },
0181 
0182     { ngx_string("ssl_crl"),
0183       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0184       ngx_conf_set_str_slot,
0185       NGX_STREAM_SRV_CONF_OFFSET,
0186       offsetof(ngx_stream_ssl_conf_t, crl),
0187       NULL },
0188 
0189       ngx_null_command
0190 };
0191 
0192 
0193 static ngx_stream_module_t  ngx_stream_ssl_module_ctx = {
0194     ngx_stream_ssl_add_variables,          /* preconfiguration */
0195     ngx_stream_ssl_init,                   /* postconfiguration */
0196 
0197     NULL,                                  /* create main configuration */
0198     NULL,                                  /* init main configuration */
0199 
0200     ngx_stream_ssl_create_conf,            /* create server configuration */
0201     ngx_stream_ssl_merge_conf              /* merge server configuration */
0202 };
0203 
0204 
0205 ngx_module_t  ngx_stream_ssl_module = {
0206     NGX_MODULE_V1,
0207     &ngx_stream_ssl_module_ctx,            /* module context */
0208     ngx_stream_ssl_commands,               /* module directives */
0209     NGX_STREAM_MODULE,                     /* module type */
0210     NULL,                                  /* init master */
0211     NULL,                                  /* init module */
0212     NULL,                                  /* init process */
0213     NULL,                                  /* init thread */
0214     NULL,                                  /* exit thread */
0215     NULL,                                  /* exit process */
0216     NULL,                                  /* exit master */
0217     NGX_MODULE_V1_PADDING
0218 };
0219 
0220 
0221 static ngx_stream_variable_t  ngx_stream_ssl_vars[] = {
0222 
0223     { ngx_string("ssl_protocol"), NULL, ngx_stream_ssl_static_variable,
0224       (uintptr_t) ngx_ssl_get_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 },
0225 
0226     { ngx_string("ssl_cipher"), NULL, ngx_stream_ssl_static_variable,
0227       (uintptr_t) ngx_ssl_get_cipher_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
0228 
0229     { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable,
0230       (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 },
0231 
0232     { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable,
0233       (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 },
0234 
0235     { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable,
0236       (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 },
0237 
0238     { ngx_string("ssl_session_reused"), NULL, ngx_stream_ssl_variable,
0239       (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 },
0240 
0241     { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable,
0242       (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
0243 
0244     { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable,
0245       (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 },
0246 
0247     { ngx_string("ssl_client_raw_cert"), NULL, ngx_stream_ssl_variable,
0248       (uintptr_t) ngx_ssl_get_raw_certificate,
0249       NGX_STREAM_VAR_CHANGEABLE, 0 },
0250 
0251     { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable,
0252       (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
0253 
0254     { ngx_string("ssl_client_i_dn"), NULL, ngx_stream_ssl_variable,
0255       (uintptr_t) ngx_ssl_get_issuer_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
0256 
0257     { ngx_string("ssl_client_serial"), NULL, ngx_stream_ssl_variable,
0258       (uintptr_t) ngx_ssl_get_serial_number, NGX_STREAM_VAR_CHANGEABLE, 0 },
0259 
0260     { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable,
0261       (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 },
0262 
0263     { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable,
0264       (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 },
0265 
0266     { ngx_string("ssl_client_v_start"), NULL, ngx_stream_ssl_variable,
0267       (uintptr_t) ngx_ssl_get_client_v_start, NGX_STREAM_VAR_CHANGEABLE, 0 },
0268 
0269     { ngx_string("ssl_client_v_end"), NULL, ngx_stream_ssl_variable,
0270       (uintptr_t) ngx_ssl_get_client_v_end, NGX_STREAM_VAR_CHANGEABLE, 0 },
0271 
0272     { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable,
0273       (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 },
0274 
0275     { ngx_null_string, NULL, NULL, 0, 0, 0 }
0276 };
0277 
0278 
0279 static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
0280 
0281 
0282 static ngx_int_t
0283 ngx_stream_ssl_handler(ngx_stream_session_t *s)
0284 {
0285     long                    rc;
0286     X509                   *cert;
0287     ngx_int_t               rv;
0288     ngx_connection_t       *c;
0289     ngx_stream_ssl_conf_t  *sslcf;
0290 
0291     if (!s->ssl) {
0292         return NGX_OK;
0293     }
0294 
0295     c = s->connection;
0296 
0297     sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
0298 
0299     if (c->ssl == NULL) {
0300         c->log->action = "SSL handshaking";
0301 
0302         if (sslcf->ssl.ctx == NULL) {
0303             ngx_log_error(NGX_LOG_ERR, c->log, 0,
0304                           "no \"ssl_certificate\" is defined "
0305                           "in server listening on SSL port");
0306             return NGX_ERROR;
0307         }
0308 
0309         rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c);
0310 
0311         if (rv != NGX_OK) {
0312             return rv;
0313         }
0314     }
0315 
0316     if (sslcf->verify) {
0317         rc = SSL_get_verify_result(c->ssl->connection);
0318 
0319         if (rc != X509_V_OK
0320             && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
0321         {
0322             ngx_log_error(NGX_LOG_INFO, c->log, 0,
0323                           "client SSL certificate verify error: (%l:%s)",
0324                           rc, X509_verify_cert_error_string(rc));
0325 
0326             ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
0327                                        (SSL_get0_session(c->ssl->connection)));
0328             return NGX_ERROR;
0329         }
0330 
0331         if (sslcf->verify == 1) {
0332             cert = SSL_get_peer_certificate(c->ssl->connection);
0333 
0334             if (cert == NULL) {
0335                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
0336                               "client sent no required SSL certificate");
0337 
0338                 ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
0339                                        (SSL_get0_session(c->ssl->connection)));
0340                 return NGX_ERROR;
0341             }
0342 
0343             X509_free(cert);
0344         }
0345     }
0346 
0347     return NGX_OK;
0348 }
0349 
0350 
0351 static ngx_int_t
0352 ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
0353 {
0354     ngx_int_t               rc;
0355     ngx_stream_session_t   *s;
0356     ngx_stream_ssl_conf_t  *sslcf;
0357 
0358     s = c->data;
0359 
0360     if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
0361         return NGX_ERROR;
0362     }
0363 
0364     rc = ngx_ssl_handshake(c);
0365 
0366     if (rc == NGX_ERROR) {
0367         return NGX_ERROR;
0368     }
0369 
0370     if (rc == NGX_AGAIN) {
0371         sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
0372 
0373         ngx_add_timer(c->read, sslcf->handshake_timeout);
0374 
0375         c->ssl->handler = ngx_stream_ssl_handshake_handler;
0376 
0377         return NGX_AGAIN;
0378     }
0379 
0380     /* rc == NGX_OK */
0381 
0382     return NGX_OK;
0383 }
0384 
0385 
0386 static void
0387 ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
0388 {
0389     ngx_stream_session_t  *s;
0390 
0391     s = c->data;
0392 
0393     if (!c->ssl->handshaked) {
0394         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0395         return;
0396     }
0397 
0398     if (c->read->timer_set) {
0399         ngx_del_timer(c->read);
0400     }
0401 
0402     ngx_stream_core_run_phases(s);
0403 }
0404 
0405 
0406 static ngx_int_t
0407 ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
0408     ngx_stream_variable_value_t *v, uintptr_t data)
0409 {
0410     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
0411 
0412     size_t     len;
0413     ngx_str_t  str;
0414 
0415     if (s->connection->ssl) {
0416 
0417         (void) handler(s->connection, NULL, &str);
0418 
0419         v->data = str.data;
0420 
0421         for (len = 0; v->data[len]; len++) { /* void */ }
0422 
0423         v->len = len;
0424         v->valid = 1;
0425         v->no_cacheable = 0;
0426         v->not_found = 0;
0427 
0428         return NGX_OK;
0429     }
0430 
0431     v->not_found = 1;
0432 
0433     return NGX_OK;
0434 }
0435 
0436 
0437 static ngx_int_t
0438 ngx_stream_ssl_variable(ngx_stream_session_t *s,
0439     ngx_stream_variable_value_t *v, uintptr_t data)
0440 {
0441     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
0442 
0443     ngx_str_t  str;
0444 
0445     if (s->connection->ssl) {
0446 
0447         if (handler(s->connection, s->connection->pool, &str) != NGX_OK) {
0448             return NGX_ERROR;
0449         }
0450 
0451         v->len = str.len;
0452         v->data = str.data;
0453 
0454         if (v->len) {
0455             v->valid = 1;
0456             v->no_cacheable = 0;
0457             v->not_found = 0;
0458 
0459             return NGX_OK;
0460         }
0461     }
0462 
0463     v->not_found = 1;
0464 
0465     return NGX_OK;
0466 }
0467 
0468 
0469 static ngx_int_t
0470 ngx_stream_ssl_add_variables(ngx_conf_t *cf)
0471 {
0472     ngx_stream_variable_t  *var, *v;
0473 
0474     for (v = ngx_stream_ssl_vars; v->name.len; v++) {
0475         var = ngx_stream_add_variable(cf, &v->name, v->flags);
0476         if (var == NULL) {
0477             return NGX_ERROR;
0478         }
0479 
0480         var->get_handler = v->get_handler;
0481         var->data = v->data;
0482     }
0483 
0484     return NGX_OK;
0485 }
0486 
0487 
0488 static void *
0489 ngx_stream_ssl_create_conf(ngx_conf_t *cf)
0490 {
0491     ngx_stream_ssl_conf_t  *scf;
0492 
0493     scf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ssl_conf_t));
0494     if (scf == NULL) {
0495         return NULL;
0496     }
0497 
0498     /*
0499      * set by ngx_pcalloc():
0500      *
0501      *     scf->protocols = 0;
0502      *     scf->dhparam = { 0, NULL };
0503      *     scf->ecdh_curve = { 0, NULL };
0504      *     scf->client_certificate = { 0, NULL };
0505      *     scf->trusted_certificate = { 0, NULL };
0506      *     scf->crl = { 0, NULL };
0507      *     scf->ciphers = { 0, NULL };
0508      *     scf->shm_zone = NULL;
0509      */
0510 
0511     scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
0512     scf->certificates = NGX_CONF_UNSET_PTR;
0513     scf->certificate_keys = NGX_CONF_UNSET_PTR;
0514     scf->passwords = NGX_CONF_UNSET_PTR;
0515     scf->prefer_server_ciphers = NGX_CONF_UNSET;
0516     scf->verify = NGX_CONF_UNSET_UINT;
0517     scf->verify_depth = NGX_CONF_UNSET_UINT;
0518     scf->builtin_session_cache = NGX_CONF_UNSET;
0519     scf->session_timeout = NGX_CONF_UNSET;
0520     scf->session_tickets = NGX_CONF_UNSET;
0521     scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
0522 
0523     return scf;
0524 }
0525 
0526 
0527 static char *
0528 ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
0529 {
0530     ngx_stream_ssl_conf_t *prev = parent;
0531     ngx_stream_ssl_conf_t *conf = child;
0532 
0533     ngx_pool_cleanup_t  *cln;
0534 
0535     ngx_conf_merge_msec_value(conf->handshake_timeout,
0536                          prev->handshake_timeout, 60000);
0537 
0538     ngx_conf_merge_value(conf->session_timeout,
0539                          prev->session_timeout, 300);
0540 
0541     ngx_conf_merge_value(conf->prefer_server_ciphers,
0542                          prev->prefer_server_ciphers, 0);
0543 
0544     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
0545                          (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
0546                           |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
0547 
0548     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
0549     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
0550 
0551     ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
0552     ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
0553                          NULL);
0554 
0555     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
0556 
0557     ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
0558 
0559     ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
0560                          "");
0561     ngx_conf_merge_str_value(conf->trusted_certificate,
0562                          prev->trusted_certificate, "");
0563     ngx_conf_merge_str_value(conf->crl, prev->crl, "");
0564 
0565     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
0566                          NGX_DEFAULT_ECDH_CURVE);
0567 
0568     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
0569 
0570 
0571     conf->ssl.log = cf->log;
0572 
0573     if (conf->certificates == NULL) {
0574         return NGX_CONF_OK;
0575     }
0576 
0577     if (conf->certificate_keys == NULL
0578         || conf->certificate_keys->nelts < conf->certificates->nelts)
0579     {
0580         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0581                       "no \"ssl_certificate_key\" is defined "
0582                       "for certificate \"%V\"",
0583                       ((ngx_str_t *) conf->certificates->elts)
0584                       + conf->certificates->nelts - 1);
0585         return NGX_CONF_ERROR;
0586     }
0587 
0588     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
0589         return NGX_CONF_ERROR;
0590     }
0591 
0592     cln = ngx_pool_cleanup_add(cf->pool, 0);
0593     if (cln == NULL) {
0594         return NGX_CONF_ERROR;
0595     }
0596 
0597     cln->handler = ngx_ssl_cleanup_ctx;
0598     cln->data = &conf->ssl;
0599 
0600     if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
0601                              conf->certificate_keys, conf->passwords)
0602         != NGX_OK)
0603     {
0604         return NGX_CONF_ERROR;
0605     }
0606 
0607     if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
0608                         conf->prefer_server_ciphers)
0609         != NGX_OK)
0610     {
0611         return NGX_CONF_ERROR;
0612     }
0613 
0614     if (conf->verify) {
0615 
0616         if (conf->client_certificate.len == 0 && conf->verify != 3) {
0617             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0618                           "no ssl_client_certificate for ssl_client_verify");
0619             return NGX_CONF_ERROR;
0620         }
0621 
0622         if (ngx_ssl_client_certificate(cf, &conf->ssl,
0623                                        &conf->client_certificate,
0624                                        conf->verify_depth)
0625             != NGX_OK)
0626         {
0627             return NGX_CONF_ERROR;
0628         }
0629 
0630         if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
0631                                         &conf->trusted_certificate,
0632                                         conf->verify_depth)
0633             != NGX_OK)
0634         {
0635             return NGX_CONF_ERROR;
0636         }
0637 
0638         if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
0639             return NGX_CONF_ERROR;
0640         }
0641     }
0642 
0643     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
0644         return NGX_CONF_ERROR;
0645     }
0646 
0647     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
0648         return NGX_CONF_ERROR;
0649     }
0650 
0651     ngx_conf_merge_value(conf->builtin_session_cache,
0652                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
0653 
0654     if (conf->shm_zone == NULL) {
0655         conf->shm_zone = prev->shm_zone;
0656     }
0657 
0658     if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx,
0659                               conf->builtin_session_cache,
0660                               conf->shm_zone, conf->session_timeout)
0661         != NGX_OK)
0662     {
0663         return NGX_CONF_ERROR;
0664     }
0665 
0666     ngx_conf_merge_value(conf->session_tickets,
0667                          prev->session_tickets, 1);
0668 
0669 #ifdef SSL_OP_NO_TICKET
0670     if (!conf->session_tickets) {
0671         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
0672     }
0673 #endif
0674 
0675     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
0676                          prev->session_ticket_keys, NULL);
0677 
0678     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
0679         != NGX_OK)
0680     {
0681         return NGX_CONF_ERROR;
0682     }
0683 
0684     return NGX_CONF_OK;
0685 }
0686 
0687 
0688 static char *
0689 ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0690 {
0691     ngx_stream_ssl_conf_t  *scf = conf;
0692 
0693     ngx_str_t  *value;
0694 
0695     if (scf->passwords != NGX_CONF_UNSET_PTR) {
0696         return "is duplicate";
0697     }
0698 
0699     value = cf->args->elts;
0700 
0701     scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
0702 
0703     if (scf->passwords == NULL) {
0704         return NGX_CONF_ERROR;
0705     }
0706 
0707     return NGX_CONF_OK;
0708 }
0709 
0710 
0711 static char *
0712 ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0713 {
0714     ngx_stream_ssl_conf_t  *scf = conf;
0715 
0716     size_t       len;
0717     ngx_str_t   *value, name, size;
0718     ngx_int_t    n;
0719     ngx_uint_t   i, j;
0720 
0721     value = cf->args->elts;
0722 
0723     for (i = 1; i < cf->args->nelts; i++) {
0724 
0725         if (ngx_strcmp(value[i].data, "off") == 0) {
0726             scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
0727             continue;
0728         }
0729 
0730         if (ngx_strcmp(value[i].data, "none") == 0) {
0731             scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
0732             continue;
0733         }
0734 
0735         if (ngx_strcmp(value[i].data, "builtin") == 0) {
0736             scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
0737             continue;
0738         }
0739 
0740         if (value[i].len > sizeof("builtin:") - 1
0741             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
0742                == 0)
0743         {
0744             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
0745                          value[i].len - (sizeof("builtin:") - 1));
0746 
0747             if (n == NGX_ERROR) {
0748                 goto invalid;
0749             }
0750 
0751             scf->builtin_session_cache = n;
0752 
0753             continue;
0754         }
0755 
0756         if (value[i].len > sizeof("shared:") - 1
0757             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
0758                == 0)
0759         {
0760             len = 0;
0761 
0762             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
0763                 if (value[i].data[j] == ':') {
0764                     break;
0765                 }
0766 
0767                 len++;
0768             }
0769 
0770             if (len == 0) {
0771                 goto invalid;
0772             }
0773 
0774             name.len = len;
0775             name.data = value[i].data + sizeof("shared:") - 1;
0776 
0777             size.len = value[i].len - j - 1;
0778             size.data = name.data + len + 1;
0779 
0780             n = ngx_parse_size(&size);
0781 
0782             if (n == NGX_ERROR) {
0783                 goto invalid;
0784             }
0785 
0786             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
0787                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0788                                    "session cache \"%V\" is too small",
0789                                    &value[i]);
0790 
0791                 return NGX_CONF_ERROR;
0792             }
0793 
0794             scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
0795                                                    &ngx_stream_ssl_module);
0796             if (scf->shm_zone == NULL) {
0797                 return NGX_CONF_ERROR;
0798             }
0799 
0800             scf->shm_zone->init = ngx_ssl_session_cache_init;
0801 
0802             continue;
0803         }
0804 
0805         goto invalid;
0806     }
0807 
0808     if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
0809         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
0810     }
0811 
0812     return NGX_CONF_OK;
0813 
0814 invalid:
0815 
0816     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0817                        "invalid session cache \"%V\"", &value[i]);
0818 
0819     return NGX_CONF_ERROR;
0820 }
0821 
0822 
0823 static ngx_int_t
0824 ngx_stream_ssl_init(ngx_conf_t *cf)
0825 {
0826     ngx_stream_handler_pt        *h;
0827     ngx_stream_core_main_conf_t  *cmcf;
0828 
0829     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
0830 
0831     h = ngx_array_push(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers);
0832     if (h == NULL) {
0833         return NGX_ERROR;
0834     }
0835 
0836     *h = ngx_stream_ssl_handler;
0837 
0838     return NGX_OK;
0839 }