mirror of
https://github.com/nginx/nginx.git
synced 2024-12-20 14:13:33 -06:00
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.
This commit is contained in:
parent
f7ec295fb4
commit
74ad4494a6
@ -69,12 +69,12 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
|
||||
#include <ngx_slab.h>
|
||||
#include <ngx_inet.h>
|
||||
#include <ngx_cycle.h>
|
||||
#include <ngx_resolver.h>
|
||||
#if (NGX_OPENSSL)
|
||||
#include <ngx_event_openssl.h>
|
||||
#endif
|
||||
#include <ngx_process_cycle.h>
|
||||
#include <ngx_conf_file.h>
|
||||
#include <ngx_resolver.h>
|
||||
#include <ngx_open_file_cache.h>
|
||||
#include <ngx_os.h>
|
||||
#include <ngx_connection.h>
|
||||
|
@ -82,6 +82,8 @@ ngx_module_t ngx_openssl_module = {
|
||||
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 @@ ngx_ssl_init(ngx_log_t *log)
|
||||
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_int_t
|
||||
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;
|
||||
}
|
||||
|
@ -105,7 +105,10 @@ ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
ngx_str_t *cert, ngx_int_t depth);
|
||||
ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl);
|
||||
ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
|
||||
ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
ngx_str_t *responder, ngx_str_t *file);
|
||||
ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
|
||||
RSA *ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length);
|
||||
ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
|
||||
ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
|
||||
@ -161,6 +164,8 @@ void ngx_ssl_cleanup_ctx(void *data);
|
||||
extern int ngx_ssl_connection_index;
|
||||
extern int ngx_ssl_server_conf_index;
|
||||
extern int ngx_ssl_session_cache_index;
|
||||
extern int ngx_ssl_certificate_index;
|
||||
extern int ngx_ssl_stapling_index;
|
||||
|
||||
|
||||
#endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,8 @@ static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
|
||||
|
||||
|
||||
static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
|
||||
{ ngx_string("SSLv2"), NGX_SSL_SSLv2 },
|
||||
@ -173,13 +175,20 @@ static ngx_command_t ngx_http_ssl_commands[] = {
|
||||
offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("ssl_stapling_responder"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_HTTP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_http_ssl_srv_conf_t, stapling_responder),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
static ngx_http_module_t ngx_http_ssl_module_ctx = {
|
||||
ngx_http_ssl_add_variables, /* preconfiguration */
|
||||
NULL, /* postconfiguration */
|
||||
ngx_http_ssl_init, /* postconfiguration */
|
||||
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
@ -351,6 +360,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
|
||||
* sscf->ciphers = { 0, NULL };
|
||||
* sscf->shm_zone = NULL;
|
||||
* sscf->stapling_file = { 0, NULL };
|
||||
* sscf->stapling_responder = { 0, NULL };
|
||||
*/
|
||||
|
||||
sscf->enable = NGX_CONF_UNSET;
|
||||
@ -415,6 +425,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
|
||||
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
|
||||
ngx_conf_merge_str_value(conf->stapling_responder,
|
||||
prev->stapling_responder, "");
|
||||
|
||||
conf->ssl.log = cf->log;
|
||||
|
||||
@ -551,10 +563,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (conf->stapling
|
||||
&& ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file) != NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
if (conf->stapling) {
|
||||
|
||||
if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_responder,
|
||||
&conf->stapling_file)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
@ -692,3 +709,37 @@ invalid:
|
||||
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_ssl_init(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_uint_t s;
|
||||
ngx_http_ssl_srv_conf_t *sscf;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
ngx_http_core_srv_conf_t **cscfp;
|
||||
ngx_http_core_main_conf_t *cmcf;
|
||||
|
||||
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
|
||||
cscfp = cmcf->servers.elts;
|
||||
|
||||
for (s = 0; s < cmcf->servers.nelts; s++) {
|
||||
|
||||
sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
|
||||
|
||||
if (!sscf->stapling) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
|
||||
|
||||
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
|
||||
clcf->resolver_timeout)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ typedef struct {
|
||||
|
||||
ngx_flag_t stapling;
|
||||
ngx_str_t stapling_file;
|
||||
ngx_str_t stapling_responder;
|
||||
|
||||
u_char *file;
|
||||
ngx_uint_t line;
|
||||
|
Loading…
Reference in New Issue
Block a user