[PATCH 2 of 4] OCSP stapling: ssl_stapling_file support
Maxim Dounin
mdounin at mdounin.ru
Wed Sep 5 11:14:42 UTC 2012
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1346840511 -14400
# Node ID 9fa7f13e92b0287cbef687cc28a6a282a6d3f4c8
# Parent ca180646a706288271f411ed65f40ae5a1c26211
OCSP stapling: ssl_stapling_file support.
Very basic version without any OCSP responder query code, assuming valid
DER-encoded OCSP response is present in a ssl_stapling_file configured.
Such file might be produced with openssl like this:
openssl ocsp -issuer root.crt -cert domain.crt -respout domain.staple \
-url http://ocsp.example.com
diff --git a/auto/sources b/auto/sources
--- a/auto/sources
+++ b/auto/sources
@@ -77,7 +77,8 @@ REGEX_SRCS=src/core/ngx_regex.c
OPENSSL_MODULE=ngx_openssl_module
OPENSSL_DEPS=src/event/ngx_event_openssl.h
-OPENSSL_SRCS=src/event/ngx_event_openssl.c
+OPENSSL_SRCS="src/event/ngx_event_openssl.c \
+ src/event/ngx_event_openssl_stapling.c"
EVENT_MODULES="ngx_events_module ngx_event_core_module"
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
@@ -17,6 +17,7 @@
#include <openssl/conf.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
+#include <openssl/ocsp.h>
#define NGX_SSL_NAME "OpenSSL"
@@ -104,6 +105,7 @@ ngx_int_t ngx_ssl_client_certificate(ngx
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);
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);
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c
new file mode 100644
--- /dev/null
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -0,0 +1,121 @@
+
+/*
+ * Copyright (C) Maxim Dounin
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
+ void *data);
+
+
+ngx_int_t
+ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
+{
+ BIO *bio;
+ int len;
+ u_char *p, *buf;
+ ngx_str_t *staple;
+ OCSP_RESPONSE *response;
+
+ if (file->len == 0) {
+ return NGX_OK;
+ }
+
+ if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ bio = BIO_new_file((char *) file->data, "r");
+ if (bio == NULL) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "BIO_new_file(\"%s\") failed", file->data);
+ return NGX_ERROR;
+ }
+
+ response = d2i_OCSP_RESPONSE_bio(bio, NULL);
+ if (response == NULL) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
+ BIO_free(bio);
+ return NGX_ERROR;
+ }
+
+ len = i2d_OCSP_RESPONSE(response, NULL);
+ if (len <= 0) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
+ goto failed;
+ }
+
+ buf = ngx_pnalloc(cf->pool, len);
+ if (buf == NULL) {
+ goto failed;
+ }
+
+ p = buf;
+ len = i2d_OCSP_RESPONSE(response, &p);
+ if (len <= 0) {
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
+ goto failed;
+ }
+
+ OCSP_RESPONSE_free(response);
+ BIO_free(bio);
+
+ staple = ngx_palloc(cf->pool, sizeof(ngx_str_t));
+ if (staple == NULL) {
+ return NGX_ERROR;
+ }
+
+ staple->data = buf;
+ staple->len = len;
+
+ SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
+ SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple);
+
+ return NGX_OK;
+
+failed:
+
+ OCSP_RESPONSE_free(response);
+ BIO_free(bio);
+
+ return NGX_ERROR;
+}
+
+
+static int
+ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
+{
+ u_char *p;
+ ngx_str_t *staple;
+ ngx_connection_t *c;
+
+ c = ngx_ssl_get_connection(ssl_conn);
+
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "SSL certificate status callback");
+
+ staple = data;
+
+ /* we have to copy the staple as OpenSSL will free it by itself */
+
+ p = OPENSSL_malloc(staple->len);
+ if (p == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
+
+ ngx_memcpy(p, staple->data, staple->len);
+
+ SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->len);
+
+ return SSL_TLSEXT_ERR_OK;
+}
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -159,6 +159,20 @@ static ngx_command_t ngx_http_ssl_comma
offsetof(ngx_http_ssl_srv_conf_t, crl),
NULL },
+ { ngx_string("ssl_stapling"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_ssl_srv_conf_t, stapling),
+ NULL },
+
+ { ngx_string("ssl_stapling_file"),
+ 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_file),
+ NULL },
+
ngx_null_command
};
@@ -336,6 +350,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t
* sscf->crl = { 0, NULL };
* sscf->ciphers = { 0, NULL };
* sscf->shm_zone = NULL;
+ * sscf->stapling_file = { 0, NULL };
*/
sscf->enable = NGX_CONF_UNSET;
@@ -344,6 +359,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t
sscf->verify_depth = NGX_CONF_UNSET_UINT;
sscf->builtin_session_cache = NGX_CONF_UNSET;
sscf->session_timeout = NGX_CONF_UNSET;
+ sscf->stapling = NGX_CONF_UNSET;
return sscf;
}
@@ -397,6 +413,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
+ ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
+ ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
conf->ssl.log = cf->log;
@@ -533,6 +551,12 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
return NGX_CONF_ERROR;
}
+ if (conf->stapling
+ && ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -42,6 +42,9 @@ typedef struct {
ngx_shm_zone_t *shm_zone;
+ ngx_flag_t stapling;
+ ngx_str_t stapling_file;
+
u_char *file;
ngx_uint_t line;
} ngx_http_ssl_srv_conf_t;
More information about the nginx-devel
mailing list