[nginx] SSL: made it possible to iterate though all certificates.
Maxim Dounin
mdounin at mdounin.ru
Thu May 19 17:30:22 UTC 2016
details: http://hg.nginx.org/nginx/rev/8a34e92d8ab5
branches:
changeset: 6548:8a34e92d8ab5
user: Maxim Dounin <mdounin at mdounin.ru>
date: Thu May 19 14:46:32 2016 +0300
description:
SSL: made it possible to iterate though all certificates.
A pointer to a previously configured certificate now stored in a certificate.
This makes it possible to iterate though all certificates configured in
the SSL context. This is now used to configure OCSP stapling for all
certificates, and in ngx_ssl_session_id_context().
As SSL_CTX_use_certificate() frees previously loaded certificate of the same
type, and we have no way to find out if it's the case, X509_free() calls
are now posponed till ngx_ssl_cleanup_ctx().
Note that in OpenSSL 1.0.2+ this can be done without storing things in exdata
using the SSL_CTX_set_current_cert() and SSL_CTX_get0_certificate() functions.
These are not yet available in all supported versions though, so it's easier
to continue to use exdata for now.
diffstat:
src/event/ngx_event_openssl.c | 65 ++++++++++++++++++++++++++-------
src/event/ngx_event_openssl.h | 1 +
src/event/ngx_event_openssl_stapling.c | 26 ++++++++-----
3 files changed, 67 insertions(+), 25 deletions(-)
diffs (179 lines):
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -105,6 +105,7 @@ int ngx_ssl_server_conf_index;
int ngx_ssl_session_cache_index;
int ngx_ssl_session_ticket_keys_index;
int ngx_ssl_certificate_index;
+int ngx_ssl_next_certificate_index;
int ngx_ssl_stapling_index;
@@ -187,6 +188,13 @@ ngx_ssl_init(ngx_log_t *log)
return NGX_ERROR;
}
+ ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
+ NULL);
+ if (ngx_ssl_next_certificate_index == -1) {
+ ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
+ return NGX_ERROR;
+ }
+
ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL);
if (ngx_ssl_stapling_index == -1) {
@@ -214,6 +222,12 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_
return NGX_ERROR;
}
+ if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "SSL_CTX_set_ex_data() failed");
+ return NGX_ERROR;
+ }
+
ssl->buffer_size = NGX_SSL_BUFSIZE;
/* client side options */
@@ -350,6 +364,16 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_
return NGX_ERROR;
}
+ if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index,
+ SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index))
+ == 0)
+ {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
+ X509_free(x509);
+ BIO_free(bio);
+ return NGX_ERROR;
+ }
+
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
== 0)
{
@@ -360,8 +384,6 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_
return NGX_ERROR;
}
- X509_free(x509);
-
/* read rest of the chain */
for ( ;; ) {
@@ -2163,7 +2185,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss
/*
* Session ID context is set based on the string provided,
- * the server certificate, and the client CA list.
+ * the server certificates, and the client CA list.
*/
md = EVP_MD_CTX_create();
@@ -2183,18 +2205,21 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss
goto failed;
}
- cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
-
- if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
- ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
- "X509_digest() failed");
- goto failed;
- }
-
- if (EVP_DigestUpdate(md, buf, len) == 0) {
- ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
- "EVP_DigestUpdate() failed");
- goto failed;
+ for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
+ cert;
+ cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
+ {
+ if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "X509_digest() failed");
+ goto failed;
+ }
+
+ if (EVP_DigestUpdate(md, buf, len) == 0) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "EVP_DigestUpdate() failed");
+ goto failed;
+ }
}
list = SSL_CTX_get_client_CA_list(ssl->ctx);
@@ -2950,6 +2975,16 @@ ngx_ssl_cleanup_ctx(void *data)
{
ngx_ssl_t *ssl = data;
+ X509 *cert, *next;
+
+ cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
+
+ while (cert) {
+ next = X509_get_ex_data(cert, ngx_ssl_next_certificate_index);
+ X509_free(cert);
+ cert = next;
+ }
+
SSL_CTX_free(ssl->ctx);
}
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -227,6 +227,7 @@ extern int ngx_ssl_server_conf_index;
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_next_certificate_index;
extern int ngx_ssl_stapling_index;
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c
--- a/src/event/ngx_event_openssl_stapling.c
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -126,12 +126,15 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl
{
X509 *cert;
- cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
-
- if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
- != NGX_OK)
+ for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
+ cert;
+ cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
{
- return NGX_ERROR;
+ if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
}
SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
@@ -455,11 +458,14 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf
X509 *cert;
ngx_ssl_stapling_t *staple;
- cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
- staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
-
- staple->resolver = resolver;
- staple->resolver_timeout = resolver_timeout;
+ for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
+ cert;
+ cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
+ {
+ staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
+ staple->resolver = resolver;
+ staple->resolver_timeout = resolver_timeout;
+ }
return NGX_OK;
}
More information about the nginx-devel
mailing list