1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) Nginx, Inc. 5 */ 6 7 8 #include <ngx_config.h> 9 #include <ngx_core.h> 10 #include <ngx_stream.h> 11 12 13 typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c, 14 ngx_pool_t *pool, ngx_str_t *s); 15 16 17 #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" 18 #define NGX_DEFAULT_ECDH_CURVE "auto" 19 20 21 static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s); 22 static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, 23 ngx_connection_t *c); 24 static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c); 25 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME 26 int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg); 27 #endif 28 #ifdef SSL_R_CERT_CB_ERROR 29 static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg); 30 #endif 31 static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s, 32 ngx_stream_variable_value_t *v, uintptr_t data); 33 static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s, 34 ngx_stream_variable_value_t *v, uintptr_t data); 35 36 static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf); 37 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf); 38 static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, 39 void *child); 40 41 static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, 42 ngx_stream_ssl_conf_t *conf); 43 44 static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, 45 void *conf); 46 static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, 47 void *conf); 48 49 static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, 50 void *data); 51 52 static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf); 53 54 55 static ngx_conf_bitmask_t ngx_stream_ssl_protocols[] = { 56 { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, 57 { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, 58 { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, 59 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, 60 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, 61 { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, 62 { ngx_null_string, 0 } 63 }; 64 65 66 static ngx_conf_enum_t ngx_stream_ssl_verify[] = { 67 { ngx_string("off"), 0 }, 68 { ngx_string("on"), 1 }, 69 { ngx_string("optional"), 2 }, 70 { ngx_string("optional_no_ca"), 3 }, 71 { ngx_null_string, 0 } 72 }; 73 74 75 static ngx_conf_post_t ngx_stream_ssl_conf_command_post = 76 { ngx_stream_ssl_conf_command_check }; 77 78 79 static ngx_command_t ngx_stream_ssl_commands[] = { 80 81 { ngx_string("ssl_handshake_timeout"), 82 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 83 ngx_conf_set_msec_slot, 84 NGX_STREAM_SRV_CONF_OFFSET, 85 offsetof(ngx_stream_ssl_conf_t, handshake_timeout), 86 NULL }, 87 88 { ngx_string("ssl_certificate"), 89 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 90 ngx_conf_set_str_array_slot, 91 NGX_STREAM_SRV_CONF_OFFSET, 92 offsetof(ngx_stream_ssl_conf_t, certificates), 93 NULL }, 94 95 { ngx_string("ssl_certificate_key"), 96 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 97 ngx_conf_set_str_array_slot, 98 NGX_STREAM_SRV_CONF_OFFSET, 99 offsetof(ngx_stream_ssl_conf_t, certificate_keys), 100 NULL }, 101 102 { ngx_string("ssl_password_file"), 103 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 104 ngx_stream_ssl_password_file, 105 NGX_STREAM_SRV_CONF_OFFSET, 106 0, 107 NULL }, 108 109 { ngx_string("ssl_dhparam"), 110 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 111 ngx_conf_set_str_slot, 112 NGX_STREAM_SRV_CONF_OFFSET, 113 offsetof(ngx_stream_ssl_conf_t, dhparam), 114 NULL }, 115 116 { ngx_string("ssl_ecdh_curve"), 117 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 118 ngx_conf_set_str_slot, 119 NGX_STREAM_SRV_CONF_OFFSET, 120 offsetof(ngx_stream_ssl_conf_t, ecdh_curve), 121 NULL }, 122 123 { ngx_string("ssl_protocols"), 124 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, 125 ngx_conf_set_bitmask_slot, 126 NGX_STREAM_SRV_CONF_OFFSET, 127 offsetof(ngx_stream_ssl_conf_t, protocols), 128 &ngx_stream_ssl_protocols }, 129 130 { ngx_string("ssl_ciphers"), 131 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 132 ngx_conf_set_str_slot, 133 NGX_STREAM_SRV_CONF_OFFSET, 134 offsetof(ngx_stream_ssl_conf_t, ciphers), 135 NULL }, 136 137 { ngx_string("ssl_verify_client"), 138 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 139 ngx_conf_set_enum_slot, 140 NGX_STREAM_SRV_CONF_OFFSET, 141 offsetof(ngx_stream_ssl_conf_t, verify), 142 &ngx_stream_ssl_verify }, 143 144 { ngx_string("ssl_verify_depth"), 145 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 146 ngx_conf_set_num_slot, 147 NGX_STREAM_SRV_CONF_OFFSET, 148 offsetof(ngx_stream_ssl_conf_t, verify_depth), 149 NULL }, 150 151 { ngx_string("ssl_client_certificate"), 152 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 153 ngx_conf_set_str_slot, 154 NGX_STREAM_SRV_CONF_OFFSET, 155 offsetof(ngx_stream_ssl_conf_t, client_certificate), 156 NULL }, 157 158 { ngx_string("ssl_trusted_certificate"), 159 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 160 ngx_conf_set_str_slot, 161 NGX_STREAM_SRV_CONF_OFFSET, 162 offsetof(ngx_stream_ssl_conf_t, trusted_certificate), 163 NULL }, 164 165 { ngx_string("ssl_prefer_server_ciphers"), 166 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, 167 ngx_conf_set_flag_slot, 168 NGX_STREAM_SRV_CONF_OFFSET, 169 offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers), 170 NULL }, 171 172 { ngx_string("ssl_session_cache"), 173 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12, 174 ngx_stream_ssl_session_cache, 175 NGX_STREAM_SRV_CONF_OFFSET, 176 0, 177 NULL }, 178 179 { ngx_string("ssl_session_tickets"), 180 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, 181 ngx_conf_set_flag_slot, 182 NGX_STREAM_SRV_CONF_OFFSET, 183 offsetof(ngx_stream_ssl_conf_t, session_tickets), 184 NULL }, 185 186 { ngx_string("ssl_session_ticket_key"), 187 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 188 ngx_conf_set_str_array_slot, 189 NGX_STREAM_SRV_CONF_OFFSET, 190 offsetof(ngx_stream_ssl_conf_t, session_ticket_keys), 191 NULL }, 192 193 { ngx_string("ssl_session_timeout"), 194 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 195 ngx_conf_set_sec_slot, 196 NGX_STREAM_SRV_CONF_OFFSET, 197 offsetof(ngx_stream_ssl_conf_t, session_timeout), 198 NULL }, 199 200 { ngx_string("ssl_crl"), 201 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 202 ngx_conf_set_str_slot, 203 NGX_STREAM_SRV_CONF_OFFSET, 204 offsetof(ngx_stream_ssl_conf_t, crl), 205 NULL }, 206 207 { ngx_string("ssl_conf_command"), 208 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2, 209 ngx_conf_set_keyval_slot, 210 NGX_STREAM_SRV_CONF_OFFSET, 211 offsetof(ngx_stream_ssl_conf_t, conf_commands), 212 &ngx_stream_ssl_conf_command_post }, 213 214 ngx_null_command 215 }; 216 217 218 static ngx_stream_module_t ngx_stream_ssl_module_ctx = { 219 ngx_stream_ssl_add_variables, /* preconfiguration */ 220 ngx_stream_ssl_init, /* postconfiguration */ 221 222 NULL, /* create main configuration */ 223 NULL, /* init main configuration */ 224 225 ngx_stream_ssl_create_conf, /* create server configuration */ 226 ngx_stream_ssl_merge_conf /* merge server configuration */ 227 }; 228 229 230 ngx_module_t ngx_stream_ssl_module = { 231 NGX_MODULE_V1, 232 &ngx_stream_ssl_module_ctx, /* module context */ 233 ngx_stream_ssl_commands, /* module directives */ 234 NGX_STREAM_MODULE, /* module type */ 235 NULL, /* init master */ 236 NULL, /* init module */ 237 NULL, /* init process */ 238 NULL, /* init thread */ 239 NULL, /* exit thread */ 240 NULL, /* exit process */ 241 NULL, /* exit master */ 242 NGX_MODULE_V1_PADDING 243 }; 244 245 246 static ngx_stream_variable_t ngx_stream_ssl_vars[] = { 247 248 { ngx_string("ssl_protocol"), NULL, ngx_stream_ssl_static_variable, 249 (uintptr_t) ngx_ssl_get_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 }, 250 251 { ngx_string("ssl_cipher"), NULL, ngx_stream_ssl_static_variable, 252 (uintptr_t) ngx_ssl_get_cipher_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, 253 254 { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable, 255 (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 }, 256 257 { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable, 258 (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 }, 259 260 { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable, 261 (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 }, 262 263 { ngx_string("ssl_session_reused"), NULL, ngx_stream_ssl_variable, 264 (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 }, 265 266 { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable, 267 (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, 268 269 { ngx_string("ssl_alpn_protocol"), NULL, ngx_stream_ssl_variable, 270 (uintptr_t) ngx_ssl_get_alpn_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 }, 271 272 { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable, 273 (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 }, 274 275 { ngx_string("ssl_client_raw_cert"), NULL, ngx_stream_ssl_variable, 276 (uintptr_t) ngx_ssl_get_raw_certificate, 277 NGX_STREAM_VAR_CHANGEABLE, 0 }, 278 279 { ngx_string("ssl_client_escaped_cert"), NULL, ngx_stream_ssl_variable, 280 (uintptr_t) ngx_ssl_get_escaped_certificate, 281 NGX_STREAM_VAR_CHANGEABLE, 0 }, 282 283 { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable, 284 (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 }, 285 286 { ngx_string("ssl_client_i_dn"), NULL, ngx_stream_ssl_variable, 287 (uintptr_t) ngx_ssl_get_issuer_dn, NGX_STREAM_VAR_CHANGEABLE, 0 }, 288 289 { ngx_string("ssl_client_serial"), NULL, ngx_stream_ssl_variable, 290 (uintptr_t) ngx_ssl_get_serial_number, NGX_STREAM_VAR_CHANGEABLE, 0 }, 291 292 { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable, 293 (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 }, 294 295 { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable, 296 (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 }, 297 298 { ngx_string("ssl_client_v_start"), NULL, ngx_stream_ssl_variable, 299 (uintptr_t) ngx_ssl_get_client_v_start, NGX_STREAM_VAR_CHANGEABLE, 0 }, 300 301 { ngx_string("ssl_client_v_end"), NULL, ngx_stream_ssl_variable, 302 (uintptr_t) ngx_ssl_get_client_v_end, NGX_STREAM_VAR_CHANGEABLE, 0 }, 303 304 { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable, 305 (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 }, 306 307 ngx_stream_null_variable 308 }; 309 310 311 static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM"); 312 313 314 static ngx_int_t 315 ngx_stream_ssl_handler(ngx_stream_session_t *s) 316 { 317 long rc; 318 X509 *cert; 319 ngx_int_t rv; 320 ngx_connection_t *c; 321 ngx_stream_ssl_conf_t *sslcf; 322 323 if (!s->ssl) { 324 return NGX_OK; 325 } 326 327 c = s->connection; 328 329 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); 330 331 if (c->ssl == NULL) { 332 c->log->action = "SSL handshaking"; 333 334 rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c); 335 336 if (rv != NGX_OK) { 337 return rv; 338 } 339 } 340 341 if (sslcf->verify) { 342 rc = SSL_get_verify_result(c->ssl->connection); 343 344 if (rc != X509_V_OK 345 && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc))) 346 { 347 ngx_log_error(NGX_LOG_INFO, c->log, 0, 348 "client SSL certificate verify error: (%l:%s)", 349 rc, X509_verify_cert_error_string(rc)); 350 351 ngx_ssl_remove_cached_session(c->ssl->session_ctx, 352 (SSL_get0_session(c->ssl->connection))); 353 return NGX_ERROR; 354 } 355 356 if (sslcf->verify == 1) { 357 cert = SSL_get_peer_certificate(c->ssl->connection); 358 359 if (cert == NULL) { 360 ngx_log_error(NGX_LOG_INFO, c->log, 0, 361 "client sent no required SSL certificate"); 362 363 ngx_ssl_remove_cached_session(c->ssl->session_ctx, 364 (SSL_get0_session(c->ssl->connection))); 365 return NGX_ERROR; 366 } 367 368 X509_free(cert); 369 } 370 } 371 372 return NGX_OK; 373 } 374 375 376 static ngx_int_t 377 ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) 378 { 379 ngx_int_t rc; 380 ngx_stream_session_t *s; 381 ngx_stream_ssl_conf_t *sslcf; 382 ngx_stream_core_srv_conf_t *cscf; 383 384 s = c->data; 385 386 cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); 387 388 if (cscf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { 389 return NGX_ERROR; 390 } 391 392 if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) { 393 return NGX_ERROR; 394 } 395 396 rc = ngx_ssl_handshake(c); 397 398 if (rc == NGX_ERROR) { 399 return NGX_ERROR; 400 } 401 402 if (rc == NGX_AGAIN) { 403 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); 404 405 ngx_add_timer(c->read, sslcf->handshake_timeout); 406 407 c->ssl->handler = ngx_stream_ssl_handshake_handler; 408 409 return NGX_AGAIN; 410 } 411 412 /* rc == NGX_OK */ 413 414 return NGX_OK; 415 } 416 417 418 static void 419 ngx_stream_ssl_handshake_handler(ngx_connection_t *c) 420 { 421 ngx_stream_session_t *s; 422 423 s = c->data; 424 425 if (!c->ssl->handshaked) { 426 ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); 427 return; 428 } 429 430 if (c->read->timer_set) { 431 ngx_del_timer(c->read); 432 } 433 434 ngx_stream_core_run_phases(s); 435 } 436 437 438 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME 439 440 int 441 ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) 442 { 443 return SSL_TLSEXT_ERR_OK; 444 } 445 446 #endif 447 448 449 #ifdef SSL_R_CERT_CB_ERROR 450 451 int 452 ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) 453 { 454 ngx_str_t cert, key; 455 ngx_uint_t i, nelts; 456 ngx_connection_t *c; 457 ngx_stream_session_t *s; 458 ngx_stream_ssl_conf_t *sslcf; 459 ngx_stream_complex_value_t *certs, *keys; 460 461 c = ngx_ssl_get_connection(ssl_conn); 462 463 if (c->ssl->handshaked) { 464 return 0; 465 } 466 467 s = c->data; 468 469 sslcf = arg; 470 471 nelts = sslcf->certificate_values->nelts; 472 certs = sslcf->certificate_values->elts; 473 keys = sslcf->certificate_key_values->elts; 474 475 for (i = 0; i < nelts; i++) { 476 477 if (ngx_stream_complex_value(s, &certs[i], &cert) != NGX_OK) { 478 return 0; 479 } 480 481 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, 482 "ssl cert: \"%s\"", cert.data); 483 484 if (ngx_stream_complex_value(s, &keys[i], &key) != NGX_OK) { 485 return 0; 486 } 487 488 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, 489 "ssl key: \"%s\"", key.data); 490 491 if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key, 492 sslcf->passwords) 493 != NGX_OK) 494 { 495 return 0; 496 } 497 } 498 499 return 1; 500 } 501 502 #endif 503 504 505 static ngx_int_t 506 ngx_stream_ssl_static_variable(ngx_stream_session_t *s, 507 ngx_stream_variable_value_t *v, uintptr_t data) 508 { 509 ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; 510 511 size_t len; 512 ngx_str_t str; 513 514 if (s->connection->ssl) { 515 516 (void) handler(s->connection, NULL, &str); 517 518 v->data = str.data; 519 520 for (len = 0; v->data[len]; len++) { /* void */ } 521 522 v->len = len; 523 v->valid = 1; 524 v->no_cacheable = 0; 525 v->not_found = 0; 526 527 return NGX_OK; 528 } 529 530 v->not_found = 1; 531 532 return NGX_OK; 533 } 534 535 536 static ngx_int_t 537 ngx_stream_ssl_variable(ngx_stream_session_t *s, 538 ngx_stream_variable_value_t *v, uintptr_t data) 539 { 540 ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; 541 542 ngx_str_t str; 543 544 if (s->connection->ssl) { 545 546 if (handler(s->connection, s->connection->pool, &str) != NGX_OK) { 547 return NGX_ERROR; 548 } 549 550 v->len = str.len; 551 v->data = str.data; 552 553 if (v->len) { 554 v->valid = 1; 555 v->no_cacheable = 0; 556 v->not_found = 0; 557 558 return NGX_OK; 559 } 560 } 561 562 v->not_found = 1; 563 564 return NGX_OK; 565 } 566 567 568 static ngx_int_t 569 ngx_stream_ssl_add_variables(ngx_conf_t *cf) 570 { 571 ngx_stream_variable_t *var, *v; 572 573 for (v = ngx_stream_ssl_vars; v->name.len; v++) { 574 var = ngx_stream_add_variable(cf, &v->name, v->flags); 575 if (var == NULL) { 576 return NGX_ERROR; 577 } 578 579 var->get_handler = v->get_handler; 580 var->data = v->data; 581 } 582 583 return NGX_OK; 584 } 585 586 587 static void * 588 ngx_stream_ssl_create_conf(ngx_conf_t *cf) 589 { 590 ngx_stream_ssl_conf_t *scf; 591 592 scf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ssl_conf_t)); 593 if (scf == NULL) { 594 return NULL; 595 } 596 597 /* 598 * set by ngx_pcalloc(): 599 * 600 * scf->listen = 0; 601 * scf->protocols = 0; 602 * scf->certificate_values = NULL; 603 * scf->dhparam = { 0, NULL }; 604 * scf->ecdh_curve = { 0, NULL }; 605 * scf->client_certificate = { 0, NULL }; 606 * scf->trusted_certificate = { 0, NULL }; 607 * scf->crl = { 0, NULL }; 608 * scf->ciphers = { 0, NULL }; 609 * scf->shm_zone = NULL; 610 */ 611 612 scf->handshake_timeout = NGX_CONF_UNSET_MSEC; 613 scf->certificates = NGX_CONF_UNSET_PTR; 614 scf->certificate_keys = NGX_CONF_UNSET_PTR; 615 scf->passwords = NGX_CONF_UNSET_PTR; 616 scf->conf_commands = NGX_CONF_UNSET_PTR; 617 scf->prefer_server_ciphers = NGX_CONF_UNSET; 618 scf->verify = NGX_CONF_UNSET_UINT; 619 scf->verify_depth = NGX_CONF_UNSET_UINT; 620 scf->builtin_session_cache = NGX_CONF_UNSET; 621 scf->session_timeout = NGX_CONF_UNSET; 622 scf->session_tickets = NGX_CONF_UNSET; 623 scf->session_ticket_keys = NGX_CONF_UNSET_PTR; 624 625 return scf; 626 } 627 628 629 static char * 630 ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) 631 { 632 ngx_stream_ssl_conf_t *prev = parent; 633 ngx_stream_ssl_conf_t *conf = child; 634 635 ngx_pool_cleanup_t *cln; 636 637 ngx_conf_merge_msec_value(conf->handshake_timeout, 638 prev->handshake_timeout, 60000); 639 640 ngx_conf_merge_value(conf->session_timeout, 641 prev->session_timeout, 300); 642 643 ngx_conf_merge_value(conf->prefer_server_ciphers, 644 prev->prefer_server_ciphers, 0); 645 646 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, 647 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 648 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); 649 650 ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); 651 ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); 652 653 ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); 654 ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, 655 NULL); 656 657 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); 658 659 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); 660 661 ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, 662 ""); 663 ngx_conf_merge_str_value(conf->trusted_certificate, 664 prev->trusted_certificate, ""); 665 ngx_conf_merge_str_value(conf->crl, prev->crl, ""); 666 667 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, 668 NGX_DEFAULT_ECDH_CURVE); 669 670 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); 671 672 ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL); 673 674 675 conf->ssl.log = cf->log; 676 677 if (!conf->listen) { 678 return NGX_CONF_OK; 679 } 680 681 if (conf->certificates == NULL) { 682 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 683 "no \"ssl_certificate\" is defined for " 684 "the \"listen ... ssl\" directive in %s:%ui", 685 conf->file, conf->line); 686 return NGX_CONF_ERROR; 687 } 688 689 if (conf->certificate_keys == NULL) { 690 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 691 "no \"ssl_certificate_key\" is defined for " 692 "the \"listen ... ssl\" directive in %s:%ui", 693 conf->file, conf->line); 694 return NGX_CONF_ERROR; 695 } 696 697 if (conf->certificate_keys->nelts < conf->certificates->nelts) { 698 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 699 "no \"ssl_certificate_key\" is defined " 700 "for certificate \"%V\" and " 701 "the \"listen ... ssl\" directive in %s:%ui", 702 ((ngx_str_t *) conf->certificates->elts) 703 + conf->certificates->nelts - 1, 704 conf->file, conf->line); 705 return NGX_CONF_ERROR; 706 } 707 708 if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { 709 return NGX_CONF_ERROR; 710 } 711 712 cln = ngx_pool_cleanup_add(cf->pool, 0); 713 if (cln == NULL) { 714 ngx_ssl_cleanup_ctx(&conf->ssl); 715 return NGX_CONF_ERROR; 716 } 717 718 cln->handler = ngx_ssl_cleanup_ctx; 719 cln->data = &conf->ssl; 720 721 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME 722 SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, 723 ngx_stream_ssl_servername); 724 #endif 725 726 if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, 727 conf->prefer_server_ciphers) 728 != NGX_OK) 729 { 730 return NGX_CONF_ERROR; 731 } 732 733 if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) { 734 return NGX_CONF_ERROR; 735 } 736 737 if (conf->certificate_values) { 738 739 #ifdef SSL_R_CERT_CB_ERROR 740 741 /* install callback to lookup certificates */ 742 743 SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, conf); 744 745 #else 746 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 747 "variables in " 748 "\"ssl_certificate\" and \"ssl_certificate_key\" " 749 "directives are not supported on this platform"); 750 return NGX_CONF_ERROR; 751 #endif 752 753 } else { 754 755 /* configure certificates */ 756 757 if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, 758 conf->certificate_keys, conf->passwords) 759 != NGX_OK) 760 { 761 return NGX_CONF_ERROR; 762 } 763 } 764 765 if (conf->verify) { 766 767 if (conf->client_certificate.len == 0 && conf->verify != 3) { 768 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 769 "no ssl_client_certificate for ssl_verify_client"); 770 return NGX_CONF_ERROR; 771 } 772 773 if (ngx_ssl_client_certificate(cf, &conf->ssl, 774 &conf->client_certificate, 775 conf->verify_depth) 776 != NGX_OK) 777 { 778 return NGX_CONF_ERROR; 779 } 780 781 if (ngx_ssl_trusted_certificate(cf, &conf->ssl, 782 &conf->trusted_certificate, 783 conf->verify_depth) 784 != NGX_OK) 785 { 786 return NGX_CONF_ERROR; 787 } 788 789 if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { 790 return NGX_CONF_ERROR; 791 } 792 } 793 794 if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { 795 return NGX_CONF_ERROR; 796 } 797 798 if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { 799 return NGX_CONF_ERROR; 800 } 801 802 ngx_conf_merge_value(conf->builtin_session_cache, 803 prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); 804 805 if (conf->shm_zone == NULL) { 806 conf->shm_zone = prev->shm_zone; 807 } 808 809 if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx, 810 conf->certificates, conf->builtin_session_cache, 811 conf->shm_zone, conf->session_timeout) 812 != NGX_OK) 813 { 814 return NGX_CONF_ERROR; 815 } 816 817 ngx_conf_merge_value(conf->session_tickets, 818 prev->session_tickets, 1); 819 820 #ifdef SSL_OP_NO_TICKET 821 if (!conf->session_tickets) { 822 SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET); 823 } 824 #endif 825 826 ngx_conf_merge_ptr_value(conf->session_ticket_keys, 827 prev->session_ticket_keys, NULL); 828 829 if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) 830 != NGX_OK) 831 { 832 return NGX_CONF_ERROR; 833 } 834 835 if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) { 836 return NGX_CONF_ERROR; 837 } 838 839 return NGX_CONF_OK; 840 } 841 842 843 static ngx_int_t 844 ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, 845 ngx_stream_ssl_conf_t *conf) 846 { 847 ngx_str_t *cert, *key; 848 ngx_uint_t i, nelts; 849 ngx_stream_complex_value_t *cv; 850 ngx_stream_compile_complex_value_t ccv; 851 852 cert = conf->certificates->elts; 853 key = conf->certificate_keys->elts; 854 nelts = conf->certificates->nelts; 855 856 for (i = 0; i < nelts; i++) { 857 858 if (ngx_stream_script_variables_count(&cert[i])) { 859 goto found; 860 } 861 862 if (ngx_stream_script_variables_count(&key[i])) { 863 goto found; 864 } 865 } 866 867 return NGX_OK; 868 869 found: 870 871 conf->certificate_values = ngx_array_create(cf->pool, nelts, 872 sizeof(ngx_stream_complex_value_t)); 873 if (conf->certificate_values == NULL) { 874 return NGX_ERROR; 875 } 876 877 conf->certificate_key_values = ngx_array_create(cf->pool, nelts, 878 sizeof(ngx_stream_complex_value_t)); 879 if (conf->certificate_key_values == NULL) { 880 return NGX_ERROR; 881 } 882 883 for (i = 0; i < nelts; i++) { 884 885 cv = ngx_array_push(conf->certificate_values); 886 if (cv == NULL) { 887 return NGX_ERROR; 888 } 889 890 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); 891 892 ccv.cf = cf; 893 ccv.value = &cert[i]; 894 ccv.complex_value = cv; 895 ccv.zero = 1; 896 897 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { 898 return NGX_ERROR; 899 } 900 901 cv = ngx_array_push(conf->certificate_key_values); 902 if (cv == NULL) { 903 return NGX_ERROR; 904 } 905 906 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); 907 908 ccv.cf = cf; 909 ccv.value = &key[i]; 910 ccv.complex_value = cv; 911 ccv.zero = 1; 912 913 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { 914 return NGX_ERROR; 915 } 916 } 917 918 conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords); 919 if (conf->passwords == NULL) { 920 return NGX_ERROR; 921 } 922 923 return NGX_OK; 924 } 925 926 927 static char * 928 ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 929 { 930 ngx_stream_ssl_conf_t *scf = conf; 931 932 ngx_str_t *value; 933 934 if (scf->passwords != NGX_CONF_UNSET_PTR) { 935 return "is duplicate"; 936 } 937 938 value = cf->args->elts; 939 940 scf->passwords = ngx_ssl_read_password_file(cf, &value[1]); 941 942 if (scf->passwords == NULL) { 943 return NGX_CONF_ERROR; 944 } 945 946 return NGX_CONF_OK; 947 } 948 949 950 static char * 951 ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 952 { 953 ngx_stream_ssl_conf_t *scf = conf; 954 955 size_t len; 956 ngx_str_t *value, name, size; 957 ngx_int_t n; 958 ngx_uint_t i, j; 959 960 value = cf->args->elts; 961 962 for (i = 1; i < cf->args->nelts; i++) { 963 964 if (ngx_strcmp(value[i].data, "off") == 0) { 965 scf->builtin_session_cache = NGX_SSL_NO_SCACHE; 966 continue; 967 } 968 969 if (ngx_strcmp(value[i].data, "none") == 0) { 970 scf->builtin_session_cache = NGX_SSL_NONE_SCACHE; 971 continue; 972 } 973 974 if (ngx_strcmp(value[i].data, "builtin") == 0) { 975 scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE; 976 continue; 977 } 978 979 if (value[i].len > sizeof("builtin:") - 1 980 && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1) 981 == 0) 982 { 983 n = ngx_atoi(value[i].data + sizeof("builtin:") - 1, 984 value[i].len - (sizeof("builtin:") - 1)); 985 986 if (n == NGX_ERROR) { 987 goto invalid; 988 } 989 990 scf->builtin_session_cache = n; 991 992 continue; 993 } 994 995 if (value[i].len > sizeof("shared:") - 1 996 && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1) 997 == 0) 998 { 999 len = 0; 1000 1001 for (j = sizeof("shared:") - 1; j < value[i].len; j++) { 1002 if (value[i].data[j] == ':') { 1003 break; 1004 } 1005 1006 len++; 1007 } 1008 1009 if (len == 0) { 1010 goto invalid; 1011 } 1012 1013 name.len = len; 1014 name.data = value[i].data + sizeof("shared:") - 1; 1015 1016 size.len = value[i].len - j - 1; 1017 size.data = name.data + len + 1; 1018 1019 n = ngx_parse_size(&size); 1020 1021 if (n == NGX_ERROR) { 1022 goto invalid; 1023 } 1024 1025 if (n < (ngx_int_t) (8 * ngx_pagesize)) { 1026 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1027 "session cache \"%V\" is too small", 1028 &value[i]); 1029 1030 return NGX_CONF_ERROR; 1031 } 1032 1033 scf->shm_zone = ngx_shared_memory_add(cf, &name, n, 1034 &ngx_stream_ssl_module); 1035 if (scf->shm_zone == NULL) { 1036 return NGX_CONF_ERROR; 1037 } 1038 1039 scf->shm_zone->init = ngx_ssl_session_cache_init; 1040 1041 continue; 1042 } 1043 1044 goto invalid; 1045 } 1046 1047 if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) { 1048 scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE; 1049 } 1050 1051 return NGX_CONF_OK; 1052 1053 invalid: 1054 1055 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1056 "invalid session cache \"%V\"", &value[i]); 1057 1058 return NGX_CONF_ERROR; 1059 } 1060 1061 1062 static char * 1063 ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) 1064 { 1065 #ifndef SSL_CONF_FLAG_FILE 1066 return "is not supported on this platform"; 1067 #else 1068 return NGX_CONF_OK; 1069 #endif 1070 } 1071 1072 1073 static ngx_int_t 1074 ngx_stream_ssl_init(ngx_conf_t *cf) 1075 { 1076 ngx_stream_handler_pt *h; 1077 ngx_stream_core_main_conf_t *cmcf; 1078 1079 cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); 1080 1081 h = ngx_array_push(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers); 1082 if (h == NULL) { 1083 return NGX_ERROR; 1084 } 1085 1086 *h = ngx_stream_ssl_handler; 1087 1088 return NGX_OK; 1089 } 1090