xref: /nginx/src/http/modules/ngx_http_ssl_module.c (revision 7934:61abb35bb8cf)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
14     ngx_pool_t *pool, ngx_str_t *s);
15 
16 
17 #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
18 #define NGX_DEFAULT_ECDH_CURVE  "auto"
19 
20 #define NGX_HTTP_ALPN_PROTO     "\x08http/1.1"
21 
22 
23 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
24 static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
25     const unsigned char **out, unsigned char *outlen,
26     const unsigned char *in, unsigned int inlen, void *arg);
27 #endif
28 
29 static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
30     ngx_http_variable_value_t *v, uintptr_t data);
31 static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
32     ngx_http_variable_value_t *v, uintptr_t data);
33 
34 static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
35 static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
36 static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
37     void *parent, void *child);
38 
39 static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
40     ngx_http_ssl_srv_conf_t *conf);
41 
42 static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
43     void *conf);
44 static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
45     void *conf);
46 static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
47     void *conf);
48 static char *ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd,
49     void *conf);
50 
51 static char *ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post,
52     void *data);
53 
54 static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
55 
56 
57 static ngx_conf_bitmask_t  ngx_http_ssl_protocols[] = {
58     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
59     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
60     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
61     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
62     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
63     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
64     { ngx_null_string, 0 }
65 };
66 
67 
68 static ngx_conf_enum_t  ngx_http_ssl_verify[] = {
69     { ngx_string("off"), 0 },
70     { ngx_string("on"), 1 },
71     { ngx_string("optional"), 2 },
72     { ngx_string("optional_no_ca"), 3 },
73     { ngx_null_string, 0 }
74 };
75 
76 
77 static ngx_conf_enum_t  ngx_http_ssl_ocsp[] = {
78     { ngx_string("off"), 0 },
79     { ngx_string("on"), 1 },
80     { ngx_string("leaf"), 2 },
81     { ngx_null_string, 0 }
82 };
83 
84 
85 static ngx_conf_deprecated_t  ngx_http_ssl_deprecated = {
86     ngx_conf_deprecated, "ssl", "listen ... ssl"
87 };
88 
89 
90 static ngx_conf_post_t  ngx_http_ssl_conf_command_post =
91     { ngx_http_ssl_conf_command_check };
92 
93 
94 static ngx_command_t  ngx_http_ssl_commands[] = {
95 
96     { ngx_string("ssl"),
97       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
98       ngx_http_ssl_enable,
99       NGX_HTTP_SRV_CONF_OFFSET,
100       offsetof(ngx_http_ssl_srv_conf_t, enable),
101       &ngx_http_ssl_deprecated },
102 
103     { ngx_string("ssl_certificate"),
104       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
105       ngx_conf_set_str_array_slot,
106       NGX_HTTP_SRV_CONF_OFFSET,
107       offsetof(ngx_http_ssl_srv_conf_t, certificates),
108       NULL },
109 
110     { ngx_string("ssl_certificate_key"),
111       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
112       ngx_conf_set_str_array_slot,
113       NGX_HTTP_SRV_CONF_OFFSET,
114       offsetof(ngx_http_ssl_srv_conf_t, certificate_keys),
115       NULL },
116 
117     { ngx_string("ssl_password_file"),
118       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
119       ngx_http_ssl_password_file,
120       NGX_HTTP_SRV_CONF_OFFSET,
121       0,
122       NULL },
123 
124     { ngx_string("ssl_dhparam"),
125       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
126       ngx_conf_set_str_slot,
127       NGX_HTTP_SRV_CONF_OFFSET,
128       offsetof(ngx_http_ssl_srv_conf_t, dhparam),
129       NULL },
130 
131     { ngx_string("ssl_ecdh_curve"),
132       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
133       ngx_conf_set_str_slot,
134       NGX_HTTP_SRV_CONF_OFFSET,
135       offsetof(ngx_http_ssl_srv_conf_t, ecdh_curve),
136       NULL },
137 
138     { ngx_string("ssl_protocols"),
139       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
140       ngx_conf_set_bitmask_slot,
141       NGX_HTTP_SRV_CONF_OFFSET,
142       offsetof(ngx_http_ssl_srv_conf_t, protocols),
143       &ngx_http_ssl_protocols },
144 
145     { ngx_string("ssl_ciphers"),
146       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
147       ngx_conf_set_str_slot,
148       NGX_HTTP_SRV_CONF_OFFSET,
149       offsetof(ngx_http_ssl_srv_conf_t, ciphers),
150       NULL },
151 
152     { ngx_string("ssl_buffer_size"),
153       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
154       ngx_conf_set_size_slot,
155       NGX_HTTP_SRV_CONF_OFFSET,
156       offsetof(ngx_http_ssl_srv_conf_t, buffer_size),
157       NULL },
158 
159     { ngx_string("ssl_verify_client"),
160       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
161       ngx_conf_set_enum_slot,
162       NGX_HTTP_SRV_CONF_OFFSET,
163       offsetof(ngx_http_ssl_srv_conf_t, verify),
164       &ngx_http_ssl_verify },
165 
166     { ngx_string("ssl_verify_depth"),
167       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
168       ngx_conf_set_num_slot,
169       NGX_HTTP_SRV_CONF_OFFSET,
170       offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
171       NULL },
172 
173     { ngx_string("ssl_client_certificate"),
174       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
175       ngx_conf_set_str_slot,
176       NGX_HTTP_SRV_CONF_OFFSET,
177       offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
178       NULL },
179 
180     { ngx_string("ssl_trusted_certificate"),
181       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
182       ngx_conf_set_str_slot,
183       NGX_HTTP_SRV_CONF_OFFSET,
184       offsetof(ngx_http_ssl_srv_conf_t, trusted_certificate),
185       NULL },
186 
187     { ngx_string("ssl_prefer_server_ciphers"),
188       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
189       ngx_conf_set_flag_slot,
190       NGX_HTTP_SRV_CONF_OFFSET,
191       offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers),
192       NULL },
193 
194     { ngx_string("ssl_session_cache"),
195       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
196       ngx_http_ssl_session_cache,
197       NGX_HTTP_SRV_CONF_OFFSET,
198       0,
199       NULL },
200 
201     { ngx_string("ssl_session_tickets"),
202       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
203       ngx_conf_set_flag_slot,
204       NGX_HTTP_SRV_CONF_OFFSET,
205       offsetof(ngx_http_ssl_srv_conf_t, session_tickets),
206       NULL },
207 
208     { ngx_string("ssl_session_ticket_key"),
209       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
210       ngx_conf_set_str_array_slot,
211       NGX_HTTP_SRV_CONF_OFFSET,
212       offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys),
213       NULL },
214 
215     { ngx_string("ssl_session_timeout"),
216       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
217       ngx_conf_set_sec_slot,
218       NGX_HTTP_SRV_CONF_OFFSET,
219       offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
220       NULL },
221 
222     { ngx_string("ssl_crl"),
223       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
224       ngx_conf_set_str_slot,
225       NGX_HTTP_SRV_CONF_OFFSET,
226       offsetof(ngx_http_ssl_srv_conf_t, crl),
227       NULL },
228 
229     { ngx_string("ssl_ocsp"),
230       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
231       ngx_conf_set_enum_slot,
232       NGX_HTTP_SRV_CONF_OFFSET,
233       offsetof(ngx_http_ssl_srv_conf_t, ocsp),
234       &ngx_http_ssl_ocsp },
235 
236     { ngx_string("ssl_ocsp_responder"),
237       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
238       ngx_conf_set_str_slot,
239       NGX_HTTP_SRV_CONF_OFFSET,
240       offsetof(ngx_http_ssl_srv_conf_t, ocsp_responder),
241       NULL },
242 
243     { ngx_string("ssl_ocsp_cache"),
244       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
245       ngx_http_ssl_ocsp_cache,
246       NGX_HTTP_SRV_CONF_OFFSET,
247       0,
248       NULL },
249 
250     { ngx_string("ssl_stapling"),
251       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
252       ngx_conf_set_flag_slot,
253       NGX_HTTP_SRV_CONF_OFFSET,
254       offsetof(ngx_http_ssl_srv_conf_t, stapling),
255       NULL },
256 
257     { ngx_string("ssl_stapling_file"),
258       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
259       ngx_conf_set_str_slot,
260       NGX_HTTP_SRV_CONF_OFFSET,
261       offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
262       NULL },
263 
264     { ngx_string("ssl_stapling_responder"),
265       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
266       ngx_conf_set_str_slot,
267       NGX_HTTP_SRV_CONF_OFFSET,
268       offsetof(ngx_http_ssl_srv_conf_t, stapling_responder),
269       NULL },
270 
271     { ngx_string("ssl_stapling_verify"),
272       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
273       ngx_conf_set_flag_slot,
274       NGX_HTTP_SRV_CONF_OFFSET,
275       offsetof(ngx_http_ssl_srv_conf_t, stapling_verify),
276       NULL },
277 
278     { ngx_string("ssl_early_data"),
279       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
280       ngx_conf_set_flag_slot,
281       NGX_HTTP_SRV_CONF_OFFSET,
282       offsetof(ngx_http_ssl_srv_conf_t, early_data),
283       NULL },
284 
285     { ngx_string("ssl_conf_command"),
286       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
287       ngx_conf_set_keyval_slot,
288       NGX_HTTP_SRV_CONF_OFFSET,
289       offsetof(ngx_http_ssl_srv_conf_t, conf_commands),
290       &ngx_http_ssl_conf_command_post },
291 
292     { ngx_string("ssl_reject_handshake"),
293       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
294       ngx_conf_set_flag_slot,
295       NGX_HTTP_SRV_CONF_OFFSET,
296       offsetof(ngx_http_ssl_srv_conf_t, reject_handshake),
297       NULL },
298 
299       ngx_null_command
300 };
301 
302 
303 static ngx_http_module_t  ngx_http_ssl_module_ctx = {
304     ngx_http_ssl_add_variables,            /* preconfiguration */
305     ngx_http_ssl_init,                     /* postconfiguration */
306 
307     NULL,                                  /* create main configuration */
308     NULL,                                  /* init main configuration */
309 
310     ngx_http_ssl_create_srv_conf,          /* create server configuration */
311     ngx_http_ssl_merge_srv_conf,           /* merge server configuration */
312 
313     NULL,                                  /* create location configuration */
314     NULL                                   /* merge location configuration */
315 };
316 
317 
318 ngx_module_t  ngx_http_ssl_module = {
319     NGX_MODULE_V1,
320     &ngx_http_ssl_module_ctx,              /* module context */
321     ngx_http_ssl_commands,                 /* module directives */
322     NGX_HTTP_MODULE,                       /* module type */
323     NULL,                                  /* init master */
324     NULL,                                  /* init module */
325     NULL,                                  /* init process */
326     NULL,                                  /* init thread */
327     NULL,                                  /* exit thread */
328     NULL,                                  /* exit process */
329     NULL,                                  /* exit master */
330     NGX_MODULE_V1_PADDING
331 };
332 
333 
334 static ngx_http_variable_t  ngx_http_ssl_vars[] = {
335 
336     { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
337       (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
338 
339     { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
340       (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
341 
342     { ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable,
343       (uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 },
344 
345     { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable,
346       (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 },
347 
348     { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
349       (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
350 
351     { ngx_string("ssl_session_reused"), NULL, ngx_http_ssl_variable,
352       (uintptr_t) ngx_ssl_get_session_reused, NGX_HTTP_VAR_CHANGEABLE, 0 },
353 
354     { ngx_string("ssl_early_data"), NULL, ngx_http_ssl_variable,
355       (uintptr_t) ngx_ssl_get_early_data,
356       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
357 
358     { ngx_string("ssl_server_name"), NULL, ngx_http_ssl_variable,
359       (uintptr_t) ngx_ssl_get_server_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
360 
361     { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
362       (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
363 
364     { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
365       (uintptr_t) ngx_ssl_get_raw_certificate,
366       NGX_HTTP_VAR_CHANGEABLE, 0 },
367 
368     { ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable,
369       (uintptr_t) ngx_ssl_get_escaped_certificate,
370       NGX_HTTP_VAR_CHANGEABLE, 0 },
371 
372     { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
373       (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
374 
375     { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
376       (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
377 
378     { ngx_string("ssl_client_s_dn_legacy"), NULL, ngx_http_ssl_variable,
379       (uintptr_t) ngx_ssl_get_subject_dn_legacy, NGX_HTTP_VAR_CHANGEABLE, 0 },
380 
381     { ngx_string("ssl_client_i_dn_legacy"), NULL, ngx_http_ssl_variable,
382       (uintptr_t) ngx_ssl_get_issuer_dn_legacy, NGX_HTTP_VAR_CHANGEABLE, 0 },
383 
384     { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
385       (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },
386 
387     { ngx_string("ssl_client_fingerprint"), NULL, ngx_http_ssl_variable,
388       (uintptr_t) ngx_ssl_get_fingerprint, NGX_HTTP_VAR_CHANGEABLE, 0 },
389 
390     { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable,
391       (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 },
392 
393     { ngx_string("ssl_client_v_start"), NULL, ngx_http_ssl_variable,
394       (uintptr_t) ngx_ssl_get_client_v_start, NGX_HTTP_VAR_CHANGEABLE, 0 },
395 
396     { ngx_string("ssl_client_v_end"), NULL, ngx_http_ssl_variable,
397       (uintptr_t) ngx_ssl_get_client_v_end, NGX_HTTP_VAR_CHANGEABLE, 0 },
398 
399     { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,
400       (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },
401 
402       ngx_http_null_variable
403 };
404 
405 
406 static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
407 
408 
409 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
410 
411 static int
412 ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
413     unsigned char *outlen, const unsigned char *in, unsigned int inlen,
414     void *arg)
415 {
416     unsigned int            srvlen;
417     unsigned char          *srv;
418 #if (NGX_DEBUG)
419     unsigned int            i;
420 #endif
421 #if (NGX_HTTP_V2)
422     ngx_http_connection_t  *hc;
423 #endif
424 #if (NGX_HTTP_V2 || NGX_DEBUG)
425     ngx_connection_t       *c;
426 
427     c = ngx_ssl_get_connection(ssl_conn);
428 #endif
429 
430 #if (NGX_DEBUG)
431     for (i = 0; i < inlen; i += in[i] + 1) {
432         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
433                        "SSL ALPN supported by client: %*s",
434                        (size_t) in[i], &in[i + 1]);
435     }
436 #endif
437 
438 #if (NGX_HTTP_V2)
439     hc = c->data;
440 
441     if (hc->addr_conf->http2) {
442         srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTO;
443         srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTO) - 1;
444 
445     } else
446 #endif
447     {
448         srv = (unsigned char *) NGX_HTTP_ALPN_PROTO;
449         srvlen = sizeof(NGX_HTTP_ALPN_PROTO) - 1;
450     }
451 
452     if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
453                               in, inlen)
454         != OPENSSL_NPN_NEGOTIATED)
455     {
456         return SSL_TLSEXT_ERR_NOACK;
457     }
458 
459     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
460                    "SSL ALPN selected: %*s", (size_t) *outlen, *out);
461 
462     return SSL_TLSEXT_ERR_OK;
463 }
464 
465 #endif
466 
467 
468 static ngx_int_t
469 ngx_http_ssl_static_variable(ngx_http_request_t *r,
470     ngx_http_variable_value_t *v, uintptr_t data)
471 {
472     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
473 
474     size_t     len;
475     ngx_str_t  s;
476 
477     if (r->connection->ssl) {
478 
479         (void) handler(r->connection, NULL, &s);
480 
481         v->data = s.data;
482 
483         for (len = 0; v->data[len]; len++) { /* void */ }
484 
485         v->len = len;
486         v->valid = 1;
487         v->no_cacheable = 0;
488         v->not_found = 0;
489 
490         return NGX_OK;
491     }
492 
493     v->not_found = 1;
494 
495     return NGX_OK;
496 }
497 
498 
499 static ngx_int_t
500 ngx_http_ssl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
501     uintptr_t data)
502 {
503     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
504 
505     ngx_str_t  s;
506 
507     if (r->connection->ssl) {
508 
509         if (handler(r->connection, r->pool, &s) != NGX_OK) {
510             return NGX_ERROR;
511         }
512 
513         v->len = s.len;
514         v->data = s.data;
515 
516         if (v->len) {
517             v->valid = 1;
518             v->no_cacheable = 0;
519             v->not_found = 0;
520 
521             return NGX_OK;
522         }
523     }
524 
525     v->not_found = 1;
526 
527     return NGX_OK;
528 }
529 
530 
531 static ngx_int_t
532 ngx_http_ssl_add_variables(ngx_conf_t *cf)
533 {
534     ngx_http_variable_t  *var, *v;
535 
536     for (v = ngx_http_ssl_vars; v->name.len; v++) {
537         var = ngx_http_add_variable(cf, &v->name, v->flags);
538         if (var == NULL) {
539             return NGX_ERROR;
540         }
541 
542         var->get_handler = v->get_handler;
543         var->data = v->data;
544     }
545 
546     return NGX_OK;
547 }
548 
549 
550 static void *
551 ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
552 {
553     ngx_http_ssl_srv_conf_t  *sscf;
554 
555     sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
556     if (sscf == NULL) {
557         return NULL;
558     }
559 
560     /*
561      * set by ngx_pcalloc():
562      *
563      *     sscf->protocols = 0;
564      *     sscf->certificate_values = NULL;
565      *     sscf->dhparam = { 0, NULL };
566      *     sscf->ecdh_curve = { 0, NULL };
567      *     sscf->client_certificate = { 0, NULL };
568      *     sscf->trusted_certificate = { 0, NULL };
569      *     sscf->crl = { 0, NULL };
570      *     sscf->ciphers = { 0, NULL };
571      *     sscf->shm_zone = NULL;
572      *     sscf->ocsp_responder = { 0, NULL };
573      *     sscf->stapling_file = { 0, NULL };
574      *     sscf->stapling_responder = { 0, NULL };
575      */
576 
577     sscf->enable = NGX_CONF_UNSET;
578     sscf->prefer_server_ciphers = NGX_CONF_UNSET;
579     sscf->early_data = NGX_CONF_UNSET;
580     sscf->reject_handshake = NGX_CONF_UNSET;
581     sscf->buffer_size = NGX_CONF_UNSET_SIZE;
582     sscf->verify = NGX_CONF_UNSET_UINT;
583     sscf->verify_depth = NGX_CONF_UNSET_UINT;
584     sscf->certificates = NGX_CONF_UNSET_PTR;
585     sscf->certificate_keys = NGX_CONF_UNSET_PTR;
586     sscf->passwords = NGX_CONF_UNSET_PTR;
587     sscf->conf_commands = NGX_CONF_UNSET_PTR;
588     sscf->builtin_session_cache = NGX_CONF_UNSET;
589     sscf->session_timeout = NGX_CONF_UNSET;
590     sscf->session_tickets = NGX_CONF_UNSET;
591     sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
592     sscf->ocsp = NGX_CONF_UNSET_UINT;
593     sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR;
594     sscf->stapling = NGX_CONF_UNSET;
595     sscf->stapling_verify = NGX_CONF_UNSET;
596 
597     return sscf;
598 }
599 
600 
601 static char *
602 ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
603 {
604     ngx_http_ssl_srv_conf_t *prev = parent;
605     ngx_http_ssl_srv_conf_t *conf = child;
606 
607     ngx_pool_cleanup_t  *cln;
608 
609     if (conf->enable == NGX_CONF_UNSET) {
610         if (prev->enable == NGX_CONF_UNSET) {
611             conf->enable = 0;
612 
613         } else {
614             conf->enable = prev->enable;
615             conf->file = prev->file;
616             conf->line = prev->line;
617         }
618     }
619 
620     ngx_conf_merge_value(conf->session_timeout,
621                          prev->session_timeout, 300);
622 
623     ngx_conf_merge_value(conf->prefer_server_ciphers,
624                          prev->prefer_server_ciphers, 0);
625 
626     ngx_conf_merge_value(conf->early_data, prev->early_data, 0);
627     ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
628 
629     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
630                          (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
631                           |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
632 
633     ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
634                          NGX_SSL_BUFSIZE);
635 
636     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
637     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
638 
639     ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
640     ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
641                          NULL);
642 
643     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
644 
645     ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
646 
647     ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
648                          "");
649     ngx_conf_merge_str_value(conf->trusted_certificate,
650                          prev->trusted_certificate, "");
651     ngx_conf_merge_str_value(conf->crl, prev->crl, "");
652 
653     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
654                          NGX_DEFAULT_ECDH_CURVE);
655 
656     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
657 
658     ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
659 
660     ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0);
661     ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, "");
662     ngx_conf_merge_ptr_value(conf->ocsp_cache_zone,
663                          prev->ocsp_cache_zone, NULL);
664 
665     ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
666     ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
667     ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
668     ngx_conf_merge_str_value(conf->stapling_responder,
669                          prev->stapling_responder, "");
670 
671     conf->ssl.log = cf->log;
672 
673     if (conf->enable) {
674 
675         if (conf->certificates) {
676             if (conf->certificate_keys == NULL) {
677                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
678                               "no \"ssl_certificate_key\" is defined for "
679                               "the \"ssl\" directive in %s:%ui",
680                               conf->file, conf->line);
681                 return NGX_CONF_ERROR;
682             }
683 
684             if (conf->certificate_keys->nelts < conf->certificates->nelts) {
685                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
686                               "no \"ssl_certificate_key\" is defined "
687                               "for certificate \"%V\" and "
688                               "the \"ssl\" directive in %s:%ui",
689                               ((ngx_str_t *) conf->certificates->elts)
690                               + conf->certificates->nelts - 1,
691                               conf->file, conf->line);
692                 return NGX_CONF_ERROR;
693             }
694 
695         } else if (!conf->reject_handshake) {
696             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
697                           "no \"ssl_certificate\" is defined for "
698                           "the \"ssl\" directive in %s:%ui",
699                           conf->file, conf->line);
700             return NGX_CONF_ERROR;
701         }
702 
703     } else if (conf->certificates) {
704 
705         if (conf->certificate_keys == NULL
706             || conf->certificate_keys->nelts < conf->certificates->nelts)
707         {
708             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
709                           "no \"ssl_certificate_key\" is defined "
710                           "for certificate \"%V\"",
711                           ((ngx_str_t *) conf->certificates->elts)
712                           + conf->certificates->nelts - 1);
713             return NGX_CONF_ERROR;
714         }
715 
716     } else if (!conf->reject_handshake) {
717         return NGX_CONF_OK;
718     }
719 
720     if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
721         return NGX_CONF_ERROR;
722     }
723 
724     cln = ngx_pool_cleanup_add(cf->pool, 0);
725     if (cln == NULL) {
726         ngx_ssl_cleanup_ctx(&conf->ssl);
727         return NGX_CONF_ERROR;
728     }
729 
730     cln->handler = ngx_ssl_cleanup_ctx;
731     cln->data = &conf->ssl;
732 
733 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
734 
735     if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
736                                                ngx_http_ssl_servername)
737         == 0)
738     {
739         ngx_log_error(NGX_LOG_WARN, cf->log, 0,
740             "nginx was built with SNI support, however, now it is linked "
741             "dynamically to an OpenSSL library which has no tlsext support, "
742             "therefore SNI is not available");
743     }
744 
745 #endif
746 
747 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
748     SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL);
749 #endif
750 
751     if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
752                         conf->prefer_server_ciphers)
753         != NGX_OK)
754     {
755         return NGX_CONF_ERROR;
756     }
757 
758     if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) {
759         return NGX_CONF_ERROR;
760     }
761 
762     if (conf->certificate_values) {
763 
764 #ifdef SSL_R_CERT_CB_ERROR
765 
766         /* install callback to lookup certificates */
767 
768         SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, conf);
769 
770 #else
771         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
772                       "variables in "
773                       "\"ssl_certificate\" and \"ssl_certificate_key\" "
774                       "directives are not supported on this platform");
775         return NGX_CONF_ERROR;
776 #endif
777 
778     } else if (conf->certificates) {
779 
780         /* configure certificates */
781 
782         if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
783                                  conf->certificate_keys, conf->passwords)
784             != NGX_OK)
785         {
786             return NGX_CONF_ERROR;
787         }
788     }
789 
790     conf->ssl.buffer_size = conf->buffer_size;
791 
792     if (conf->verify) {
793 
794         if (conf->client_certificate.len == 0 && conf->verify != 3) {
795             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
796                           "no ssl_client_certificate for ssl_verify_client");
797             return NGX_CONF_ERROR;
798         }
799 
800         if (ngx_ssl_client_certificate(cf, &conf->ssl,
801                                        &conf->client_certificate,
802                                        conf->verify_depth)
803             != NGX_OK)
804         {
805             return NGX_CONF_ERROR;
806         }
807     }
808 
809     if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
810                                     &conf->trusted_certificate,
811                                     conf->verify_depth)
812         != NGX_OK)
813     {
814         return NGX_CONF_ERROR;
815     }
816 
817     if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
818         return NGX_CONF_ERROR;
819     }
820 
821     if (conf->ocsp) {
822 
823         if (conf->verify == 3) {
824             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
825                           "\"ssl_ocsp\" is incompatible with "
826                           "\"ssl_verify_client optional_no_ca\"");
827             return NGX_CONF_ERROR;
828         }
829 
830         if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp,
831                          conf->ocsp_cache_zone)
832             != NGX_OK)
833         {
834             return NGX_CONF_ERROR;
835         }
836     }
837 
838     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
839         return NGX_CONF_ERROR;
840     }
841 
842     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
843         return NGX_CONF_ERROR;
844     }
845 
846     ngx_conf_merge_value(conf->builtin_session_cache,
847                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
848 
849     if (conf->shm_zone == NULL) {
850         conf->shm_zone = prev->shm_zone;
851     }
852 
853     if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
854                               conf->certificates, conf->builtin_session_cache,
855                               conf->shm_zone, conf->session_timeout)
856         != NGX_OK)
857     {
858         return NGX_CONF_ERROR;
859     }
860 
861     ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1);
862 
863 #ifdef SSL_OP_NO_TICKET
864     if (!conf->session_tickets) {
865         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
866     }
867 #endif
868 
869     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
870                          prev->session_ticket_keys, NULL);
871 
872     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
873         != NGX_OK)
874     {
875         return NGX_CONF_ERROR;
876     }
877 
878     if (conf->stapling) {
879 
880         if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
881                              &conf->stapling_responder, conf->stapling_verify)
882             != NGX_OK)
883         {
884             return NGX_CONF_ERROR;
885         }
886 
887     }
888 
889     if (ngx_ssl_early_data(cf, &conf->ssl, conf->early_data) != NGX_OK) {
890         return NGX_CONF_ERROR;
891     }
892 
893     if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
894         return NGX_CONF_ERROR;
895     }
896 
897     return NGX_CONF_OK;
898 }
899 
900 
901 static ngx_int_t
902 ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
903     ngx_http_ssl_srv_conf_t *conf)
904 {
905     ngx_str_t                         *cert, *key;
906     ngx_uint_t                         i, nelts;
907     ngx_http_complex_value_t          *cv;
908     ngx_http_compile_complex_value_t   ccv;
909 
910     if (conf->certificates == NULL) {
911         return NGX_OK;
912     }
913 
914     cert = conf->certificates->elts;
915     key = conf->certificate_keys->elts;
916     nelts = conf->certificates->nelts;
917 
918     for (i = 0; i < nelts; i++) {
919 
920         if (ngx_http_script_variables_count(&cert[i])) {
921             goto found;
922         }
923 
924         if (ngx_http_script_variables_count(&key[i])) {
925             goto found;
926         }
927     }
928 
929     return NGX_OK;
930 
931 found:
932 
933     conf->certificate_values = ngx_array_create(cf->pool, nelts,
934                                              sizeof(ngx_http_complex_value_t));
935     if (conf->certificate_values == NULL) {
936         return NGX_ERROR;
937     }
938 
939     conf->certificate_key_values = ngx_array_create(cf->pool, nelts,
940                                              sizeof(ngx_http_complex_value_t));
941     if (conf->certificate_key_values == NULL) {
942         return NGX_ERROR;
943     }
944 
945     for (i = 0; i < nelts; i++) {
946 
947         cv = ngx_array_push(conf->certificate_values);
948         if (cv == NULL) {
949             return NGX_ERROR;
950         }
951 
952         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
953 
954         ccv.cf = cf;
955         ccv.value = &cert[i];
956         ccv.complex_value = cv;
957         ccv.zero = 1;
958 
959         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
960             return NGX_ERROR;
961         }
962 
963         cv = ngx_array_push(conf->certificate_key_values);
964         if (cv == NULL) {
965             return NGX_ERROR;
966         }
967 
968         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
969 
970         ccv.cf = cf;
971         ccv.value = &key[i];
972         ccv.complex_value = cv;
973         ccv.zero = 1;
974 
975         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
976             return NGX_ERROR;
977         }
978     }
979 
980     conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords);
981     if (conf->passwords == NULL) {
982         return NGX_ERROR;
983     }
984 
985     return NGX_OK;
986 }
987 
988 
989 static char *
990 ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
991 {
992     ngx_http_ssl_srv_conf_t *sscf = conf;
993 
994     char  *rv;
995 
996     rv = ngx_conf_set_flag_slot(cf, cmd, conf);
997 
998     if (rv != NGX_CONF_OK) {
999         return rv;
1000     }
1001 
1002     sscf->file = cf->conf_file->file.name.data;
1003     sscf->line = cf->conf_file->line;
1004 
1005     return NGX_CONF_OK;
1006 }
1007 
1008 
1009 static char *
1010 ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1011 {
1012     ngx_http_ssl_srv_conf_t *sscf = conf;
1013 
1014     ngx_str_t  *value;
1015 
1016     if (sscf->passwords != NGX_CONF_UNSET_PTR) {
1017         return "is duplicate";
1018     }
1019 
1020     value = cf->args->elts;
1021 
1022     sscf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
1023 
1024     if (sscf->passwords == NULL) {
1025         return NGX_CONF_ERROR;
1026     }
1027 
1028     return NGX_CONF_OK;
1029 }
1030 
1031 
1032 static char *
1033 ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1034 {
1035     ngx_http_ssl_srv_conf_t *sscf = conf;
1036 
1037     size_t       len;
1038     ngx_str_t   *value, name, size;
1039     ngx_int_t    n;
1040     ngx_uint_t   i, j;
1041 
1042     value = cf->args->elts;
1043 
1044     for (i = 1; i < cf->args->nelts; i++) {
1045 
1046         if (ngx_strcmp(value[i].data, "off") == 0) {
1047             sscf->builtin_session_cache = NGX_SSL_NO_SCACHE;
1048             continue;
1049         }
1050 
1051         if (ngx_strcmp(value[i].data, "none") == 0) {
1052             sscf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
1053             continue;
1054         }
1055 
1056         if (ngx_strcmp(value[i].data, "builtin") == 0) {
1057             sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
1058             continue;
1059         }
1060 
1061         if (value[i].len > sizeof("builtin:") - 1
1062             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
1063                == 0)
1064         {
1065             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
1066                          value[i].len - (sizeof("builtin:") - 1));
1067 
1068             if (n == NGX_ERROR) {
1069                 goto invalid;
1070             }
1071 
1072             sscf->builtin_session_cache = n;
1073 
1074             continue;
1075         }
1076 
1077         if (value[i].len > sizeof("shared:") - 1
1078             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
1079                == 0)
1080         {
1081             len = 0;
1082 
1083             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
1084                 if (value[i].data[j] == ':') {
1085                     break;
1086                 }
1087 
1088                 len++;
1089             }
1090 
1091             if (len == 0) {
1092                 goto invalid;
1093             }
1094 
1095             name.len = len;
1096             name.data = value[i].data + sizeof("shared:") - 1;
1097 
1098             size.len = value[i].len - j - 1;
1099             size.data = name.data + len + 1;
1100 
1101             n = ngx_parse_size(&size);
1102 
1103             if (n == NGX_ERROR) {
1104                 goto invalid;
1105             }
1106 
1107             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
1108                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1109                                    "session cache \"%V\" is too small",
1110                                    &value[i]);
1111 
1112                 return NGX_CONF_ERROR;
1113             }
1114 
1115             sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
1116                                                    &ngx_http_ssl_module);
1117             if (sscf->shm_zone == NULL) {
1118                 return NGX_CONF_ERROR;
1119             }
1120 
1121             sscf->shm_zone->init = ngx_ssl_session_cache_init;
1122 
1123             continue;
1124         }
1125 
1126         goto invalid;
1127     }
1128 
1129     if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
1130         sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
1131     }
1132 
1133     return NGX_CONF_OK;
1134 
1135 invalid:
1136 
1137     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1138                        "invalid session cache \"%V\"", &value[i]);
1139 
1140     return NGX_CONF_ERROR;
1141 }
1142 
1143 
1144 static char *
1145 ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1146 {
1147     ngx_http_ssl_srv_conf_t *sscf = conf;
1148 
1149     size_t       len;
1150     ngx_int_t    n;
1151     ngx_str_t   *value, name, size;
1152     ngx_uint_t   j;
1153 
1154     if (sscf->ocsp_cache_zone != NGX_CONF_UNSET_PTR) {
1155         return "is duplicate";
1156     }
1157 
1158     value = cf->args->elts;
1159 
1160     if (ngx_strcmp(value[1].data, "off") == 0) {
1161         sscf->ocsp_cache_zone = NULL;
1162         return NGX_CONF_OK;
1163     }
1164 
1165     if (value[1].len <= sizeof("shared:") - 1
1166         || ngx_strncmp(value[1].data, "shared:", sizeof("shared:") - 1) != 0)
1167     {
1168         goto invalid;
1169     }
1170 
1171     len = 0;
1172 
1173     for (j = sizeof("shared:") - 1; j < value[1].len; j++) {
1174         if (value[1].data[j] == ':') {
1175             break;
1176         }
1177 
1178         len++;
1179     }
1180 
1181     if (len == 0) {
1182         goto invalid;
1183     }
1184 
1185     name.len = len;
1186     name.data = value[1].data + sizeof("shared:") - 1;
1187 
1188     size.len = value[1].len - j - 1;
1189     size.data = name.data + len + 1;
1190 
1191     n = ngx_parse_size(&size);
1192 
1193     if (n == NGX_ERROR) {
1194         goto invalid;
1195     }
1196 
1197     if (n < (ngx_int_t) (8 * ngx_pagesize)) {
1198         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1199                            "OCSP cache \"%V\" is too small", &value[1]);
1200 
1201         return NGX_CONF_ERROR;
1202     }
1203 
1204     sscf->ocsp_cache_zone = ngx_shared_memory_add(cf, &name, n,
1205                                                   &ngx_http_ssl_module_ctx);
1206     if (sscf->ocsp_cache_zone == NULL) {
1207         return NGX_CONF_ERROR;
1208     }
1209 
1210     sscf->ocsp_cache_zone->init = ngx_ssl_ocsp_cache_init;
1211 
1212     return NGX_CONF_OK;
1213 
1214 invalid:
1215 
1216     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1217                        "invalid OCSP cache \"%V\"", &value[1]);
1218 
1219     return NGX_CONF_ERROR;
1220 }
1221 
1222 
1223 static char *
1224 ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
1225 {
1226 #ifndef SSL_CONF_FLAG_FILE
1227     return "is not supported on this platform";
1228 #else
1229     return NGX_CONF_OK;
1230 #endif
1231 }
1232 
1233 
1234 static ngx_int_t
1235 ngx_http_ssl_init(ngx_conf_t *cf)
1236 {
1237     ngx_uint_t                   a, p, s;
1238     ngx_http_conf_addr_t        *addr;
1239     ngx_http_conf_port_t        *port;
1240     ngx_http_ssl_srv_conf_t     *sscf;
1241     ngx_http_core_loc_conf_t    *clcf;
1242     ngx_http_core_srv_conf_t   **cscfp, *cscf;
1243     ngx_http_core_main_conf_t   *cmcf;
1244 
1245     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1246     cscfp = cmcf->servers.elts;
1247 
1248     for (s = 0; s < cmcf->servers.nelts; s++) {
1249 
1250         sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
1251 
1252         if (sscf->ssl.ctx == NULL) {
1253             continue;
1254         }
1255 
1256         clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
1257 
1258         if (sscf->stapling) {
1259             if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
1260                                           clcf->resolver_timeout)
1261                 != NGX_OK)
1262             {
1263                 return NGX_ERROR;
1264             }
1265         }
1266 
1267         if (sscf->ocsp) {
1268             if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, clcf->resolver,
1269                                       clcf->resolver_timeout)
1270                 != NGX_OK)
1271             {
1272                 return NGX_ERROR;
1273             }
1274         }
1275     }
1276 
1277     if (cmcf->ports == NULL) {
1278         return NGX_OK;
1279     }
1280 
1281     port = cmcf->ports->elts;
1282     for (p = 0; p < cmcf->ports->nelts; p++) {
1283 
1284         addr = port[p].addrs.elts;
1285         for (a = 0; a < port[p].addrs.nelts; a++) {
1286 
1287             if (!addr[a].opt.ssl) {
1288                 continue;
1289             }
1290 
1291             cscf = addr[a].default_server;
1292             sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
1293 
1294             if (sscf->certificates) {
1295                 continue;
1296             }
1297 
1298             if (!sscf->reject_handshake) {
1299                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1300                               "no \"ssl_certificate\" is defined for "
1301                               "the \"listen ... ssl\" directive in %s:%ui",
1302                               cscf->file_name, cscf->line);
1303                 return NGX_ERROR;
1304             }
1305 
1306             /*
1307              * if no certificates are defined in the default server,
1308              * check all non-default server blocks
1309              */
1310 
1311             cscfp = addr[a].servers.elts;
1312             for (s = 0; s < addr[a].servers.nelts; s++) {
1313 
1314                 cscf = cscfp[s];
1315                 sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
1316 
1317                 if (sscf->certificates || sscf->reject_handshake) {
1318                     continue;
1319                 }
1320 
1321                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1322                               "no \"ssl_certificate\" is defined for "
1323                               "the \"listen ... ssl\" directive in %s:%ui",
1324                               cscf->file_name, cscf->line);
1325                 return NGX_ERROR;
1326             }
1327         }
1328     }
1329 
1330     return NGX_OK;
1331 }
1332