Mercurial > hg > nginx
diff src/event/ngx_event_openssl.c @ 4875:386a06a22c40
OCSP stapling: loading OCSP responses.
This includes the ssl_stapling_responder directive (defaults to OCSP
responder set in certificate's AIA extension).
OCSP response for a given certificate is requested once we get at least
one connection with certificate_status extension in ClientHello, and
certificate status won't be sent in the connection in question. This due
to limitations in the OpenSSL API (certificate status callback is blocking).
Note: SSL_CTX_use_certificate_chain_file() was reimplemented as it doesn't
allow to access the certificate loaded via SSL_CTX.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 01 Oct 2012 12:47:55 +0000 |
parents | 7c3cca603438 |
children | f2e450929c1f |
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c Mon Oct 01 12:42:43 2012 +0000 +++ b/src/event/ngx_event_openssl.c Mon Oct 01 12:47:55 2012 +0000 @@ -82,6 +82,8 @@ int ngx_ssl_connection_index; int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; +int ngx_ssl_certificate_index; +int ngx_ssl_stapling_index; ngx_int_t @@ -137,6 +139,22 @@ return NGX_ERROR; } + ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_certificate_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + + ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_stapling_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + return NGX_OK; } @@ -218,19 +236,89 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key) { + BIO *bio; + X509 *x509; + u_long n; + if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { return NGX_ERROR; } - if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data) + /* + * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't + * allow to access certificate later from SSL_CTX, so we reimplement + * it here + */ + + bio = BIO_new_file((char *) cert->data, "r"); + if (bio == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "BIO_new_file(\"%s\") failed", cert->data); + return NGX_ERROR; + } + + x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); + if (x509 == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data); + BIO_free(bio); + return NGX_ERROR; + } + + if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_certificate(\"%s\") failed", cert->data); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_use_certificate_chain_file(\"%s\") failed", - cert->data); + "SSL_CTX_set_ex_data() failed"); return NGX_ERROR; } + X509_free(x509); + + /* read rest of the chain */ + + for ( ;; ) { + + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (x509 == NULL) { + n = ERR_peek_last_error(); + + if (ERR_GET_LIB(n) == ERR_LIB_PEM + && ERR_GET_REASON(n) == PEM_R_NO_START_LINE) + { + /* end of file */ + ERR_clear_error(); + break; + } + + /* some real error */ + + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "PEM_read_bio_X509(\"%s\") failed", cert->data); + BIO_free(bio); + return NGX_ERROR; + } + + 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); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + } + + BIO_free(bio); + if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { return NGX_ERROR; }