1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Maxim Dounin
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev#include <ngx_event_connect.h>
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyev#if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev
17e18a033bSKonstantin Ananyevtypedef struct {
18e18a033bSKonstantin Ananyev    ngx_str_t                    staple;
19e18a033bSKonstantin Ananyev    ngx_msec_t                   timeout;
20e18a033bSKonstantin Ananyev
21e18a033bSKonstantin Ananyev    ngx_resolver_t              *resolver;
22e18a033bSKonstantin Ananyev    ngx_msec_t                   resolver_timeout;
23e18a033bSKonstantin Ananyev
24e18a033bSKonstantin Ananyev    ngx_addr_t                  *addrs;
25e18a033bSKonstantin Ananyev    ngx_str_t                    host;
26e18a033bSKonstantin Ananyev    ngx_str_t                    uri;
27e18a033bSKonstantin Ananyev    in_port_t                    port;
28e18a033bSKonstantin Ananyev
29e18a033bSKonstantin Ananyev    SSL_CTX                     *ssl_ctx;
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyev    X509                        *cert;
32e18a033bSKonstantin Ananyev    X509                        *issuer;
33e18a033bSKonstantin Ananyev
34e18a033bSKonstantin Ananyev    u_char                      *name;
35e18a033bSKonstantin Ananyev
36e18a033bSKonstantin Ananyev    time_t                       valid;
37e18a033bSKonstantin Ananyev    time_t                       refresh;
38e18a033bSKonstantin Ananyev
39e18a033bSKonstantin Ananyev    unsigned                     verify:1;
40e18a033bSKonstantin Ananyev    unsigned                     loading:1;
41e18a033bSKonstantin Ananyev} ngx_ssl_stapling_t;
42e18a033bSKonstantin Ananyev
43e18a033bSKonstantin Ananyev
44e18a033bSKonstantin Ananyevtypedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;
45e18a033bSKonstantin Ananyev
46e18a033bSKonstantin Ananyevstruct ngx_ssl_ocsp_ctx_s {
47e18a033bSKonstantin Ananyev    X509                        *cert;
48e18a033bSKonstantin Ananyev    X509                        *issuer;
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyev    u_char                      *name;
51e18a033bSKonstantin Ananyev
52e18a033bSKonstantin Ananyev    ngx_uint_t                   naddrs;
53e18a033bSKonstantin Ananyev
54e18a033bSKonstantin Ananyev    ngx_addr_t                  *addrs;
55e18a033bSKonstantin Ananyev    ngx_str_t                    host;
56e18a033bSKonstantin Ananyev    ngx_str_t                    uri;
57e18a033bSKonstantin Ananyev    in_port_t                    port;
58e18a033bSKonstantin Ananyev
59e18a033bSKonstantin Ananyev    ngx_resolver_t              *resolver;
60e18a033bSKonstantin Ananyev    ngx_msec_t                   resolver_timeout;
61e18a033bSKonstantin Ananyev
62e18a033bSKonstantin Ananyev    ngx_msec_t                   timeout;
63e18a033bSKonstantin Ananyev
64e18a033bSKonstantin Ananyev    void                       (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
65e18a033bSKonstantin Ananyev    void                        *data;
66e18a033bSKonstantin Ananyev
67e18a033bSKonstantin Ananyev    ngx_buf_t                   *request;
68e18a033bSKonstantin Ananyev    ngx_buf_t                   *response;
69e18a033bSKonstantin Ananyev    ngx_peer_connection_t        peer;
70e18a033bSKonstantin Ananyev
71e18a033bSKonstantin Ananyev    ngx_int_t                  (*process)(ngx_ssl_ocsp_ctx_t *ctx);
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyev    ngx_uint_t                   state;
74e18a033bSKonstantin Ananyev
75e18a033bSKonstantin Ananyev    ngx_uint_t                   code;
76e18a033bSKonstantin Ananyev    ngx_uint_t                   count;
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev    ngx_uint_t                   done;
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyev    u_char                      *header_name_start;
81e18a033bSKonstantin Ananyev    u_char                      *header_name_end;
82e18a033bSKonstantin Ananyev    u_char                      *header_start;
83e18a033bSKonstantin Ananyev    u_char                      *header_end;
84e18a033bSKonstantin Ananyev
85e18a033bSKonstantin Ananyev    ngx_pool_t                  *pool;
86e18a033bSKonstantin Ananyev    ngx_log_t                   *log;
87e18a033bSKonstantin Ananyev};
88e18a033bSKonstantin Ananyev
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
91e18a033bSKonstantin Ananyev    X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
92e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
93e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t *staple, ngx_str_t *file);
94e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
95e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t *staple);
96e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
97e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t *staple, ngx_str_t *responder);
98e18a033bSKonstantin Ananyev
99e18a033bSKonstantin Ananyevstatic int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
100e18a033bSKonstantin Ananyev    void *data);
101e18a033bSKonstantin Ananyevstatic void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
102e18a033bSKonstantin Ananyevstatic void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
103e18a033bSKonstantin Ananyev
104e18a033bSKonstantin Ananyevstatic time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
105e18a033bSKonstantin Ananyev
106e18a033bSKonstantin Ananyevstatic void ngx_ssl_stapling_cleanup(void *data);
107e18a033bSKonstantin Ananyev
108e18a033bSKonstantin Ananyevstatic ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
109e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
110e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
111e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
112e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
113e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
114e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
115e18a033bSKonstantin Ananyevstatic void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);
116e18a033bSKonstantin Ananyev
117e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
118e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
119e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
120e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
121e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
122e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
123e18a033bSKonstantin Ananyev
124e18a033bSKonstantin Ananyevstatic u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
125e18a033bSKonstantin Ananyev
126e18a033bSKonstantin Ananyev
127e18a033bSKonstantin Ananyevngx_int_t
128e18a033bSKonstantin Ananyevngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
129e18a033bSKonstantin Ananyev    ngx_str_t *responder, ngx_uint_t verify)
130e18a033bSKonstantin Ananyev{
131e18a033bSKonstantin Ananyev    X509  *cert;
132e18a033bSKonstantin Ananyev
133e18a033bSKonstantin Ananyev    for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
134e18a033bSKonstantin Ananyev         cert;
135e18a033bSKonstantin Ananyev         cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
136e18a033bSKonstantin Ananyev    {
137e18a033bSKonstantin Ananyev        if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
138e18a033bSKonstantin Ananyev            != NGX_OK)
139e18a033bSKonstantin Ananyev        {
140e18a033bSKonstantin Ananyev            return NGX_ERROR;
141e18a033bSKonstantin Ananyev        }
142e18a033bSKonstantin Ananyev    }
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev    SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
145e18a033bSKonstantin Ananyev
146e18a033bSKonstantin Ananyev    return NGX_OK;
147e18a033bSKonstantin Ananyev}
148e18a033bSKonstantin Ananyev
149e18a033bSKonstantin Ananyev
150e18a033bSKonstantin Ananyevstatic ngx_int_t
151e18a033bSKonstantin Ananyevngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
152e18a033bSKonstantin Ananyev    ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify)
153e18a033bSKonstantin Ananyev{
154e18a033bSKonstantin Ananyev    ngx_int_t            rc;
155e18a033bSKonstantin Ananyev    ngx_pool_cleanup_t  *cln;
156e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t  *staple;
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev    staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
159e18a033bSKonstantin Ananyev    if (staple == NULL) {
160e18a033bSKonstantin Ananyev        return NGX_ERROR;
161e18a033bSKonstantin Ananyev    }
162e18a033bSKonstantin Ananyev
163e18a033bSKonstantin Ananyev    cln = ngx_pool_cleanup_add(cf->pool, 0);
164e18a033bSKonstantin Ananyev    if (cln == NULL) {
165e18a033bSKonstantin Ananyev        return NGX_ERROR;
166e18a033bSKonstantin Ananyev    }
167e18a033bSKonstantin Ananyev
168e18a033bSKonstantin Ananyev    cln->handler = ngx_ssl_stapling_cleanup;
169e18a033bSKonstantin Ananyev    cln->data = staple;
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev    if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) {
172e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
173e18a033bSKonstantin Ananyev        return NGX_ERROR;
174e18a033bSKonstantin Ananyev    }
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev    staple->ssl_ctx = ssl->ctx;
177e18a033bSKonstantin Ananyev    staple->timeout = 60000;
178e18a033bSKonstantin Ananyev    staple->verify = verify;
179e18a033bSKonstantin Ananyev    staple->cert = cert;
180e18a033bSKonstantin Ananyev    staple->name = X509_get_ex_data(staple->cert,
181e18a033bSKonstantin Ananyev                                    ngx_ssl_certificate_name_index);
182e18a033bSKonstantin Ananyev
183e18a033bSKonstantin Ananyev    if (file->len) {
184e18a033bSKonstantin Ananyev        /* use OCSP response from the file */
185e18a033bSKonstantin Ananyev
186e18a033bSKonstantin Ananyev        if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) {
187e18a033bSKonstantin Ananyev            return NGX_ERROR;
188e18a033bSKonstantin Ananyev        }
189e18a033bSKonstantin Ananyev
190e18a033bSKonstantin Ananyev        return NGX_OK;
191e18a033bSKonstantin Ananyev    }
192e18a033bSKonstantin Ananyev
193e18a033bSKonstantin Ananyev    rc = ngx_ssl_stapling_issuer(cf, ssl, staple);
194e18a033bSKonstantin Ananyev
195e18a033bSKonstantin Ananyev    if (rc == NGX_DECLINED) {
196e18a033bSKonstantin Ananyev        return NGX_OK;
197e18a033bSKonstantin Ananyev    }
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyev    if (rc != NGX_OK) {
200e18a033bSKonstantin Ananyev        return NGX_ERROR;
201e18a033bSKonstantin Ananyev    }
202e18a033bSKonstantin Ananyev
203e18a033bSKonstantin Ananyev    rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder);
204e18a033bSKonstantin Ananyev
205e18a033bSKonstantin Ananyev    if (rc == NGX_DECLINED) {
206e18a033bSKonstantin Ananyev        return NGX_OK;
207e18a033bSKonstantin Ananyev    }
208e18a033bSKonstantin Ananyev
209e18a033bSKonstantin Ananyev    if (rc != NGX_OK) {
210e18a033bSKonstantin Ananyev        return NGX_ERROR;
211e18a033bSKonstantin Ananyev    }
212e18a033bSKonstantin Ananyev
213e18a033bSKonstantin Ananyev    return NGX_OK;
214e18a033bSKonstantin Ananyev}
215e18a033bSKonstantin Ananyev
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyevstatic ngx_int_t
218e18a033bSKonstantin Ananyevngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
219e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t *staple, ngx_str_t *file)
220e18a033bSKonstantin Ananyev{
221e18a033bSKonstantin Ananyev    BIO            *bio;
222e18a033bSKonstantin Ananyev    int             len;
223e18a033bSKonstantin Ananyev    u_char         *p, *buf;
224e18a033bSKonstantin Ananyev    OCSP_RESPONSE  *response;
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev    if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
227e18a033bSKonstantin Ananyev        return NGX_ERROR;
228e18a033bSKonstantin Ananyev    }
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev    bio = BIO_new_file((char *) file->data, "r");
231e18a033bSKonstantin Ananyev    if (bio == NULL) {
232e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
233e18a033bSKonstantin Ananyev                      "BIO_new_file(\"%s\") failed", file->data);
234e18a033bSKonstantin Ananyev        return NGX_ERROR;
235e18a033bSKonstantin Ananyev    }
236e18a033bSKonstantin Ananyev
237e18a033bSKonstantin Ananyev    response = d2i_OCSP_RESPONSE_bio(bio, NULL);
238e18a033bSKonstantin Ananyev    if (response == NULL) {
239e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
240e18a033bSKonstantin Ananyev                      "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
241e18a033bSKonstantin Ananyev        BIO_free(bio);
242e18a033bSKonstantin Ananyev        return NGX_ERROR;
243e18a033bSKonstantin Ananyev    }
244e18a033bSKonstantin Ananyev
245e18a033bSKonstantin Ananyev    len = i2d_OCSP_RESPONSE(response, NULL);
246e18a033bSKonstantin Ananyev    if (len <= 0) {
247e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
248e18a033bSKonstantin Ananyev                      "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
249e18a033bSKonstantin Ananyev        goto failed;
250e18a033bSKonstantin Ananyev    }
251e18a033bSKonstantin Ananyev
252e18a033bSKonstantin Ananyev    buf = ngx_alloc(len, ssl->log);
253e18a033bSKonstantin Ananyev    if (buf == NULL) {
254e18a033bSKonstantin Ananyev        goto failed;
255e18a033bSKonstantin Ananyev    }
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev    p = buf;
258e18a033bSKonstantin Ananyev    len = i2d_OCSP_RESPONSE(response, &p);
259e18a033bSKonstantin Ananyev    if (len <= 0) {
260e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
261e18a033bSKonstantin Ananyev                      "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
262e18a033bSKonstantin Ananyev        ngx_free(buf);
263e18a033bSKonstantin Ananyev        goto failed;
264e18a033bSKonstantin Ananyev    }
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev    OCSP_RESPONSE_free(response);
267e18a033bSKonstantin Ananyev    BIO_free(bio);
268e18a033bSKonstantin Ananyev
269e18a033bSKonstantin Ananyev    staple->staple.data = buf;
270e18a033bSKonstantin Ananyev    staple->staple.len = len;
271e18a033bSKonstantin Ananyev    staple->valid = NGX_MAX_TIME_T_VALUE;
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev    return NGX_OK;
274e18a033bSKonstantin Ananyev
275e18a033bSKonstantin Ananyevfailed:
276e18a033bSKonstantin Ananyev
277e18a033bSKonstantin Ananyev    OCSP_RESPONSE_free(response);
278e18a033bSKonstantin Ananyev    BIO_free(bio);
279e18a033bSKonstantin Ananyev
280e18a033bSKonstantin Ananyev    return NGX_ERROR;
281e18a033bSKonstantin Ananyev}
282e18a033bSKonstantin Ananyev
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyevstatic ngx_int_t
285e18a033bSKonstantin Ananyevngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
286e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t *staple)
287e18a033bSKonstantin Ananyev{
288e18a033bSKonstantin Ananyev    int              i, n, rc;
289e18a033bSKonstantin Ananyev    X509            *cert, *issuer;
290e18a033bSKonstantin Ananyev    X509_STORE      *store;
291e18a033bSKonstantin Ananyev    X509_STORE_CTX  *store_ctx;
292e18a033bSKonstantin Ananyev    STACK_OF(X509)  *chain;
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev    cert = staple->cert;
295e18a033bSKonstantin Ananyev
296e18a033bSKonstantin Ananyev#ifdef SSL_CTRL_SELECT_CURRENT_CERT
297e18a033bSKonstantin Ananyev    /* OpenSSL 1.0.2+ */
298e18a033bSKonstantin Ananyev    SSL_CTX_select_current_cert(ssl->ctx, cert);
299e18a033bSKonstantin Ananyev#endif
300e18a033bSKonstantin Ananyev
301e18a033bSKonstantin Ananyev#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
302e18a033bSKonstantin Ananyev    /* OpenSSL 1.0.1+ */
303e18a033bSKonstantin Ananyev    SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
304e18a033bSKonstantin Ananyev#else
305e18a033bSKonstantin Ananyev    chain = ssl->ctx->extra_certs;
306e18a033bSKonstantin Ananyev#endif
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyev    n = sk_X509_num(chain);
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
311e18a033bSKonstantin Ananyev                   "SSL get issuer: %d extra certs", n);
312e18a033bSKonstantin Ananyev
313e18a033bSKonstantin Ananyev    for (i = 0; i < n; i++) {
314e18a033bSKonstantin Ananyev        issuer = sk_X509_value(chain, i);
315e18a033bSKonstantin Ananyev        if (X509_check_issued(issuer, cert) == X509_V_OK) {
316e18a033bSKonstantin Ananyev#if OPENSSL_VERSION_NUMBER >= 0x10100001L
317e18a033bSKonstantin Ananyev            X509_up_ref(issuer);
318e18a033bSKonstantin Ananyev#else
319e18a033bSKonstantin Ananyev            CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
320e18a033bSKonstantin Ananyev#endif
321e18a033bSKonstantin Ananyev
322e18a033bSKonstantin Ananyev            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
323e18a033bSKonstantin Ananyev                           "SSL get issuer: found %p in extra certs", issuer);
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev            staple->issuer = issuer;
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev            return NGX_OK;
328e18a033bSKonstantin Ananyev        }
329e18a033bSKonstantin Ananyev    }
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev    store = SSL_CTX_get_cert_store(ssl->ctx);
332e18a033bSKonstantin Ananyev    if (store == NULL) {
333e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
334e18a033bSKonstantin Ananyev                      "SSL_CTX_get_cert_store() failed");
335e18a033bSKonstantin Ananyev        return NGX_ERROR;
336e18a033bSKonstantin Ananyev    }
337e18a033bSKonstantin Ananyev
338e18a033bSKonstantin Ananyev    store_ctx = X509_STORE_CTX_new();
339e18a033bSKonstantin Ananyev    if (store_ctx == NULL) {
340e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
341e18a033bSKonstantin Ananyev                      "X509_STORE_CTX_new() failed");
342e18a033bSKonstantin Ananyev        return NGX_ERROR;
343e18a033bSKonstantin Ananyev    }
344e18a033bSKonstantin Ananyev
345e18a033bSKonstantin Ananyev    if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
346e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
347e18a033bSKonstantin Ananyev                      "X509_STORE_CTX_init() failed");
348e18a033bSKonstantin Ananyev        X509_STORE_CTX_free(store_ctx);
349e18a033bSKonstantin Ananyev        return NGX_ERROR;
350e18a033bSKonstantin Ananyev    }
351e18a033bSKonstantin Ananyev
352e18a033bSKonstantin Ananyev    rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
353e18a033bSKonstantin Ananyev
354e18a033bSKonstantin Ananyev    if (rc == -1) {
355e18a033bSKonstantin Ananyev        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
356e18a033bSKonstantin Ananyev                      "X509_STORE_CTX_get1_issuer() failed");
357e18a033bSKonstantin Ananyev        X509_STORE_CTX_free(store_ctx);
358e18a033bSKonstantin Ananyev        return NGX_ERROR;
359e18a033bSKonstantin Ananyev    }
360e18a033bSKonstantin Ananyev
361e18a033bSKonstantin Ananyev    if (rc == 0) {
362e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
363e18a033bSKonstantin Ananyev                      "\"ssl_stapling\" ignored, "
364e18a033bSKonstantin Ananyev                      "issuer certificate not found for certificate \"%s\"",
365e18a033bSKonstantin Ananyev                      staple->name);
366e18a033bSKonstantin Ananyev        X509_STORE_CTX_free(store_ctx);
367e18a033bSKonstantin Ananyev        return NGX_DECLINED;
368e18a033bSKonstantin Ananyev    }
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev    X509_STORE_CTX_free(store_ctx);
371e18a033bSKonstantin Ananyev
372e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
373e18a033bSKonstantin Ananyev                   "SSL get issuer: found %p in cert store", issuer);
374e18a033bSKonstantin Ananyev
375e18a033bSKonstantin Ananyev    staple->issuer = issuer;
376e18a033bSKonstantin Ananyev
377e18a033bSKonstantin Ananyev    return NGX_OK;
378e18a033bSKonstantin Ananyev}
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev
381e18a033bSKonstantin Ananyevstatic ngx_int_t
382e18a033bSKonstantin Ananyevngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
383e18a033bSKonstantin Ananyev    ngx_ssl_stapling_t *staple, ngx_str_t *responder)
384e18a033bSKonstantin Ananyev{
385e18a033bSKonstantin Ananyev    char                      *s;
386e18a033bSKonstantin Ananyev    ngx_str_t                  rsp;
387e18a033bSKonstantin Ananyev    ngx_url_t                  u;
388e18a033bSKonstantin Ananyev    STACK_OF(OPENSSL_STRING)  *aia;
389e18a033bSKonstantin Ananyev
390e18a033bSKonstantin Ananyev    if (responder->len == 0) {
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyev        /* extract OCSP responder URL from certificate */
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev        aia = X509_get1_ocsp(staple->cert);
395e18a033bSKonstantin Ananyev        if (aia == NULL) {
396e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
397e18a033bSKonstantin Ananyev                          "\"ssl_stapling\" ignored, "
398e18a033bSKonstantin Ananyev                          "no OCSP responder URL in the certificate \"%s\"",
399e18a033bSKonstantin Ananyev                          staple->name);
400e18a033bSKonstantin Ananyev            return NGX_DECLINED;
401e18a033bSKonstantin Ananyev        }
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyev#if OPENSSL_VERSION_NUMBER >= 0x10000000L
404e18a033bSKonstantin Ananyev        s = sk_OPENSSL_STRING_value(aia, 0);
405e18a033bSKonstantin Ananyev#else
406e18a033bSKonstantin Ananyev        s = sk_value(aia, 0);
407e18a033bSKonstantin Ananyev#endif
408e18a033bSKonstantin Ananyev        if (s == NULL) {
409e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
410e18a033bSKonstantin Ananyev                          "\"ssl_stapling\" ignored, "
411e18a033bSKonstantin Ananyev                          "no OCSP responder URL in the certificate \"%s\"",
412e18a033bSKonstantin Ananyev                          staple->name);
413e18a033bSKonstantin Ananyev            X509_email_free(aia);
414