Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

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 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
0026 int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
0027 #endif
0028 #ifdef SSL_R_CERT_CB_ERROR
0029 static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg);
0030 #endif
0031 static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
0032     ngx_stream_variable_value_t *v, uintptr_t data);
0033 static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s,
0034     ngx_stream_variable_value_t *v, uintptr_t data);
0035 
0036 static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf);
0037 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf);
0038 static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent,
0039     void *child);
0040 
0041 static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
0042     ngx_stream_ssl_conf_t *conf);
0043 
0044 static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
0045     void *conf);
0046 static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
0047     void *conf);
0048 static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf);
0049 
0050 
0051 static ngx_conf_bitmask_t  ngx_stream_ssl_protocols[] = {
0052     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
0053     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
0054     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
0055     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
0056     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
0057     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
0058     { ngx_null_string, 0 }
0059 };
0060 
0061 
0062 static ngx_conf_enum_t  ngx_stream_ssl_verify[] = {
0063     { ngx_string("off"), 0 },
0064     { ngx_string("on"), 1 },
0065     { ngx_string("optional"), 2 },
0066     { ngx_string("optional_no_ca"), 3 },
0067     { ngx_null_string, 0 }
0068 };
0069 
0070 
0071 static ngx_command_t  ngx_stream_ssl_commands[] = {
0072 
0073     { ngx_string("ssl_handshake_timeout"),
0074       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0075       ngx_conf_set_msec_slot,
0076       NGX_STREAM_SRV_CONF_OFFSET,
0077       offsetof(ngx_stream_ssl_conf_t, handshake_timeout),
0078       NULL },
0079 
0080     { ngx_string("ssl_certificate"),
0081       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0082       ngx_conf_set_str_array_slot,
0083       NGX_STREAM_SRV_CONF_OFFSET,
0084       offsetof(ngx_stream_ssl_conf_t, certificates),
0085       NULL },
0086 
0087     { ngx_string("ssl_certificate_key"),
0088       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0089       ngx_conf_set_str_array_slot,
0090       NGX_STREAM_SRV_CONF_OFFSET,
0091       offsetof(ngx_stream_ssl_conf_t, certificate_keys),
0092       NULL },
0093 
0094     { ngx_string("ssl_password_file"),
0095       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0096       ngx_stream_ssl_password_file,
0097       NGX_STREAM_SRV_CONF_OFFSET,
0098       0,
0099       NULL },
0100 
0101     { ngx_string("ssl_dhparam"),
0102       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0103       ngx_conf_set_str_slot,
0104       NGX_STREAM_SRV_CONF_OFFSET,
0105       offsetof(ngx_stream_ssl_conf_t, dhparam),
0106       NULL },
0107 
0108     { ngx_string("ssl_ecdh_curve"),
0109       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0110       ngx_conf_set_str_slot,
0111       NGX_STREAM_SRV_CONF_OFFSET,
0112       offsetof(ngx_stream_ssl_conf_t, ecdh_curve),
0113       NULL },
0114 
0115     { ngx_string("ssl_protocols"),
0116       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0117       ngx_conf_set_bitmask_slot,
0118       NGX_STREAM_SRV_CONF_OFFSET,
0119       offsetof(ngx_stream_ssl_conf_t, protocols),
0120       &ngx_stream_ssl_protocols },
0121 
0122     { ngx_string("ssl_ciphers"),
0123       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0124       ngx_conf_set_str_slot,
0125       NGX_STREAM_SRV_CONF_OFFSET,
0126       offsetof(ngx_stream_ssl_conf_t, ciphers),
0127       NULL },
0128 
0129     { ngx_string("ssl_verify_client"),
0130       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0131       ngx_conf_set_enum_slot,
0132       NGX_STREAM_SRV_CONF_OFFSET,
0133       offsetof(ngx_stream_ssl_conf_t, verify),
0134       &ngx_stream_ssl_verify },
0135 
0136     { ngx_string("ssl_verify_depth"),
0137       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0138       ngx_conf_set_num_slot,
0139       NGX_STREAM_SRV_CONF_OFFSET,
0140       offsetof(ngx_stream_ssl_conf_t, verify_depth),
0141       NULL },
0142 
0143     { ngx_string("ssl_client_certificate"),
0144       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0145       ngx_conf_set_str_slot,
0146       NGX_STREAM_SRV_CONF_OFFSET,
0147       offsetof(ngx_stream_ssl_conf_t, client_certificate),
0148       NULL },
0149 
0150     { ngx_string("ssl_trusted_certificate"),
0151       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0152       ngx_conf_set_str_slot,
0153       NGX_STREAM_SRV_CONF_OFFSET,
0154       offsetof(ngx_stream_ssl_conf_t, trusted_certificate),
0155       NULL },
0156 
0157     { ngx_string("ssl_prefer_server_ciphers"),
0158       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
0159       ngx_conf_set_flag_slot,
0160       NGX_STREAM_SRV_CONF_OFFSET,
0161       offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers),
0162       NULL },
0163 
0164     { ngx_string("ssl_session_cache"),
0165       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12,
0166       ngx_stream_ssl_session_cache,
0167       NGX_STREAM_SRV_CONF_OFFSET,
0168       0,
0169       NULL },
0170 
0171     { ngx_string("ssl_session_tickets"),
0172       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
0173       ngx_conf_set_flag_slot,
0174       NGX_STREAM_SRV_CONF_OFFSET,
0175       offsetof(ngx_stream_ssl_conf_t, session_tickets),
0176       NULL },
0177 
0178     { ngx_string("ssl_session_ticket_key"),
0179       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0180       ngx_conf_set_str_array_slot,
0181       NGX_STREAM_SRV_CONF_OFFSET,
0182       offsetof(ngx_stream_ssl_conf_t, session_ticket_keys),
0183       NULL },
0184 
0185     { ngx_string("ssl_session_timeout"),
0186       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0187       ngx_conf_set_sec_slot,
0188       NGX_STREAM_SRV_CONF_OFFSET,
0189       offsetof(ngx_stream_ssl_conf_t, session_timeout),
0190       NULL },
0191 
0192     { ngx_string("ssl_crl"),
0193       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0194       ngx_conf_set_str_slot,
0195       NGX_STREAM_SRV_CONF_OFFSET,
0196       offsetof(ngx_stream_ssl_conf_t, crl),
0197       NULL },
0198 
0199       ngx_null_command
0200 };
0201 
0202 
0203 static ngx_stream_module_t  ngx_stream_ssl_module_ctx = {
0204     ngx_stream_ssl_add_variables,          /* preconfiguration */
0205     ngx_stream_ssl_init,                   /* postconfiguration */
0206 
0207     NULL,                                  /* create main configuration */
0208     NULL,                                  /* init main configuration */
0209 
0210     ngx_stream_ssl_create_conf,            /* create server configuration */
0211     ngx_stream_ssl_merge_conf              /* merge server configuration */
0212 };
0213 
0214 
0215 ngx_module_t  ngx_stream_ssl_module = {
0216     NGX_MODULE_V1,
0217     &ngx_stream_ssl_module_ctx,            /* module context */
0218     ngx_stream_ssl_commands,               /* module directives */
0219     NGX_STREAM_MODULE,                     /* module type */
0220     NULL,                                  /* init master */
0221     NULL,                                  /* init module */
0222     NULL,                                  /* init process */
0223     NULL,                                  /* init thread */
0224     NULL,                                  /* exit thread */
0225     NULL,                                  /* exit process */
0226     NULL,                                  /* exit master */
0227     NGX_MODULE_V1_PADDING
0228 };
0229 
0230 
0231 static ngx_stream_variable_t  ngx_stream_ssl_vars[] = {
0232 
0233     { ngx_string("ssl_protocol"), NULL, ngx_stream_ssl_static_variable,
0234       (uintptr_t) ngx_ssl_get_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 },
0235 
0236     { ngx_string("ssl_cipher"), NULL, ngx_stream_ssl_static_variable,
0237       (uintptr_t) ngx_ssl_get_cipher_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
0238 
0239     { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable,
0240       (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 },
0241 
0242     { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable,
0243       (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 },
0244 
0245     { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable,
0246       (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 },
0247 
0248     { ngx_string("ssl_session_reused"), NULL, ngx_stream_ssl_variable,
0249       (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 },
0250 
0251     { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable,
0252       (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
0253 
0254     { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable,
0255       (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 },
0256 
0257     { ngx_string("ssl_client_raw_cert"), NULL, ngx_stream_ssl_variable,
0258       (uintptr_t) ngx_ssl_get_raw_certificate,
0259       NGX_STREAM_VAR_CHANGEABLE, 0 },
0260 
0261     { ngx_string("ssl_client_escaped_cert"), NULL, ngx_stream_ssl_variable,
0262       (uintptr_t) ngx_ssl_get_escaped_certificate,
0263       NGX_STREAM_VAR_CHANGEABLE, 0 },
0264 
0265     { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable,
0266       (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
0267 
0268     { ngx_string("ssl_client_i_dn"), NULL, ngx_stream_ssl_variable,
0269       (uintptr_t) ngx_ssl_get_issuer_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
0270 
0271     { ngx_string("ssl_client_serial"), NULL, ngx_stream_ssl_variable,
0272       (uintptr_t) ngx_ssl_get_serial_number, NGX_STREAM_VAR_CHANGEABLE, 0 },
0273 
0274     { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable,
0275       (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 },
0276 
0277     { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable,
0278       (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 },
0279 
0280     { ngx_string("ssl_client_v_start"), NULL, ngx_stream_ssl_variable,
0281       (uintptr_t) ngx_ssl_get_client_v_start, NGX_STREAM_VAR_CHANGEABLE, 0 },
0282 
0283     { ngx_string("ssl_client_v_end"), NULL, ngx_stream_ssl_variable,
0284       (uintptr_t) ngx_ssl_get_client_v_end, NGX_STREAM_VAR_CHANGEABLE, 0 },
0285 
0286     { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable,
0287       (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 },
0288 
0289       ngx_stream_null_variable
0290 };
0291 
0292 
0293 static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
0294 
0295 
0296 static ngx_int_t
0297 ngx_stream_ssl_handler(ngx_stream_session_t *s)
0298 {
0299     long                    rc;
0300     X509                   *cert;
0301     ngx_int_t               rv;
0302     ngx_connection_t       *c;
0303     ngx_stream_ssl_conf_t  *sslcf;
0304 
0305     if (!s->ssl) {
0306         return NGX_OK;
0307     }
0308 
0309     c = s->connection;
0310 
0311     sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
0312 
0313     if (c->ssl == NULL) {
0314         c->log->action = "SSL handshaking";
0315 
0316         rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c);
0317 
0318         if (rv != NGX_OK) {
0319             return rv;
0320         }
0321     }
0322 
0323     if (sslcf->verify) {
0324         rc = SSL_get_verify_result(c->ssl->connection);
0325 
0326         if (rc != X509_V_OK
0327             && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
0328         {
0329             ngx_log_error(NGX_LOG_INFO, c->log, 0,
0330                           "client SSL certificate verify error: (%l:%s)",
0331                           rc, X509_verify_cert_error_string(rc));
0332 
0333             ngx_ssl_remove_cached_session(c->ssl->session_ctx,
0334                                        (SSL_get0_session(c->ssl->connection)));
0335             return NGX_ERROR;
0336         }
0337 
0338         if (sslcf->verify == 1) {
0339             cert = SSL_get_peer_certificate(c->ssl->connection);
0340 
0341             if (cert == NULL) {
0342                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
0343                               "client sent no required SSL certificate");
0344 
0345                 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
0346                                        (SSL_get0_session(c->ssl->connection)));
0347                 return NGX_ERROR;
0348             }
0349 
0350             X509_free(cert);
0351         }
0352     }
0353 
0354     return NGX_OK;
0355 }
0356 
0357 
0358 static ngx_int_t
0359 ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
0360 {
0361     ngx_int_t                    rc;
0362     ngx_stream_session_t        *s;
0363     ngx_stream_ssl_conf_t       *sslcf;
0364     ngx_stream_core_srv_conf_t  *cscf;
0365 
0366     s = c->data;
0367 
0368     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0369 
0370     if (cscf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
0371         return NGX_ERROR;
0372     }
0373 
0374     if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) {
0375         return NGX_ERROR;
0376     }
0377 
0378     rc = ngx_ssl_handshake(c);
0379 
0380     if (rc == NGX_ERROR) {
0381         return NGX_ERROR;
0382     }
0383 
0384     if (rc == NGX_AGAIN) {
0385         sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
0386 
0387         ngx_add_timer(c->read, sslcf->handshake_timeout);
0388 
0389         c->ssl->handler = ngx_stream_ssl_handshake_handler;
0390 
0391         return NGX_AGAIN;
0392     }
0393 
0394     /* rc == NGX_OK */
0395 
0396     return NGX_OK;
0397 }
0398 
0399 
0400 static void
0401 ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
0402 {
0403     ngx_stream_session_t  *s;
0404 
0405     s = c->data;
0406 
0407     if (!c->ssl->handshaked) {
0408         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0409         return;
0410     }
0411 
0412     if (c->read->timer_set) {
0413         ngx_del_timer(c->read);
0414     }
0415 
0416     ngx_stream_core_run_phases(s);
0417 }
0418 
0419 
0420 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
0421 
0422 int
0423 ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
0424 {
0425     return SSL_TLSEXT_ERR_OK;
0426 }
0427 
0428 #endif
0429 
0430 
0431 #ifdef SSL_R_CERT_CB_ERROR
0432 
0433 int
0434 ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
0435 {
0436     ngx_str_t                    cert, key;
0437     ngx_uint_t                   i, nelts;
0438     ngx_connection_t            *c;
0439     ngx_stream_session_t        *s;
0440     ngx_stream_ssl_conf_t       *sslcf;
0441     ngx_stream_complex_value_t  *certs, *keys;
0442 
0443     c = ngx_ssl_get_connection(ssl_conn);
0444 
0445     if (c->ssl->handshaked) {
0446         return 0;
0447     }
0448 
0449     s = c->data;
0450 
0451     sslcf = arg;
0452 
0453     nelts = sslcf->certificate_values->nelts;
0454     certs = sslcf->certificate_values->elts;
0455     keys = sslcf->certificate_key_values->elts;
0456 
0457     for (i = 0; i < nelts; i++) {
0458 
0459         if (ngx_stream_complex_value(s, &certs[i], &cert) != NGX_OK) {
0460             return 0;
0461         }
0462 
0463         ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
0464                        "ssl cert: \"%s\"", cert.data);
0465 
0466         if (ngx_stream_complex_value(s, &keys[i], &key) != NGX_OK) {
0467             return 0;
0468         }
0469 
0470         ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
0471                        "ssl key: \"%s\"", key.data);
0472 
0473         if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key,
0474                                            sslcf->passwords)
0475             != NGX_OK)
0476         {
0477             return 0;
0478         }
0479     }
0480 
0481     return 1;
0482 }
0483 
0484 #endif
0485 
0486 
0487 static ngx_int_t
0488 ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
0489     ngx_stream_variable_value_t *v, uintptr_t data)
0490 {
0491     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
0492 
0493     size_t     len;
0494     ngx_str_t  str;
0495 
0496     if (s->connection->ssl) {
0497 
0498         (void) handler(s->connection, NULL, &str);
0499 
0500         v->data = str.data;
0501 
0502         for (len = 0; v->data[len]; len++) { /* void */ }
0503 
0504         v->len = len;
0505         v->valid = 1;
0506         v->no_cacheable = 0;
0507         v->not_found = 0;
0508 
0509         return NGX_OK;
0510     }
0511 
0512     v->not_found = 1;
0513 
0514     return NGX_OK;
0515 }
0516 
0517 
0518 static ngx_int_t
0519 ngx_stream_ssl_variable(ngx_stream_session_t *s,
0520     ngx_stream_variable_value_t *v, uintptr_t data)
0521 {
0522     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
0523 
0524     ngx_str_t  str;
0525 
0526     if (s->connection->ssl) {
0527 
0528         if (handler(s->connection, s->connection->pool, &str) != NGX_OK) {
0529             return NGX_ERROR;
0530         }
0531 
0532         v->len = str.len;
0533         v->data = str.data;
0534 
0535         if (v->len) {
0536             v->valid = 1;
0537             v->no_cacheable = 0;
0538             v->not_found = 0;
0539 
0540             return NGX_OK;
0541         }
0542     }
0543 
0544     v->not_found = 1;
0545 
0546     return NGX_OK;
0547 }
0548 
0549 
0550 static ngx_int_t
0551 ngx_stream_ssl_add_variables(ngx_conf_t *cf)
0552 {
0553     ngx_stream_variable_t  *var, *v;
0554 
0555     for (v = ngx_stream_ssl_vars; v->name.len; v++) {
0556         var = ngx_stream_add_variable(cf, &v->name, v->flags);
0557         if (var == NULL) {
0558             return NGX_ERROR;
0559         }
0560 
0561         var->get_handler = v->get_handler;
0562         var->data = v->data;
0563     }
0564 
0565     return NGX_OK;
0566 }
0567 
0568 
0569 static void *
0570 ngx_stream_ssl_create_conf(ngx_conf_t *cf)
0571 {
0572     ngx_stream_ssl_conf_t  *scf;
0573 
0574     scf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ssl_conf_t));
0575     if (scf == NULL) {
0576         return NULL;
0577     }
0578 
0579     /*
0580      * set by ngx_pcalloc():
0581      *
0582      *     scf->listen = 0;
0583      *     scf->protocols = 0;
0584      *     scf->certificate_values = NULL;
0585      *     scf->dhparam = { 0, NULL };
0586      *     scf->ecdh_curve = { 0, NULL };
0587      *     scf->client_certificate = { 0, NULL };
0588      *     scf->trusted_certificate = { 0, NULL };
0589      *     scf->crl = { 0, NULL };
0590      *     scf->ciphers = { 0, NULL };
0591      *     scf->shm_zone = NULL;
0592      */
0593 
0594     scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
0595     scf->certificates = NGX_CONF_UNSET_PTR;
0596     scf->certificate_keys = NGX_CONF_UNSET_PTR;
0597     scf->passwords = NGX_CONF_UNSET_PTR;
0598     scf->prefer_server_ciphers = NGX_CONF_UNSET;
0599     scf->verify = NGX_CONF_UNSET_UINT;
0600     scf->verify_depth = NGX_CONF_UNSET_UINT;
0601     scf->builtin_session_cache = NGX_CONF_UNSET;
0602     scf->session_timeout = NGX_CONF_UNSET;
0603     scf->session_tickets = NGX_CONF_UNSET;
0604     scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
0605 
0606     return scf;
0607 }
0608 
0609 
0610 static char *
0611 ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
0612 {
0613     ngx_stream_ssl_conf_t *prev = parent;
0614     ngx_stream_ssl_conf_t *conf = child;
0615 
0616     ngx_pool_cleanup_t  *cln;
0617 
0618     ngx_conf_merge_msec_value(conf->handshake_timeout,
0619                          prev->handshake_timeout, 60000);
0620 
0621     ngx_conf_merge_value(conf->session_timeout,
0622                          prev->session_timeout, 300);
0623 
0624     ngx_conf_merge_value(conf->prefer_server_ciphers,
0625                          prev->prefer_server_ciphers, 0);
0626 
0627     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
0628                          (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
0629                           |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
0630 
0631     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
0632     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
0633 
0634     ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
0635     ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
0636                          NULL);
0637 
0638     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
0639 
0640     ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
0641 
0642     ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
0643                          "");
0644     ngx_conf_merge_str_value(conf->trusted_certificate,
0645                          prev->trusted_certificate, "");
0646     ngx_conf_merge_str_value(conf->crl, prev->crl, "");
0647 
0648     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
0649                          NGX_DEFAULT_ECDH_CURVE);
0650 
0651     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
0652 
0653 
0654     conf->ssl.log = cf->log;
0655 
0656     if (!conf->listen) {
0657         return NGX_CONF_OK;
0658     }
0659 
0660     if (conf->certificates == NULL) {
0661         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0662                       "no \"ssl_certificate\" is defined for "
0663                       "the \"listen ... ssl\" directive in %s:%ui",
0664                       conf->file, conf->line);
0665         return NGX_CONF_ERROR;
0666     }
0667 
0668     if (conf->certificate_keys == NULL) {
0669         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0670                       "no \"ssl_certificate_key\" is defined for "
0671                       "the \"listen ... ssl\" directive in %s:%ui",
0672                       conf->file, conf->line);
0673         return NGX_CONF_ERROR;
0674     }
0675 
0676     if (conf->certificate_keys->nelts < conf->certificates->nelts) {
0677         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0678                       "no \"ssl_certificate_key\" is defined "
0679                       "for certificate \"%V\" and "
0680                       "the \"listen ... ssl\" directive in %s:%ui",
0681                       ((ngx_str_t *) conf->certificates->elts)
0682                       + conf->certificates->nelts - 1,
0683                       conf->file, conf->line);
0684         return NGX_CONF_ERROR;
0685     }
0686 
0687     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
0688         return NGX_CONF_ERROR;
0689     }
0690 
0691     cln = ngx_pool_cleanup_add(cf->pool, 0);
0692     if (cln == NULL) {
0693         ngx_ssl_cleanup_ctx(&conf->ssl);
0694         return NGX_CONF_ERROR;
0695     }
0696 
0697     cln->handler = ngx_ssl_cleanup_ctx;
0698     cln->data = &conf->ssl;
0699 
0700 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
0701     SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
0702                                            ngx_stream_ssl_servername);
0703 #endif
0704 
0705     if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) {
0706         return NGX_CONF_ERROR;
0707     }
0708 
0709     if (conf->certificate_values) {
0710 
0711 #ifdef SSL_R_CERT_CB_ERROR
0712 
0713         /* install callback to lookup certificates */
0714 
0715         SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, conf);
0716 
0717 #else
0718         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0719                       "variables in "
0720                       "\"ssl_certificate\" and \"ssl_certificate_key\" "
0721                       "directives are not supported on this platform");
0722         return NGX_CONF_ERROR;
0723 #endif
0724 
0725     } else {
0726 
0727         /* configure certificates */
0728 
0729         if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
0730                                  conf->certificate_keys, conf->passwords)
0731             != NGX_OK)
0732         {
0733             return NGX_CONF_ERROR;
0734         }
0735     }
0736 
0737     if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
0738                         conf->prefer_server_ciphers)
0739         != NGX_OK)
0740     {
0741         return NGX_CONF_ERROR;
0742     }
0743 
0744     if (conf->verify) {
0745 
0746         if (conf->client_certificate.len == 0 && conf->verify != 3) {
0747             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0748                           "no ssl_client_certificate for ssl_client_verify");
0749             return NGX_CONF_ERROR;
0750         }
0751 
0752         if (ngx_ssl_client_certificate(cf, &conf->ssl,
0753                                        &conf->client_certificate,
0754                                        conf->verify_depth)
0755             != NGX_OK)
0756         {
0757             return NGX_CONF_ERROR;
0758         }
0759 
0760         if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
0761                                         &conf->trusted_certificate,
0762                                         conf->verify_depth)
0763             != NGX_OK)
0764         {
0765             return NGX_CONF_ERROR;
0766         }
0767 
0768         if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
0769             return NGX_CONF_ERROR;
0770         }
0771     }
0772 
0773     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
0774         return NGX_CONF_ERROR;
0775     }
0776 
0777     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
0778         return NGX_CONF_ERROR;
0779     }
0780 
0781     ngx_conf_merge_value(conf->builtin_session_cache,
0782                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
0783 
0784     if (conf->shm_zone == NULL) {
0785         conf->shm_zone = prev->shm_zone;
0786     }
0787 
0788     if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx,
0789                               conf->certificates, conf->builtin_session_cache,
0790                               conf->shm_zone, conf->session_timeout)
0791         != NGX_OK)
0792     {
0793         return NGX_CONF_ERROR;
0794     }
0795 
0796     ngx_conf_merge_value(conf->session_tickets,
0797                          prev->session_tickets, 1);
0798 
0799 #ifdef SSL_OP_NO_TICKET
0800     if (!conf->session_tickets) {
0801         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
0802     }
0803 #endif
0804 
0805     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
0806                          prev->session_ticket_keys, NULL);
0807 
0808     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
0809         != NGX_OK)
0810     {
0811         return NGX_CONF_ERROR;
0812     }
0813 
0814     return NGX_CONF_OK;
0815 }
0816 
0817 
0818 static ngx_int_t
0819 ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
0820     ngx_stream_ssl_conf_t *conf)
0821 {
0822     ngx_str_t                           *cert, *key;
0823     ngx_uint_t                           i, nelts;
0824     ngx_stream_complex_value_t          *cv;
0825     ngx_stream_compile_complex_value_t   ccv;
0826 
0827     cert = conf->certificates->elts;
0828     key = conf->certificate_keys->elts;
0829     nelts = conf->certificates->nelts;
0830 
0831     for (i = 0; i < nelts; i++) {
0832 
0833         if (ngx_stream_script_variables_count(&cert[i])) {
0834             goto found;
0835         }
0836 
0837         if (ngx_stream_script_variables_count(&key[i])) {
0838             goto found;
0839         }
0840     }
0841 
0842     return NGX_OK;
0843 
0844 found:
0845 
0846     conf->certificate_values = ngx_array_create(cf->pool, nelts,
0847                                            sizeof(ngx_stream_complex_value_t));
0848     if (conf->certificate_values == NULL) {
0849         return NGX_ERROR;
0850     }
0851 
0852     conf->certificate_key_values = ngx_array_create(cf->pool, nelts,
0853                                            sizeof(ngx_stream_complex_value_t));
0854     if (conf->certificate_key_values == NULL) {
0855         return NGX_ERROR;
0856     }
0857 
0858     for (i = 0; i < nelts; i++) {
0859 
0860         cv = ngx_array_push(conf->certificate_values);
0861         if (cv == NULL) {
0862             return NGX_ERROR;
0863         }
0864 
0865         ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
0866 
0867         ccv.cf = cf;
0868         ccv.value = &cert[i];
0869         ccv.complex_value = cv;
0870         ccv.zero = 1;
0871 
0872         if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
0873             return NGX_ERROR;
0874         }
0875 
0876         cv = ngx_array_push(conf->certificate_key_values);
0877         if (cv == NULL) {
0878             return NGX_ERROR;
0879         }
0880 
0881         ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
0882 
0883         ccv.cf = cf;
0884         ccv.value = &key[i];
0885         ccv.complex_value = cv;
0886         ccv.zero = 1;
0887 
0888         if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
0889             return NGX_ERROR;
0890         }
0891     }
0892 
0893     conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords);
0894     if (conf->passwords == NULL) {
0895         return NGX_ERROR;
0896     }
0897 
0898     return NGX_OK;
0899 }
0900 
0901 
0902 static char *
0903 ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0904 {
0905     ngx_stream_ssl_conf_t  *scf = conf;
0906 
0907     ngx_str_t  *value;
0908 
0909     if (scf->passwords != NGX_CONF_UNSET_PTR) {
0910         return "is duplicate";
0911     }
0912 
0913     value = cf->args->elts;
0914 
0915     scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
0916 
0917     if (scf->passwords == NULL) {
0918         return NGX_CONF_ERROR;
0919     }
0920 
0921     return NGX_CONF_OK;
0922 }
0923 
0924 
0925 static char *
0926 ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0927 {
0928     ngx_stream_ssl_conf_t  *scf = conf;
0929 
0930     size_t       len;
0931     ngx_str_t   *value, name, size;
0932     ngx_int_t    n;
0933     ngx_uint_t   i, j;
0934 
0935     value = cf->args->elts;
0936 
0937     for (i = 1; i < cf->args->nelts; i++) {
0938 
0939         if (ngx_strcmp(value[i].data, "off") == 0) {
0940             scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
0941             continue;
0942         }
0943 
0944         if (ngx_strcmp(value[i].data, "none") == 0) {
0945             scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
0946             continue;
0947         }
0948 
0949         if (ngx_strcmp(value[i].data, "builtin") == 0) {
0950             scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
0951             continue;
0952         }
0953 
0954         if (value[i].len > sizeof("builtin:") - 1
0955             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
0956                == 0)
0957         {
0958             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
0959                          value[i].len - (sizeof("builtin:") - 1));
0960 
0961             if (n == NGX_ERROR) {
0962                 goto invalid;
0963             }
0964 
0965             scf->builtin_session_cache = n;
0966 
0967             continue;
0968         }
0969 
0970         if (value[i].len > sizeof("shared:") - 1
0971             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
0972                == 0)
0973         {
0974             len = 0;
0975 
0976             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
0977                 if (value[i].data[j] == ':') {
0978                     break;
0979                 }
0980 
0981                 len++;
0982             }
0983 
0984             if (len == 0) {
0985                 goto invalid;
0986             }
0987 
0988             name.len = len;
0989             name.data = value[i].data + sizeof("shared:") - 1;
0990 
0991             size.len = value[i].len - j - 1;
0992             size.data = name.data + len + 1;
0993 
0994             n = ngx_parse_size(&size);
0995 
0996             if (n == NGX_ERROR) {
0997                 goto invalid;
0998             }
0999 
1000             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
1001                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1002                                    "session cache \"%V\" is too small",
1003                                    &value[i]);
1004 
1005                 return NGX_CONF_ERROR;
1006             }
1007 
1008             scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
1009                                                    &ngx_stream_ssl_module);
1010             if (scf->shm_zone == NULL) {
1011                 return NGX_CONF_ERROR;
1012             }
1013 
1014             scf->shm_zone->init = ngx_ssl_session_cache_init;
1015 
1016             continue;
1017         }
1018 
1019         goto invalid;
1020     }
1021 
1022     if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
1023         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
1024     }
1025 
1026     return NGX_CONF_OK;
1027 
1028 invalid:
1029 
1030     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1031                        "invalid session cache \"%V\"", &value[i]);
1032 
1033     return NGX_CONF_ERROR;
1034 }
1035 
1036 
1037 static ngx_int_t
1038 ngx_stream_ssl_init(ngx_conf_t *cf)
1039 {
1040     ngx_stream_handler_pt        *h;
1041     ngx_stream_core_main_conf_t  *cmcf;
1042 
1043     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
1044 
1045     h = ngx_array_push(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers);
1046     if (h == NULL) {
1047         return NGX_ERROR;
1048     }
1049 
1050     *h = ngx_stream_ssl_handler;
1051 
1052     return NGX_OK;
1053 }