Klaus Demo nginx / 74ad449
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. Maxim Dounin 9 years ago
6 changed file(s) with 1774 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
6868 #include <ngx_slab.h>
6969 #include <ngx_inet.h>
7070 #include <ngx_cycle.h>
71 #include <ngx_resolver.h>
7172 #if (NGX_OPENSSL)
7273 #include <ngx_event_openssl.h>
7374 #endif
7475 #include <ngx_process_cycle.h>
7576 #include <ngx_conf_file.h>
76 #include <ngx_resolver.h>
7777 #include <ngx_open_file_cache.h>
7878 #include <ngx_os.h>
7979 #include <ngx_connection.h>
8181 int ngx_ssl_connection_index;
8282 int ngx_ssl_server_conf_index;
8383 int ngx_ssl_session_cache_index;
84 int ngx_ssl_certificate_index;
85 int ngx_ssl_stapling_index;
8486
8587
8688 ngx_int_t
136138 return NGX_ERROR;
137139 }
138140
141 ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
142 NULL);
143 if (ngx_ssl_certificate_index == -1) {
144 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
145 "SSL_CTX_get_ex_new_index() failed");
146 return NGX_ERROR;
147 }
148
149 ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
150 NULL);
151 if (ngx_ssl_stapling_index == -1) {
152 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
153 "SSL_CTX_get_ex_new_index() failed");
154 return NGX_ERROR;
155 }
156
139157 return NGX_OK;
140158 }
141159
217235 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
218236 ngx_str_t *key)
219237 {
238 BIO *bio;
239 X509 *x509;
240 u_long n;
241
220242 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
221243 return NGX_ERROR;
222244 }
223245
224 if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data)
246 /*
247 * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
248 * allow to access certificate later from SSL_CTX, so we reimplement
249 * it here
250 */
251
252 bio = BIO_new_file((char *) cert->data, "r");
253 if (bio == NULL) {
254 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
255 "BIO_new_file(\"%s\") failed", cert->data);
256 return NGX_ERROR;
257 }
258
259 x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
260 if (x509 == NULL) {
261 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
262 "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
263 BIO_free(bio);
264 return NGX_ERROR;
265 }
266
267 if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
268 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
269 "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
270 X509_free(x509);
271 BIO_free(bio);
272 return NGX_ERROR;
273 }
274
275 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
225276 == 0)
226277 {
227278 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
228 "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
229 cert->data);
230 return NGX_ERROR;
231 }
279 "SSL_CTX_set_ex_data() failed");
280 return NGX_ERROR;
281 }
282
283 X509_free(x509);
284
285 /* read rest of the chain */
286
287 for ( ;; ) {
288
289 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
290 if (x509 == NULL) {
291 n = ERR_peek_last_error();
292
293 if (ERR_GET_LIB(n) == ERR_LIB_PEM
294 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
295 {
296 /* end of file */
297 ERR_clear_error();
298 break;
299 }
300
301 /* some real error */
302
303 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
304 "PEM_read_bio_X509(\"%s\") failed", cert->data);
305 BIO_free(bio);
306 return NGX_ERROR;
307 }
308
309 if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
310 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
311 "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
312 cert->data);
313 X509_free(x509);
314 BIO_free(bio);
315 return NGX_ERROR;
316 }
317 }
318
319 BIO_free(bio);
232320
233321 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
234322 return NGX_ERROR;
104104 ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
105105 ngx_str_t *cert, ngx_int_t depth);
106106 ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl);
107 ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
107 ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl,
108 ngx_str_t *responder, ngx_str_t *file);
109 ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
110 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
108111 RSA *ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length);
109112 ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
110113 ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
160163 extern int ngx_ssl_connection_index;
161164 extern int ngx_ssl_server_conf_index;
162165 extern int ngx_ssl_session_cache_index;
166 extern int ngx_ssl_certificate_index;
167 extern int ngx_ssl_stapling_index;
163168
164169
165170 #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
77 #include <ngx_config.h>
88 #include <ngx_core.h>
99 #include <ngx_event.h>
10 #include <ngx_event_connect.h>
1011
1112
1213 #ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB
1314
15
16 typedef struct {
17 ngx_str_t staple;
18 ngx_msec_t timeout;
19
20 ngx_resolver_t *resolver;
21 ngx_msec_t resolver_timeout;
22
23 ngx_addr_t *addrs;
24 ngx_str_t host;
25 ngx_str_t uri;
26 in_port_t port;
27
28 SSL_CTX *ssl_ctx;
29
30 X509 *cert;
31 X509 *issuer;
32
33 time_t valid;
34
35 ngx_uint_t loading; /* unsigned:1 */
36 } ngx_ssl_stapling_t;
37
38
39 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
40
41 struct ngx_ssl_ocsp_ctx_s {
42 X509 *cert;
43 X509 *issuer;
44
45 ngx_uint_t naddrs;
46
47 ngx_addr_t *addrs;
48 ngx_str_t host;
49 ngx_str_t uri;
50 in_port_t port;
51
52 ngx_resolver_t *resolver;
53 ngx_msec_t resolver_timeout;
54
55 ngx_msec_t timeout;
56
57 void (*handler)(ngx_ssl_ocsp_ctx_t *r);
58 void *data;
59
60 ngx_buf_t *request;
61 ngx_buf_t *response;
62 ngx_peer_connection_t peer;
63
64 ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *r);
65
66 ngx_uint_t state;
67
68 ngx_uint_t code;
69 ngx_uint_t count;
70
71 ngx_uint_t done;
72
73 u_char *header_name_start;
74 u_char *header_name_end;
75 u_char *header_start;
76 u_char *header_end;
77
78 ngx_pool_t *pool;
79 ngx_log_t *log;
80 };
81
82
83 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
84 ngx_str_t *file);
85 static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl);
86 static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
87 ngx_str_t *responder);
1488
1589 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
1690 void *data);
91 static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
92 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
93
94 static void ngx_ssl_stapling_cleanup(void *data);
95
96 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
97 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
98 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
99 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
100 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
101 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
102 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
103 static void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);
104
105 static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
106 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
107 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
108 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
109 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
110 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
111
112 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
17113
18114
19115 ngx_int_t
20 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
21 {
22 BIO *bio;
23 int len;
24 u_char *p, *buf;
25 ngx_str_t *staple;
26 OCSP_RESPONSE *response;
27
28 if (file->len == 0) {
116 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
117 ngx_str_t *file)
118 {
119 ngx_int_t rc;
120 ngx_pool_cleanup_t *cln;
121 ngx_ssl_stapling_t *staple;
122
123 staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
124 if (staple == NULL) {
125 return NGX_ERROR;
126 }
127
128 cln = ngx_pool_cleanup_add(cf->pool, 0);
129 if (cln == NULL) {
130 return NGX_ERROR;
131 }
132
133 cln->handler = ngx_ssl_stapling_cleanup;
134 cln->data = staple;
135
136 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple)
137 == 0)
138 {
139 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
140 "SSL_CTX_set_ex_data() failed");
141 return NGX_ERROR;
142 }
143
144 staple->ssl_ctx = ssl->ctx;
145 staple->timeout = 60000;
146
147 if (file->len) {
148 /* use OCSP response from the file */
149
150 if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) {
151 return NGX_ERROR;
152 }
153
154 goto done;
155 }
156
157 rc = ngx_ssl_stapling_issuer(cf, ssl);
158
159 if (rc == NGX_DECLINED) {
29160 return NGX_OK;
30161 }
162
163 if (rc != NGX_OK) {
164 return NGX_ERROR;
165 }
166
167 rc = ngx_ssl_stapling_responder(cf, ssl, responder);
168
169 if (rc == NGX_DECLINED) {
170 return NGX_OK;
171 }
172
173 if (rc != NGX_OK) {
174 return NGX_ERROR;
175 }
176
177 done:
178
179 SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
180 SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple);
181
182 return NGX_OK;
183 }
184
185
186 static ngx_int_t
187 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
188 {
189 BIO *bio;
190 int len;
191 u_char *p, *buf;
192 OCSP_RESPONSE *response;
193 ngx_ssl_stapling_t *staple;
194
195 staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
31196
32197 if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
33198 return NGX_ERROR;
55220 goto failed;
56221 }
57222
58 buf = ngx_pnalloc(cf->pool, len);
223 buf = ngx_alloc(len, ssl->log);
59224 if (buf == NULL) {
60225 goto failed;
61226 }
65230 if (len <= 0) {
66231 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
67232 "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
233 ngx_free(buf);
68234 goto failed;
69235 }
70236
71237 OCSP_RESPONSE_free(response);
72238 BIO_free(bio);
73239
74 staple = ngx_palloc(cf->pool, sizeof(ngx_str_t));
75 if (staple == NULL) {
76 return NGX_ERROR;
77 }
78
79 staple->data = buf;
80 staple->len = len;
81
82 SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
83 SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple);
240 staple->staple.data = buf;
241 staple->staple.len = len;
84242
85243 return NGX_OK;
86244
93251 }
94252
95253
254 static ngx_int_t
255 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
256 {
257 int i, n, rc;
258 X509 *cert, *issuer;
259 X509_STORE *store;
260 X509_STORE_CTX *store_ctx;
261 STACK_OF(X509) *chain;
262 ngx_ssl_stapling_t *staple;
263
264 staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
265 cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
266
267 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
268 SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
269 #else
270 chain = ssl->ctx->extra_certs;
271 #endif
272
273 n = sk_X509_num(chain);
274
275 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
276 "SSL get issuer: %d extra certs", n);
277
278 for (i = 0; i < n; i++) {
279 issuer = sk_X509_value(chain, i);
280 if (X509_check_issued(issuer, cert) == X509_V_OK) {
281 CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
282
283 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
284 "SSL get issuer: found %p in extra certs", issuer);
285
286 staple->cert = cert;
287 staple->issuer = issuer;
288
289 return NGX_OK;
290 }
291 }
292
293 store = SSL_CTX_get_cert_store(ssl->ctx);
294 if (store == NULL) {
295 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
296 "SSL_CTX_get_cert_store() failed");
297 return NGX_ERROR;
298 }
299
300 store_ctx = X509_STORE_CTX_new();
301 if (store_ctx == NULL) {
302 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
303 "X509_STORE_CTX_new() failed");
304 return NGX_ERROR;
305 }
306
307 if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
308 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
309 "X509_STORE_CTX_init() failed");
310 return NGX_ERROR;
311 }
312
313 rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
314
315 if (rc == -1) {
316 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
317 "X509_STORE_CTX_get1_issuer() failed");
318 X509_STORE_CTX_free(store_ctx);
319 return NGX_ERROR;
320 }
321
322 if (rc == 0) {
323 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
324 "\"ssl_stapling\" ignored, issuer certificate not found");
325 X509_STORE_CTX_free(store_ctx);
326 return NGX_DECLINED;
327 }
328
329 X509_STORE_CTX_free(store_ctx);
330
331 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
332 "SSL get issuer: found %p in cert store", issuer);
333
334 staple->cert = cert;
335 staple->issuer = issuer;
336
337 return NGX_OK;
338 }
339
340
341 static ngx_int_t
342 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder)
343 {
344 ngx_url_t u;
345 char *s;
346 ngx_ssl_stapling_t *staple;
347 STACK_OF(OPENSSL_STRING) *aia;
348
349 staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
350
351 if (responder->len == 0) {
352
353 /* extract OCSP responder URL from certificate */
354
355 aia = X509_get1_ocsp(staple->cert);
356 if (aia == NULL) {
357 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
358 "\"ssl_stapling\" ignored, "
359 "no OCSP responder URL in the certificate");
360 return NGX_DECLINED;
361 }
362
363 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
364 s = sk_OPENSSL_STRING_value(aia, 0);
365 #else
366 s = sk_value(aia, 0);
367 #endif
368 if (s == NULL) {
369 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
370 "\"ssl_stapling\" ignored, "
371 "no OCSP responder URL in the certificate");
372 X509_email_free(aia);
373 return NGX_DECLINED;
374 }
375
376 responder->len = ngx_strlen(s);
377 responder->data = ngx_palloc(cf->pool, responder->len);
378 if (responder->data == NULL) {
379 X509_email_free(aia);
380 return NGX_ERROR;
381 }
382
383 ngx_memcpy(responder->data, s, responder->len);
384 X509_email_free(aia);
385 }
386
387 ngx_memzero(&u, sizeof(ngx_url_t));
388
389 u.url = *responder;
390 u.default_port = 80;
391 u.uri_part = 1;
392
393 if (u.url.len > 7
394 && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
395 {
396 u.url.len -= 7;
397 u.url.data += 7;
398
399 } else {
400 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
401 "\"ssl_stapling\" ignored, "
402 "invalid URL prefix in OCSP responder \"%V\"", &u.url);
403 return NGX_DECLINED;
404 }
405
406 if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
407 if (u.err) {
408 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
409 "\"ssl_stapling\" ignored, "
410 "%s in OCSP responder \"%V\"", u.err, &u.url);
411 return NGX_DECLINED;
412 }
413
414 return NGX_ERROR;
415 }
416
417 staple->addrs = u.addrs;
418 staple->host = u.host;
419 staple->uri = u.uri;
420 staple->port = u.port;
421
422 if (staple->uri.len == 0) {
423 ngx_str_set(&staple->uri, "/");
424 }
425
426 return NGX_OK;
427 }
428
429
430 ngx_int_t
431 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
432 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
433 {
434 ngx_ssl_stapling_t *staple;
435
436 staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
437
438 staple->resolver = resolver;
439 staple->resolver_timeout = resolver_timeout;
440
441 return NGX_OK;
442 }
443
444
96445 static int
97446 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
98447 {
99 u_char *p;
100 ngx_str_t *staple;
101 ngx_connection_t *c;
448 int rc;
449 u_char *p;
450 ngx_connection_t *c;
451 ngx_ssl_stapling_t *staple;
102452
103453 c = ngx_ssl_get_connection(ssl_conn);
104454
106456 "SSL certificate status callback");
107457
108458 staple = data;
109
110 /* we have to copy the staple as OpenSSL will free it by itself */
111
112 p = OPENSSL_malloc(staple->len);
113 if (p == NULL) {
114 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
115 return SSL_TLSEXT_ERR_ALERT_FATAL;
116 }
117
118 ngx_memcpy(p, staple->data, staple->len);
119
120 SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->len);
121
122 return SSL_TLSEXT_ERR_OK;
123 }
124
125
459 rc = SSL_TLSEXT_ERR_NOACK;
460
461 if (staple->staple.len) {
462 /* we have to copy ocsp response as OpenSSL will free it by itself */
463
464 p = OPENSSL_malloc(staple->staple.len);
465 if (p == NULL) {
466 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
467 return SSL_TLSEXT_ERR_NOACK;
468 }
469
470 ngx_memcpy(p, staple->staple.data, staple->staple.len);
471
472 SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
473
474 rc = SSL_TLSEXT_ERR_OK;
475 }
476
477 ngx_ssl_stapling_update(staple);
478
479 return rc;
480 }
481
482
483 static void
484 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
485 {
486 ngx_ssl_ocsp_ctx_t *ctx;
487
488 if (staple->host.len == 0
489 || staple->loading || staple->valid >= ngx_time())
490 {
491 return;
492 }
493
494 staple->loading = 1;
495
496 ctx = ngx_ssl_ocsp_start();
497 if (ctx == NULL) {
498 return;
499 }
500
501 ctx->cert = staple->cert;
502 ctx->issuer = staple->issuer;
503
504 ctx->addrs = staple->addrs;
505 ctx->host = staple->host;
506 ctx->uri = staple->uri;
507 ctx->port = staple->port;
508 ctx->timeout = staple->timeout;
509
510 ctx->resolver = staple->resolver;
511 ctx->resolver_timeout = staple->resolver_timeout;
512
513 ctx->handler = ngx_ssl_stapling_ocsp_handler;
514 ctx->data = staple;
515
516 ngx_ssl_ocsp_request(ctx);
517
518 return;
519 }
520
521
522 static void
523 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
524 {
525 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
526 const
527 #endif
528 u_char *p;
529 int n;
530 size_t len;
531 ngx_str_t response;
532 X509_STORE *store;
533 STACK_OF(X509) *chain;
534 OCSP_CERTID *id;
535 OCSP_RESPONSE *ocsp;
536 OCSP_BASICRESP *basic;
537 ngx_ssl_stapling_t *staple;
538 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
539
540 staple = ctx->data;
541 ocsp = NULL;
542 basic = NULL;
543 id = NULL;
544
545 if (ctx->code != 200) {
546 goto error;
547 }
548
549 /* check the response */
550
551 len = ctx->response->last - ctx->response->pos;
552 p = ctx->response->pos;
553
554 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
555 if (ocsp == NULL) {
556 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
557 "d2i_OCSP_RESPONSE() failed");
558 goto error;
559 }
560
561 n = OCSP_response_status(ocsp);
562
563 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
564 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
565 "OCSP response not successful (%d: %s)",
566 n, OCSP_response_status_str(n));
567 goto error;
568 }
569
570 basic = OCSP_response_get1_basic(ocsp);
571 if (basic == NULL) {
572 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
573 "OCSP_response_get1_basic() failed");
574 goto error;
575 }
576
577 store = SSL_CTX_get_cert_store(staple->ssl_ctx);
578 if (store == NULL) {
579 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
580 "SSL_CTX_get_cert_store() failed");
581 goto error;
582 }
583
584 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
585 SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
126586 #else
587 chain = staple->ssl_ctx->extra_certs;
588 #endif
589
590 if (OCSP_basic_verify(basic, chain, store, 0) != 1) {
591 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
592 "OCSP_basic_verify() failed");
593 goto error;
594 }
595
596 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
597 if (id == NULL) {
598 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
599 "OCSP_cert_to_id() failed");
600 goto error;
601 }
602
603 if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
604 &thisupdate, &nextupdate)
605 != 1)
606 {
607 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
608 "certificate status not found in the OCSP response",
609 n, OCSP_response_status_str(n));
610 goto error;
611 }
612
613 if (n != V_OCSP_CERTSTATUS_GOOD) {
614 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
615 "certificate status \"%s\" in the OCSP response",
616 n, OCSP_cert_status_str(n));
617 goto error;
618 }
619
620 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
621 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
622 "OCSP_check_validity() failed");
623 goto error;
624 }
625
626 OCSP_CERTID_free(id);
627 OCSP_BASICRESP_free(basic);
628 OCSP_RESPONSE_free(ocsp);
629
630 /* copy the response to memory not in ctx->pool */
631
632 response.len = len;
633 response.data = ngx_alloc(response.len, ctx->log);
634
635 if (response.data == NULL) {
636 goto done;
637 }
638
639 ngx_memcpy(response.data, ctx->response->pos, response.len);
640
641 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
642 "ssl ocsp response, %s, %uz",
643 OCSP_cert_status_str(n), response.len);
644
645 if (staple->staple.data) {
646 ngx_free(staple->staple.data);
647 }
648
649 staple->staple = response;
650
651 done:
652
653 staple->loading = 0;
654 staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */
655
656 ngx_ssl_ocsp_done(ctx);
657 return;
658
659 error:
660
661 staple->loading = 0;
662 staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */
663
664 if (id) {
665 OCSP_CERTID_free(id);
666 }
667
668 if (basic) {
669 OCSP_BASICRESP_free(basic);
670 }
671
672 if (ocsp) {
673 OCSP_RESPONSE_free(ocsp);
674 }
675
676 ngx_ssl_ocsp_done(ctx);
677 }
678
679
680 static void
681 ngx_ssl_stapling_cleanup(void *data)
682 {
683 ngx_ssl_stapling_t *staple = data;
684
685 if (staple->issuer) {
686 X509_free(staple->issuer);
687 }
688
689 if (staple->staple.data) {
690 ngx_free(staple->staple.data);
691 }
692 }
693
694
695 static ngx_ssl_ocsp_ctx_t *
696 ngx_ssl_ocsp_start(void)
697 {
698 ngx_log_t *log;
699 ngx_pool_t *pool;
700 ngx_ssl_ocsp_ctx_t *ctx;
701
702 pool = ngx_create_pool(2048, ngx_cycle->log);
703 if (pool == NULL) {
704 return NULL;
705 }
706
707 ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
708 if (ctx == NULL) {
709 ngx_destroy_pool(pool);
710 return NULL;
711 }
712
713 log = ngx_palloc(pool, sizeof(ngx_log_t));
714 if (log == NULL) {
715 ngx_destroy_pool(pool);
716 return NULL;
717 }
718
719 ctx->pool = pool;
720
721 *log = *ctx->pool->log;
722
723 ctx->pool->log = log;
724 ctx->log = log;
725
726 log->handler = ngx_ssl_ocsp_log_error;
727 log->data = ctx;
728 log->action = "requesting certificate status";
729
730 return ctx;
731 }
732
733
734 static void
735 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
736 {
737 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
738 "ssl ocsp done");
739
740 if (ctx->peer.connection) {
741 ngx_close_connection(ctx->peer.connection);
742 }
743
744 ngx_destroy_pool(ctx->pool);
745 }
746
747
748 static void
749 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
750 {
751 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
752 "ssl ocsp error");
753
754 ctx->code = 0;
755 ctx->handler(ctx);
756 }
757
758
759 static void
760 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
761 {
762 ngx_resolver_ctx_t *resolve, temp;
763
764 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
765 "ssl ocsp request");
766
767 if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
768 ngx_ssl_ocsp_error(ctx);
769 return;
770 }
771
772 if (ctx->resolver) {
773 /* resolve OCSP responder hostname */
774
775 temp.name = ctx->host;
776
777 resolve = ngx_resolve_start(ctx->resolver, &temp);
778 if (resolve == NULL) {
779 ngx_ssl_ocsp_error(ctx);
780 return;
781 }
782
783 if (resolve == NGX_NO_RESOLVER) {
784 ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
785 "no resolver defined to resolve %V", &ctx->host);
786 goto connect;
787 }
788
789 resolve->name = ctx->host;
790 resolve->type = NGX_RESOLVE_A;
791 resolve->handler = ngx_ssl_ocsp_resolve_handler;
792 resolve->data = ctx;
793 resolve->timeout = ctx->resolver_timeout;
794
795 if (ngx_resolve_name(resolve) != NGX_OK) {
796 ngx_ssl_ocsp_error(ctx);
797 return;
798 }
799
800 return;
801 }
802
803 connect:
804
805 ngx_ssl_ocsp_connect(ctx);
806 }
807
808
809 static void
810 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
811 {
812 ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
813
814 u_char *p;
815 size_t len;
816 in_port_t port;
817 ngx_uint_t i;
818 struct sockaddr_in *sin;
819
820 ngx_log_debug0(NGX_LOG_ALERT, ctx->log, 0,
821 "ssl ocsp resolve handler");
822
823 if (resolve->state) {
824 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
825 "%V could not be resolved (%i: %s)",
826 &resolve->name, resolve->state,
827 ngx_resolver_strerror(resolve->state));
828 goto failed;
829 }
830
831 #if (NGX_DEBUG)
832 {
833 in_addr_t addr;
834
835 for (i = 0; i < resolve->naddrs; i++) {
836 addr = ntohl(resolve->addrs[i]);
837
838 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
839 "name was resolved to %ud.%ud.%ud.%ud",
840 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
841 (addr >> 8) & 0xff, addr & 0xff);
842 }
843 }
844 #endif
845
846 ctx->naddrs = resolve->naddrs;
847 ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
848
849 if (ctx->addrs == NULL) {
850 goto failed;
851 }
852
853 port = htons(ctx->port);
854
855 for (i = 0; i < resolve->naddrs; i++) {
856
857 sin = ngx_pcalloc(ctx->pool, sizeof(struct sockaddr_in));
858 if (sin == NULL) {
859 goto failed;
860 }
861
862 sin->sin_family = AF_INET;
863 sin->sin_port = port;
864 sin->sin_addr.s_addr = resolve->addrs[i];
865
866 ctx->addrs[i].sockaddr = (struct sockaddr *) sin;
867 ctx->addrs[i].socklen = sizeof(struct sockaddr_in);
868
869 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
870
871 p = ngx_pnalloc(ctx->pool, len);
872 if (p == NULL) {
873 goto failed;
874 }
875
876 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
877
878 ctx->addrs[i].name.len = len;
879 ctx->addrs[i].name.data = p;
880 }
881
882 ngx_resolve_name_done(resolve);
883
884 ngx_ssl_ocsp_connect(ctx);
885 return;
886
887 failed:
888
889 ngx_resolve_name_done(resolve);
890 ngx_ssl_ocsp_error(ctx);
891 }
892
893
894 static void
895 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
896 {
897 ngx_int_t rc;
898
899 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
900 "ssl ocsp connect");
901
902 /* TODO: use all ip addresses */
903
904 ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
905 ctx->peer.socklen = ctx->addrs[0].socklen;
906 ctx->peer.name = &ctx->addrs[0].name;
907 ctx->peer.get = ngx_event_get_peer;
908 ctx->peer.log = ctx->log;
909 ctx->peer.log_error = NGX_ERROR_ERR;
910
911 rc = ngx_event_connect_peer(&ctx->peer);
912
913 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
914 "ssl ocsp connect peer done");
915
916 if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
917 ngx_ssl_ocsp_error(ctx);
918 return;
919 }
920
921 ctx->peer.connection->data = ctx;
922 ctx->peer.connection->pool = ctx->pool;
923
924 ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
925 ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
926
927 ctx->process = ngx_ssl_ocsp_process_status_line;
928
929 ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
930 ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
931
932 if (rc == NGX_OK) {
933 ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
934 return;
935 }
936 }
937
938
939 static void
940 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
941 {
942 ssize_t n, size;
943 ngx_connection_t *c;
944 ngx_ssl_ocsp_ctx_t *ctx;
945
946 c = wev->data;
947 ctx = c->data;
948
949 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
950 "ssl ocsp write handler");
951
952 if (wev->timedout) {
953 ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
954 "OCSP responder timed out");
955 ngx_ssl_ocsp_error(ctx);
956 return;
957 }
958
959 size = ctx->request->last - ctx->request->pos;
960
961 n = ngx_send(c, ctx->request->pos, size);
962
963 if (n == NGX_ERROR) {
964 ngx_ssl_ocsp_error(ctx);
965 return;
966 }
967
968 if (n > 0) {
969 ctx->request->pos += n;
970
971 if (n == size) {
972 wev->handler = ngx_ssl_ocsp_dummy_handler;
973
974 if (wev->timer_set) {
975 ngx_del_timer(wev);
976 }
977
978 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
979 ngx_ssl_ocsp_error(ctx);
980 }
981
982 return;
983 }
984 }
985
986 if (!wev->timer_set) {
987 ngx_add_timer(wev, ctx->timeout);
988 }
989 }
990
991
992 static void
993 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
994 {
995 ssize_t n, size;
996 ngx_int_t rc;
997 ngx_ssl_ocsp_ctx_t *ctx;
998 ngx_connection_t *c;
999
1000 c = rev->data;
1001 ctx = c->data;
1002
1003 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1004 "ssl ocsp read handler");
1005
1006 if (rev->timedout) {
1007 ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1008 "OCSP responder timed out");
1009 ngx_ssl_ocsp_error(ctx);
1010 return;
1011 }
1012
1013 if (ctx->response == NULL) {
1014 ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1015 if (ctx->response == NULL) {
1016 ngx_ssl_ocsp_error(ctx);
1017 return;
1018 }
1019 }
1020
1021 for ( ;; ) {
1022
1023 size = ctx->response->end - ctx->response->last;
1024
1025 n = ngx_recv(c, ctx->response->last, size);
1026
1027 if (n > 0) {
1028 ctx->response->last += n;
1029
1030 rc = ctx->process(ctx);
1031
1032 if (rc == NGX_ERROR) {
1033 ngx_ssl_ocsp_error(ctx);
1034 return;
1035 }
1036
1037 continue;
1038 }
1039
1040 if (n == NGX_AGAIN) {
1041
1042 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1043 ngx_ssl_ocsp_error(ctx);
1044 }
1045
1046 return;
1047 }
1048
1049 break;
1050 }
1051
1052 ctx->done = 1;
1053
1054 rc = ctx->process(ctx);
1055
1056 if (rc == NGX_DONE) {
1057 /* ctx->handler() was called */
1058 return;
1059 }
1060
1061 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1062 "OCSP responder prematurely closed connection");
1063
1064 ngx_ssl_ocsp_error(ctx);
1065 }
1066
1067
1068 static void
1069 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1070 {
1071 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1072 "ssl ocsp dummy handler");
1073 }
1074
1075
1076 static ngx_int_t
1077 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1078 {
1079 int len;
1080 u_char *p;
1081 uintptr_t escape;
1082 ngx_str_t binary, base64;
1083 ngx_buf_t *b;
1084 OCSP_CERTID *id;
1085 OCSP_REQUEST *ocsp;
1086
1087 ocsp = OCSP_REQUEST_new();
1088 if (ocsp == NULL) {
1089 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1090 "OCSP_REQUEST_new() failed");
1091 return NGX_ERROR;
1092 }
1093
1094 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1095 if (id == NULL) {
1096 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1097 "OCSP_cert_to_id() failed");
1098 goto failed;
1099 }
1100
1101 if (OCSP_request_add0_id(ocsp, id) == NULL) {
1102 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1103 "OCSP_request_add0_id() failed");
1104 goto failed;
1105 }
1106
1107 len = i2d_OCSP_REQUEST(ocsp, NULL);
1108 if (len <= 0) {
1109 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1110 "i2d_OCSP_REQUEST() failed");
1111 goto failed;
1112 }
1113
1114 binary.len = len;
1115 binary.data = ngx_palloc(ctx->pool, len);
1116 if (binary.data == NULL) {
1117 goto failed;
1118 }
1119
1120 p = binary.data;
1121 len = i2d_OCSP_REQUEST(ocsp, &p);
1122 if (len <= 0) {
1123 ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1124 "i2d_OCSP_REQUEST() failed");
1125 goto failed;
1126 }
1127
1128 base64.len = ngx_base64_encoded_length(binary.len);
1129 base64.data = ngx_palloc(ctx->pool, base64.len);
1130 if (base64.data == NULL) {
1131 goto failed;
1132 }
1133
1134 ngx_encode_base64(&base64, &binary);
1135
1136 escape = ngx_escape_uri(NULL, base64.data, base64.len,
1137 NGX_ESCAPE_URI_COMPONENT);
1138
1139 ngx_log_debug(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1140 "ssl ocsp request length %z, escape %d",
1141 base64.len, escape);
1142
1143 len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1144 + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1145 + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1146 + sizeof(CRLF) - 1;
1147
1148 b = ngx_create_temp_buf(ctx->pool, len);
1149 if (b == NULL) {
1150 goto failed;
1151 }
1152
1153 p = b->last;
1154
1155 p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1156 p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1157
1158 if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1159 *p++ = '/';
1160 }
1161
1162 if (escape == 0) {
1163 p = ngx_cpymem(p, base64.data, base64.len);
1164
1165 } else {
1166 p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1167 NGX_ESCAPE_URI_COMPONENT);
1168 }
1169
1170 p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1171 p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1172 p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1173 *p++ = CR; *p++ = LF;
1174
1175 /* add "\r\n" at the header end */
1176 *p++ = CR; *p++ = LF;
1177
1178 b->last = p;
1179 ctx->request = b;
1180
1181 return NGX_OK;
1182
1183 failed:
1184
1185 OCSP_REQUEST_free(ocsp);
1186
1187 return NGX_ERROR;
1188 }
1189
1190
1191 static ngx_int_t
1192 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1193 {
1194 ngx_int_t rc;
1195
1196 rc = ngx_ssl_ocsp_parse_status_line(ctx);
1197
1198 if (rc == NGX_OK) {
1199 #if 0
1200 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1201 "ssl ocsp status line \"%*s\"",
1202 ctx->response->pos - ctx->response->start,
1203 ctx->response->start);
1204 #endif
1205
1206 ctx->process = ngx_ssl_ocsp_process_headers;
1207 return ctx->process(ctx);
1208 }
1209
1210 if (rc == NGX_AGAIN) {
1211 return NGX_AGAIN;
1212 }
1213
1214 /* rc == NGX_ERROR */
1215
1216 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1217 "OCSP responder sent invalid response");
1218
1219 return NGX_ERROR;
1220 }
1221
1222
1223 static ngx_int_t
1224 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1225 {
1226 u_char ch;
1227 u_char *p;
1228 ngx_buf_t *b;
1229 enum {
1230 sw_start = 0,
1231 sw_H,
1232 sw_HT,
1233 sw_HTT,
1234 sw_HTTP,
1235 sw_first_major_digit,
1236 sw_major_digit,
1237 sw_first_minor_digit,
1238 sw_minor_digit,
1239 sw_status,
1240 sw_space_after_status,
1241 sw_status_text,
1242 sw_almost_done
1243 } state;
1244
1245 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1246 "ssl ocsp process status line");
1247
1248 state = ctx->state;
1249 b = ctx->response;
1250
1251 for (p = b->pos; p < b->last; p++) {
1252 ch = *p;
1253
1254 switch (state) {
1255
1256 /* "HTTP/" */
1257 case sw_start:
1258 switch (ch) {
1259 case 'H':
1260 state = sw_H;
1261 break;
1262 default:
1263 return NGX_ERROR;
1264 }
1265 break;
1266
1267 case sw_H:
1268 switch (ch) {
1269 case 'T':
1270 state = sw_HT;
1271 break;
1272 default:
1273 return NGX_ERROR;
1274 }
1275 break;
1276
1277 case sw_HT:
1278 switch (ch) {
1279 case 'T':
1280 state = sw_HTT;
1281 break;
1282 default:
1283 return NGX_ERROR;
1284 }
1285 break;
1286
1287 case sw_HTT:
1288 switch (ch) {
1289 case 'P':
1290 state = sw_HTTP;
1291 break;
1292 default:
1293 return NGX_ERROR;
1294 }
1295 break;
1296
1297 case sw_HTTP:
1298 switch (ch) {
1299 case '/':
1300 state = sw_first_major_digit;
1301 break;
1302 default:
1303 return NGX_ERROR;
1304 }
1305 break;
1306
1307 /* the first digit of major HTTP version */
1308 case sw_first_major_digit:
1309 if (ch < '1' || ch > '9') {
1310 return NGX_ERROR;
1311 }
1312
1313 state = sw_major_digit;
1314 break;
1315
1316 /* the major HTTP version or dot */
1317 case sw_major_digit:
1318 if (ch == '.') {
1319 state = sw_first_minor_digit;
1320 break;
1321 }
1322
1323 if (ch < '0' || ch > '9') {
1324 return NGX_ERROR;
1325 }
1326
1327 break;
1328
1329 /* the first digit of minor HTTP version */
1330 case sw_first_minor_digit:
1331 if (ch < '0' || ch > '9') {
1332 return NGX_ERROR;
1333 }
1334
1335 state = sw_minor_digit;
1336 break;
1337
1338 /* the minor HTTP version or the end of the request line */
1339 case sw_minor_digit:
1340 if (ch == ' ') {
1341 state = sw_status;
1342 break;
1343 }
1344
1345 if (ch < '0' || ch > '9') {
1346 return NGX_ERROR;
1347 }
1348
1349 break;
1350
1351 /* HTTP status code */
1352 case sw_status:
1353 if (ch == ' ') {
1354 break;
1355 }
1356
1357 if (ch < '0' || ch > '9') {
1358 return NGX_ERROR;
1359 }
1360
1361 ctx->code = ctx->code * 10 + ch - '0';
1362
1363 if (++ctx->count == 3) {
1364 state = sw_space_after_status;
1365 }
1366
1367 break;
1368
1369 /* space or end of line */
1370 case sw_space_after_status:
1371 switch (ch) {
1372 case ' ':
1373 state = sw_status_text;
1374 break;
1375 case '.': /* IIS may send 403.1, 403.2, etc */
1376 state = sw_status_text;
1377 break;
1378 case CR:
1379 state = sw_almost_done;
1380 break;
1381 case LF:
1382 goto done;
1383 default:
1384 return NGX_ERROR;
1385 }
1386 break;
1387
1388 /* any text until end of line */
1389 case sw_status_text:
1390 switch (ch) {
1391 case CR:
1392 state = sw_almost_done;
1393 break;
1394 case LF:
1395 goto done;
1396 }
1397 break;
1398
1399 /* end of status line */
1400 case sw_almost_done:
1401 switch (ch) {
1402 case LF:
1403 goto done;
1404 default:
1405 return NGX_ERROR;
1406 }
1407 }
1408 }
1409
1410 b->pos = p;
1411 ctx->state = state;
1412
1413 return NGX_AGAIN;
1414
1415 done:
1416
1417 b->pos = p + 1;
1418 ctx->state = sw_start;
1419
1420 return NGX_OK;
1421 }
1422
1423
1424 static ngx_int_t
1425 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1426 {
1427 ngx_int_t rc;
1428
1429 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1430 "ssl ocsp process headers");
1431
1432 for ( ;; ) {
1433 rc = ngx_ssl_ocsp_parse_header_line(ctx);
1434
1435 if (rc == NGX_OK) {
1436
1437 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1438 "ssl ocsp header \"%*s: %*s\"",
1439 ctx->header_name_end - ctx->header_name_start,
1440 ctx->header_name_start,
1441 ctx->header_end - ctx->header_start,
1442 ctx->header_start);
1443
1444 /* TODO: honor Content-Length */
1445
1446 continue;
1447 }
1448
1449 if (rc == NGX_DONE) {
1450 break;
1451 }
1452
1453 if (rc == NGX_AGAIN) {
1454 return NGX_AGAIN;
1455 }
1456
1457 /* rc == NGX_ERROR */
1458
1459 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1460 "OCSP responder sent invalid response");
1461
1462 return NGX_ERROR;
1463 }
1464
1465 ctx->process = ngx_ssl_ocsp_process_body;
1466 return ctx->process(ctx);
1467 }
1468
1469 static ngx_int_t
1470 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1471 {
1472 u_char c, ch, *p;
1473 enum {
1474 sw_start = 0,
1475 sw_name,
1476 sw_space_before_value,
1477 sw_value,
1478 sw_space_after_value,
1479 sw_almost_done,
1480 sw_header_almost_done
1481 } state;
1482
1483 state = ctx->state;
1484
1485 for (p = ctx->response->pos; p < ctx->response->last; p++) {
1486 ch = *p;
1487
1488 #if 0
1489 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1490 "s:%d in:'%02Xd:%c'", state, ch, ch);
1491 #endif
1492
1493 switch (state) {
1494
1495 /* first char */
1496 case sw_start:
1497
1498 switch (ch) {
1499 case CR:
1500 ctx->header_end = p;
1501 state = sw_header_almost_done;
1502 break;
1503 case LF:
1504 ctx->header_end = p;
1505 goto header_done;
1506 default:
1507 state = sw_name;
1508 ctx->header_name_start = p;
1509
1510 c = (u_char) (ch | 0x20);
1511 if (c >= 'a' && c <= 'z') {
1512 break;
1513 }
1514
1515 if (ch >= '0' && ch <= '9') {
1516 break;
1517 }
1518
1519 return NGX_ERROR;
1520 }
1521 break;
1522
1523 /* header name */
1524 case sw_name:
1525 c = (u_char) (ch | 0x20);
1526 if (c >= 'a' && c <= 'z') {
1527 break;
1528 }
1529
1530 if (ch == ':') {
1531 ctx->header_name_end = p;
1532 state = sw_space_before_value;
1533 break;
1534 }
1535
1536 if (ch == '-') {
1537 break;
1538 }
1539
1540 if (ch >= '0' && ch <= '9') {
1541 break;
1542 }
1543
1544 if (ch == CR) {
1545 ctx->header_name_end = p;
1546 ctx->header_start = p;
1547 ctx->header_end = p;
1548 state = sw_almost_done;
1549 break;
1550 }
1551
1552 if (ch == LF) {
1553 ctx->header_name_end = p;
1554 ctx->header_start = p;
1555 ctx->header_end = p;
1556 goto done;
1557 }
1558
1559 return NGX_ERROR;
1560
1561 /* space* before header value */
1562 case sw_space_before_value:
1563 switch (ch) {
1564 case ' ':
1565 break;
1566 case CR:
1567 ctx->header_start = p;
1568 ctx->header_end = p;
1569 state = sw_almost_done;
1570 break;
1571 case LF:
1572 ctx->header_start = p;
1573 ctx->header_end = p;
1574 goto done;
1575 default:
1576 ctx->header_start = p;
1577 state = sw_value;
1578 break;
1579 }
1580 break;
1581
1582 /* header value */
1583 case sw_value:
1584 switch (ch) {
1585 case ' ':
1586 ctx->header_end = p;
1587 state = sw_space_after_value;
1588 break;
1589 case CR:
1590 ctx->header_end = p;
1591 state = sw_almost_done;
1592 break;
1593 case LF:
1594 ctx->header_end = p;
1595 goto done;
1596 }
1597 break;
1598
1599 /* space* before end of header line */
1600 case sw_space_after_value:
1601 switch (ch) {
1602 case ' ':
1603 break;
1604 case CR:
1605 state = sw_almost_done;
1606 break;
1607 case LF:
1608 goto done;
1609 default:
1610 state = sw_value;
1611 break;
1612 }
1613 break;
1614
1615 /* end of header line */
1616 case sw_almost_done:
1617 switch (ch) {
1618 case LF:
1619 goto done;
1620 default:
1621 return NGX_ERROR;
1622 }
1623
1624 /* end of header */
1625 case sw_header_almost_done:
1626 switch (ch) {
1627 case LF:
1628 goto header_done;
1629 default:
1630 return NGX_ERROR;
1631 }
1632 }
1633 }
1634
1635 ctx->response->pos = p;
1636 ctx->state = state;
1637
1638 return NGX_AGAIN;
1639
1640 done:
1641
1642 ctx->response->pos = p + 1;
1643 ctx->state = sw_start;
1644
1645 return NGX_OK;
1646
1647 header_done:
1648
1649 ctx->response->pos = p + 1;
1650 ctx->state = sw_start;
1651
1652 return NGX_DONE;
1653 }
1654
1655
1656 static ngx_int_t
1657 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1658 {
1659 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1660 "ssl ocsp process body");
1661
1662 if (ctx->done) {
1663 ctx->handler(ctx);
1664 return NGX_DONE;
1665 }
1666
1667 return NGX_AGAIN;
1668 }
1669
1670
1671 static u_char *
1672 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1673 {
1674 u_char *p;
1675 ngx_ssl_ocsp_ctx_t *ctx;
1676
1677 p = buf;
1678
1679 if (log->action) {
1680 p = ngx_snprintf(buf, len, " while %s", log->action);
1681 len -= p - buf;
1682 }
1683
1684 ctx = log->data;
1685
1686 if (ctx) {
1687 p = ngx_snprintf(p, len, ", responder: %V", &ctx->host);
1688 }
1689
1690 return p;
1691 }
1692
1693
1694 #else
1271695
1281696
1291697 ngx_int_t
130 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
1698 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
1699 ngx_str_t *file)
1311700 {
1321701 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1331702 "\"ssl_stapling\" ignored, not supported");
1351704 return NGX_OK;
1361705 }
1371706
1707 ngx_int_t
1708 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
1709 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
1710 {
1711 return NGX_OK;
1712 }
1713
1381714
1391715 #endif
3131 void *conf);
3232 static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
3333 void *conf);
34
35 static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
3436
3537
3638 static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
172174 offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
173175 NULL },
174176
177 { ngx_string("ssl_stapling_responder"),
178 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
179 ngx_conf_set_str_slot,
180 NGX_HTTP_SRV_CONF_OFFSET,
181 offsetof(ngx_http_ssl_srv_conf_t, stapling_responder),
182 NULL },
183
175184 ngx_null_command
176185 };
177186
178187
179188 static ngx_http_module_t ngx_http_ssl_module_ctx = {
180189 ngx_http_ssl_add_variables, /* preconfiguration */
181 NULL, /* postconfiguration */
190 ngx_http_ssl_init, /* postconfiguration */
182191
183192 NULL, /* create main configuration */
184193 NULL, /* init main configuration */
350359 * sscf->ciphers = { 0, NULL };
351360 * sscf->shm_zone = NULL;
352361 * sscf->stapling_file = { 0, NULL };
362 * sscf->stapling_responder = { 0, NULL };
353363 */
354364
355365 sscf->enable = NGX_CONF_UNSET;
414424
415425 ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
416426 ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
427 ngx_conf_merge_str_value(conf->stapling_responder,
428 prev->stapling_responder, "");
417429
418430 conf->ssl.log = cf->log;
419431
550562 return NGX_CONF_ERROR;
551563 }
552564
553 if (conf->stapling
554 && ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file) != NGX_OK)
555 {
556 return NGX_CONF_ERROR;
565 if (conf->stapling) {
566
567 if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_responder,
568 &conf->stapling_file)
569 != NGX_OK)
570 {
571 return NGX_CONF_ERROR;
572 }
573
557574 }
558575
559576 return NGX_CONF_OK;
691708
692709 return NGX_CONF_ERROR;
693710 }
711
712
713 static ngx_int_t
714 ngx_http_ssl_init(ngx_conf_t *cf)
715 {
716 ngx_uint_t s;
717 ngx_http_ssl_srv_conf_t *sscf;
718 ngx_http_core_loc_conf_t *clcf;
719 ngx_http_core_srv_conf_t **cscfp;
720 ngx_http_core_main_conf_t *cmcf;
721
722 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
723 cscfp = cmcf->servers.elts;
724
725 for (s = 0; s < cmcf->servers.nelts; s++) {
726
727 sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
728
729 if (!sscf->stapling) {
730 continue;
731 }
732
733 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
734
735 if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
736 clcf->resolver_timeout)
737 != NGX_OK)
738 {
739 return NGX_ERROR;
740 }
741 }
742
743 return NGX_OK;
744 }
4343
4444 ngx_flag_t stapling;
4545 ngx_str_t stapling_file;
46 ngx_str_t stapling_responder;
4647
4748 u_char *file;
4849 ngx_uint_t line;