Hi, This is the new version of 'Multiple server certificate support ' patches.
It relies on openssl to maintain a list of server certificates. Reviews and comments are welcome. Regards, Filipe da Silva Ingima --- # HG changeset patch # User Filipe da Silva <[email protected]> # Date 1429178261 -7200 # Thu Apr 16 11:57:41 2015 +0200 # Node ID d201e4afd59eaf79419836c1dcdec83e141d3f67 # Parent 8b7f062a3fe60f01d373db6dc87f715d3c4fd214 SSL: introduce support of new openssl 1.0.2 features. - Split 'ngx_ssl_certificate' in two parts to prepare 'Multiple SSL certificate' support. - introduce 'ngx_ssl_cert_stapling_index' - add new server certificate retrieval method. - disable ngx_ssl_certificate_index when openssl 1.0.2. - derivate ssl_session_id from all certificates. diff -r 8b7f062a3fe6 -r d201e4afd59e src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Thu Apr 16 12:17:41 2015 +0300 +++ b/src/event/ngx_event_openssl.c Thu Apr 16 11:57:41 2015 +0200 @@ -18,6 +18,10 @@ typedef struct { } ngx_openssl_conf_t; +static ngx_int_t ngx_ssl_server_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_str_t *cert); +static ngx_int_t ngx_ssl_private_key(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_str_t *key, ngx_array_t *passwords); static int ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata); static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); @@ -101,8 +105,11 @@ int ngx_ssl_connection_index; int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_session_ticket_keys_index; +#if OPENSSL_VERSION_NUMBER < 0x10002000L int ngx_ssl_certificate_index; +#endif int ngx_ssl_stapling_index; +int ngx_ssl_cert_stapling_index; ngx_int_t @@ -168,6 +175,7 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } +#if OPENSSL_VERSION_NUMBER < 0x10002000L ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_certificate_index == -1) { @@ -175,6 +183,7 @@ ngx_ssl_init(ngx_log_t *log) "SSL_CTX_get_ex_new_index() failed"); return NGX_ERROR; } +#endif ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); @@ -184,6 +193,14 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_cert_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_cert_stapling_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "X509_get_ex_new_index() failed"); + return NGX_ERROR; + } + return NGX_OK; } @@ -297,15 +314,49 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ } +X509* +ngx_ssl_get_server_certificate(ngx_ssl_t *ssl, ngx_flag_t first) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + int rc; + long op; + + op = first ? SSL_CERT_SET_FIRST : SSL_CERT_SET_NEXT; + rc = SSL_CTX_set_current_cert(ssl->ctx, op); + if (rc) + return (SSL_CTX_get0_certificate(ssl->ctx)); +#else + if (first) + return (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)); +#endif + return NULL; +} + + ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords) { + /* load server certificate */ + if (ngx_ssl_server_certificate(cf, ssl, cert) != NGX_OK) + { + return NGX_ERROR; + } + /* load private key */ + if (ngx_ssl_private_key(cf, ssl, key, passwords) != NGX_OK) + { + return NGX_ERROR; + } + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_server_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert) +{ BIO *bio; X509 *x509; u_long n; - ngx_str_t *pwd; - ngx_uint_t tries; if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { return NGX_ERROR; @@ -340,6 +391,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } +#if OPENSSL_VERSION_NUMBER < 0x10002000L if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { @@ -349,6 +401,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ BIO_free(bio); return NGX_ERROR; } +#endif X509_free(x509); @@ -376,10 +429,20 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } +#ifdef SSL_CTX_add0_chain_cert + /* OpenSSL >=1.0.2 allows multiple server certificates in a single + * SSL_CTX to each have a different chain + */ + if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_add0_chain_cert(\"%s\") failed", + cert->data); +#else if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_add_extra_chain_cert(\"%s\") failed", cert->data); +#endif X509_free(x509); BIO_free(bio); return NGX_ERROR; @@ -388,6 +451,17 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ BIO_free(bio); + return NGX_OK; +} + + +static ngx_int_t +ngx_ssl_private_key(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *key, + ngx_array_t *passwords) +{ + ngx_str_t *pwd; + ngx_uint_t tries; + if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) { #ifndef OPENSSL_NO_ENGINE @@ -2150,8 +2224,10 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss goto failed; } - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - + cert = ngx_ssl_get_server_certificate(ssl, NGX_SSL_FIRST_CERT); + while (cert) { + + /* TODO: fix loop indentation */ if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_digest() failed"); @@ -2164,6 +2240,10 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss goto failed; } + /* get next server certificate, if any */ + cert = ngx_ssl_get_server_certificate(ssl, NGX_SSL_NEXT_CERT); + } + list = SSL_CTX_get_client_CA_list(ssl->ctx); if (list != NULL) { diff -r 8b7f062a3fe6 -r d201e4afd59e src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Thu Apr 16 12:17:41 2015 +0300 +++ b/src/event/ngx_event_openssl.h Thu Apr 16 11:57:41 2015 +0200 @@ -189,6 +189,10 @@ ngx_int_t ngx_ssl_get_fingerprint(ngx_co ngx_str_t *s); ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); + +#define NGX_SSL_FIRST_CERT 1 +#define NGX_SSL_NEXT_CERT 0 +X509* ngx_ssl_get_server_certificate(ngx_ssl_t *ssl, ngx_flag_t first); ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); @@ -210,6 +214,7 @@ extern int ngx_ssl_session_cache_index; extern int ngx_ssl_session_ticket_keys_index; extern int ngx_ssl_certificate_index; extern int ngx_ssl_stapling_index; +extern int ngx_ssl_cert_stapling_index; #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ _______________________________________________ nginx-devel mailing list [email protected] http://mailman.nginx.org/mailman/listinfo/nginx-devel
