Mercurial > hg > nginx
comparison src/stream/ngx_stream_ssl_module.c @ 7464:e970de27966a
SSL: dynamic certificate loading in the stream module.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Feb 2019 16:42:43 +0300 |
parents | 7f955d3b9a0d |
children | 6708bec13757 |
comparison
equal
deleted
inserted
replaced
7463:180df83473a4 | 7464:e970de27966a |
---|---|
20 | 20 |
21 static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s); | 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, | 22 static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, |
23 ngx_connection_t *c); | 23 ngx_connection_t *c); |
24 static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c); | 24 static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c); |
25 #ifdef SSL_R_CERT_CB_ERROR | |
26 static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg); | |
27 #endif | |
25 static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s, | 28 static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s, |
26 ngx_stream_variable_value_t *v, uintptr_t data); | 29 ngx_stream_variable_value_t *v, uintptr_t data); |
27 static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s, | 30 static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s, |
28 ngx_stream_variable_value_t *v, uintptr_t data); | 31 ngx_stream_variable_value_t *v, uintptr_t data); |
29 | 32 |
30 static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf); | 33 static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf); |
31 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf); | 34 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf); |
32 static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, | 35 static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, |
33 void *child); | 36 void *child); |
37 | |
38 static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, | |
39 ngx_stream_ssl_conf_t *conf); | |
34 | 40 |
35 static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, | 41 static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, |
36 void *conf); | 42 void *conf); |
37 static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, | 43 static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, |
38 void *conf); | 44 void *conf); |
406 | 412 |
407 ngx_stream_core_run_phases(s); | 413 ngx_stream_core_run_phases(s); |
408 } | 414 } |
409 | 415 |
410 | 416 |
417 #ifdef SSL_R_CERT_CB_ERROR | |
418 | |
419 int | |
420 ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) | |
421 { | |
422 ngx_str_t cert, key; | |
423 ngx_uint_t i, nelts; | |
424 ngx_connection_t *c; | |
425 ngx_stream_session_t *s; | |
426 ngx_stream_ssl_conf_t *sslcf; | |
427 ngx_stream_complex_value_t *certs, *keys; | |
428 | |
429 c = ngx_ssl_get_connection(ssl_conn); | |
430 | |
431 if (c->ssl->handshaked) { | |
432 return 0; | |
433 } | |
434 | |
435 s = c->data; | |
436 | |
437 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); | |
438 | |
439 nelts = sslcf->certificate_values->nelts; | |
440 certs = sslcf->certificate_values->elts; | |
441 keys = sslcf->certificate_key_values->elts; | |
442 | |
443 for (i = 0; i < nelts; i++) { | |
444 | |
445 if (ngx_stream_complex_value(s, &certs[i], &cert) != NGX_OK) { | |
446 return 0; | |
447 } | |
448 | |
449 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, | |
450 "ssl cert: \"%s\"", cert.data); | |
451 | |
452 if (ngx_stream_complex_value(s, &keys[i], &key) != NGX_OK) { | |
453 return 0; | |
454 } | |
455 | |
456 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, | |
457 "ssl key: \"%s\"", key.data); | |
458 | |
459 if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key, | |
460 sslcf->passwords) | |
461 != NGX_OK) | |
462 { | |
463 return 0; | |
464 } | |
465 } | |
466 | |
467 return 1; | |
468 } | |
469 | |
470 #endif | |
471 | |
472 | |
411 static ngx_int_t | 473 static ngx_int_t |
412 ngx_stream_ssl_static_variable(ngx_stream_session_t *s, | 474 ngx_stream_ssl_static_variable(ngx_stream_session_t *s, |
413 ngx_stream_variable_value_t *v, uintptr_t data) | 475 ngx_stream_variable_value_t *v, uintptr_t data) |
414 { | 476 { |
415 ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; | 477 ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; |
503 /* | 565 /* |
504 * set by ngx_pcalloc(): | 566 * set by ngx_pcalloc(): |
505 * | 567 * |
506 * scf->listen = 0; | 568 * scf->listen = 0; |
507 * scf->protocols = 0; | 569 * scf->protocols = 0; |
570 * scf->certificate_values = NULL; | |
508 * scf->dhparam = { 0, NULL }; | 571 * scf->dhparam = { 0, NULL }; |
509 * scf->ecdh_curve = { 0, NULL }; | 572 * scf->ecdh_curve = { 0, NULL }; |
510 * scf->client_certificate = { 0, NULL }; | 573 * scf->client_certificate = { 0, NULL }; |
511 * scf->trusted_certificate = { 0, NULL }; | 574 * scf->trusted_certificate = { 0, NULL }; |
512 * scf->crl = { 0, NULL }; | 575 * scf->crl = { 0, NULL }; |
617 } | 680 } |
618 | 681 |
619 cln->handler = ngx_ssl_cleanup_ctx; | 682 cln->handler = ngx_ssl_cleanup_ctx; |
620 cln->data = &conf->ssl; | 683 cln->data = &conf->ssl; |
621 | 684 |
622 if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, | 685 if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) { |
623 conf->certificate_keys, conf->passwords) | 686 return NGX_CONF_ERROR; |
624 != NGX_OK) | 687 } |
625 { | 688 |
626 return NGX_CONF_ERROR; | 689 if (conf->certificate_values) { |
690 | |
691 #ifdef SSL_R_CERT_CB_ERROR | |
692 | |
693 /* install callback to lookup certificates */ | |
694 | |
695 SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, NULL); | |
696 | |
697 #else | |
698 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
699 "variables in " | |
700 "\"ssl_certificate\" and \"ssl_certificate_key\" " | |
701 "directives are not supported on this platform"); | |
702 return NGX_CONF_ERROR; | |
703 #endif | |
704 | |
705 } else { | |
706 | |
707 /* configure certificates */ | |
708 | |
709 if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, | |
710 conf->certificate_keys, conf->passwords) | |
711 != NGX_OK) | |
712 { | |
713 return NGX_CONF_ERROR; | |
714 } | |
627 } | 715 } |
628 | 716 |
629 if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, | 717 if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, |
630 conf->prefer_server_ciphers) | 718 conf->prefer_server_ciphers) |
631 != NGX_OK) | 719 != NGX_OK) |
705 | 793 |
706 return NGX_CONF_OK; | 794 return NGX_CONF_OK; |
707 } | 795 } |
708 | 796 |
709 | 797 |
798 static ngx_int_t | |
799 ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, | |
800 ngx_stream_ssl_conf_t *conf) | |
801 { | |
802 ngx_str_t *cert, *key; | |
803 ngx_uint_t i, nelts; | |
804 ngx_stream_complex_value_t *cv; | |
805 ngx_stream_compile_complex_value_t ccv; | |
806 | |
807 cert = conf->certificates->elts; | |
808 key = conf->certificate_keys->elts; | |
809 nelts = conf->certificates->nelts; | |
810 | |
811 for (i = 0; i < nelts; i++) { | |
812 | |
813 if (ngx_stream_script_variables_count(&cert[i])) { | |
814 goto found; | |
815 } | |
816 | |
817 if (ngx_stream_script_variables_count(&key[i])) { | |
818 goto found; | |
819 } | |
820 } | |
821 | |
822 return NGX_OK; | |
823 | |
824 found: | |
825 | |
826 conf->certificate_values = ngx_array_create(cf->pool, nelts, | |
827 sizeof(ngx_stream_complex_value_t)); | |
828 if (conf->certificate_values == NULL) { | |
829 return NGX_ERROR; | |
830 } | |
831 | |
832 conf->certificate_key_values = ngx_array_create(cf->pool, nelts, | |
833 sizeof(ngx_stream_complex_value_t)); | |
834 if (conf->certificate_key_values == NULL) { | |
835 return NGX_ERROR; | |
836 } | |
837 | |
838 for (i = 0; i < nelts; i++) { | |
839 | |
840 cv = ngx_array_push(conf->certificate_values); | |
841 if (cv == NULL) { | |
842 return NGX_ERROR; | |
843 } | |
844 | |
845 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); | |
846 | |
847 ccv.cf = cf; | |
848 ccv.value = &cert[i]; | |
849 ccv.complex_value = cv; | |
850 ccv.zero = 1; | |
851 | |
852 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { | |
853 return NGX_ERROR; | |
854 } | |
855 | |
856 cv = ngx_array_push(conf->certificate_key_values); | |
857 if (cv == NULL) { | |
858 return NGX_ERROR; | |
859 } | |
860 | |
861 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); | |
862 | |
863 ccv.cf = cf; | |
864 ccv.value = &key[i]; | |
865 ccv.complex_value = cv; | |
866 ccv.zero = 1; | |
867 | |
868 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { | |
869 return NGX_ERROR; | |
870 } | |
871 } | |
872 | |
873 conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords); | |
874 if (conf->passwords == NULL) { | |
875 return NGX_ERROR; | |
876 } | |
877 | |
878 return NGX_OK; | |
879 } | |
880 | |
881 | |
710 static char * | 882 static char * |
711 ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 883 ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
712 { | 884 { |
713 ngx_stream_ssl_conf_t *scf = conf; | 885 ngx_stream_ssl_conf_t *scf = conf; |
714 | 886 |