1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/*
* Copyright (C) Maxim Dounin
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB
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;
}
#else
ngx_int_t
ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
{
ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
"\"ssl_stapling\" ignored, not supported");
return NGX_OK;
}
#endif
|