ngx_http_ssl_module.c revision e18a033b
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
13typedef 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_NPN_ADVERTISE  "\x08http/1.1"
21
22
23#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
24static 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#ifdef TLSEXT_TYPE_next_proto_neg
30static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
31    const unsigned char **out, unsigned int *outlen, void *arg);
32#endif
33
34static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
35    ngx_http_variable_value_t *v, uintptr_t data);
36static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
37    ngx_http_variable_value_t *v, uintptr_t data);
38
39static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
40static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
41static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
42    void *parent, void *child);
43
44static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
45    void *conf);
46static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
47    void *conf);
48static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
49    void *conf);
50
51static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
52
53
54static ngx_conf_bitmask_t  ngx_http_ssl_protocols[] = {
55    { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
56    { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
57    { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
58    { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
59    { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
60    { ngx_null_string, 0 }
61};
62
63
64static ngx_conf_enum_t  ngx_http_ssl_verify[] = {
65    { ngx_string("off"), 0 },
66    { ngx_string("on"), 1 },
67    { ngx_string("optional"), 2 },
68    { ngx_string("optional_no_ca"), 3 },
69    { ngx_null_string, 0 }
70};
71
72
73static ngx_command_t  ngx_http_ssl_commands[] = {
74
75    { ngx_string("ssl"),
76      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
77      ngx_http_ssl_enable,
78      NGX_HTTP_SRV_CONF_OFFSET,
79      offsetof(ngx_http_ssl_srv_conf_t, enable),
80      NULL },
81
82    { ngx_string("ssl_certificate"),
83      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
84      ngx_conf_set_str_array_slot,
85      NGX_HTTP_SRV_CONF_OFFSET,
86      offsetof(ngx_http_ssl_srv_conf_t, certificates),
87      NULL },
88
89    { ngx_string("ssl_certificate_key"),
90      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
91      ngx_conf_set_str_array_slot,
92      NGX_HTTP_SRV_CONF_OFFSET,
93      offsetof(ngx_http_ssl_srv_conf_t, certificate_keys),
94      NULL },
95
96    { ngx_string("ssl_password_file"),
97      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
98      ngx_http_ssl_password_file,
99      NGX_HTTP_SRV_CONF_OFFSET,
100      0,
101      NULL },
102
103    { ngx_string("ssl_dhparam"),
104      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
105      ngx_conf_set_str_slot,
106      NGX_HTTP_SRV_CONF_OFFSET,
107      offsetof(ngx_http_ssl_srv_conf_t, dhparam),
108      NULL },
109
110    { ngx_string("ssl_ecdh_curve"),
111      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
112      ngx_conf_set_str_slot,
113      NGX_HTTP_SRV_CONF_OFFSET,
114      offsetof(ngx_http_ssl_srv_conf_t, ecdh_curve),
115      NULL },
116
117    { ngx_string("ssl_protocols"),
118      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
119      ngx_conf_set_bitmask_slot,
120      NGX_HTTP_SRV_CONF_OFFSET,
121      offsetof(ngx_http_ssl_srv_conf_t, protocols),
122      &ngx_http_ssl_protocols },
123
124    { ngx_string("ssl_ciphers"),
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, ciphers),
129      NULL },
130
131    { ngx_string("ssl_buffer_size"),
132      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
133      ngx_conf_set_size_slot,
134      NGX_HTTP_SRV_CONF_OFFSET,
135      offsetof(ngx_http_ssl_srv_conf_t, buffer_size),
136      NULL },
137
138    { ngx_string("ssl_verify_client"),
139      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
140      ngx_conf_set_enum_slot,
141      NGX_HTTP_SRV_CONF_OFFSET,
142      offsetof(ngx_http_ssl_srv_conf_t, verify),
143      &ngx_http_ssl_verify },
144
145    { ngx_string("ssl_verify_depth"),
146      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
147      ngx_conf_set_num_slot,
148      NGX_HTTP_SRV_CONF_OFFSET,
149      offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
150      NULL },
151
152    { ngx_string("ssl_client_certificate"),
153      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
154      ngx_conf_set_str_slot,
155      NGX_HTTP_SRV_CONF_OFFSET,
156      offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
157      NULL },
158
159    { ngx_string("ssl_trusted_certificate"),
160      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
161      ngx_conf_set_str_slot,
162      NGX_HTTP_SRV_CONF_OFFSET,
163      offsetof(ngx_http_ssl_srv_conf_t, trusted_certificate),
164      NULL },
165
166    { ngx_string("ssl_prefer_server_ciphers"),
167      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
168      ngx_conf_set_flag_slot,
169      NGX_HTTP_SRV_CONF_OFFSET,
170      offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers),
171      NULL },
172
173    { ngx_string("ssl_session_cache"),
174      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
175      ngx_http_ssl_session_cache,
176      NGX_HTTP_SRV_CONF_OFFSET,
177      0,
178      NULL },
179
180    { ngx_string("ssl_session_tickets"),
181      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
182      ngx_conf_set_flag_slot,
183      NGX_HTTP_SRV_CONF_OFFSET,
184      offsetof(ngx_http_ssl_srv_conf_t, session_tickets),
185      NULL },
186
187    { ngx_string("ssl_session_ticket_key"),
188      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
189      ngx_conf_set_str_array_slot,
190      NGX_HTTP_SRV_CONF_OFFSET,
191      offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys),
192      NULL },
193
194    { ngx_string("ssl_session_timeout"),
195      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
196      ngx_conf_set_sec_slot,
197      NGX_HTTP_SRV_CONF_OFFSET,
198      offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
199      NULL },
200
201    { ngx_string("ssl_crl"),
202      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
203      ngx_conf_set_str_slot,
204      NGX_HTTP_SRV_CONF_OFFSET,
205      offsetof(ngx_http_ssl_srv_conf_t, crl),
206      NULL },
207
208    { ngx_string("ssl_stapling"),
209      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
210      ngx_conf_set_flag_slot,
211      NGX_HTTP_SRV_CONF_OFFSET,
212      offsetof(ngx_http_ssl_srv_conf_t, stapling),
213      NULL },
214
215    { ngx_string("ssl_stapling_file"),
216      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
217      ngx_conf_set_str_slot,
218      NGX_HTTP_SRV_CONF_OFFSET,
219      offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
220      NULL },
221
222    { ngx_string("ssl_stapling_responder"),
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, stapling_responder),
227      NULL },
228
229    { ngx_string("ssl_stapling_verify"),
230      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
231      ngx_conf_set_flag_slot,
232      NGX_HTTP_SRV_CONF_OFFSET,
233      offsetof(ngx_http_ssl_srv_conf_t, stapling_verify),
234      NULL },
235
236      ngx_null_command
237};
238
239
240static ngx_http_module_t  ngx_http_ssl_module_ctx = {
241    ngx_http_ssl_add_variables,            /* preconfiguration */
242    ngx_http_ssl_init,                     /* postconfiguration */
243
244    NULL,                                  /* create main configuration */
245    NULL,                                  /* init main configuration */
246
247    ngx_http_ssl_create_srv_conf,          /* create server configuration */
248    ngx_http_ssl_merge_srv_conf,           /* merge server configuration */
249
250    NULL,                                  /* create location configuration */
251    NULL                                   /* merge location configuration */
252};
253
254
255ngx_module_t  ngx_http_ssl_module = {
256    NGX_MODULE_V1,
257    &ngx_http_ssl_module_ctx,              /* module context */
258    ngx_http_ssl_commands,                 /* module directives */
259    NGX_HTTP_MODULE,                       /* module type */
260    NULL,                                  /* init master */
261    NULL,                                  /* init module */
262    NULL,                                  /* init process */
263    NULL,                                  /* init thread */
264    NULL,                                  /* exit thread */
265    NULL,                                  /* exit process */
266    NULL,                                  /* exit master */
267    NGX_MODULE_V1_PADDING
268};
269
270
271static ngx_http_variable_t  ngx_http_ssl_vars[] = {
272
273    { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
274      (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
275
276    { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
277      (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
278
279    { ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable,
280      (uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 },
281
282    { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable,
283      (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 },
284
285    { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
286      (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
287
288    { ngx_string("ssl_session_reused"), NULL, ngx_http_ssl_variable,
289      (uintptr_t) ngx_ssl_get_session_reused, NGX_HTTP_VAR_CHANGEABLE, 0 },
290
291    { ngx_string("ssl_server_name"), NULL, ngx_http_ssl_variable,
292      (uintptr_t) ngx_ssl_get_server_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
293
294    { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
295      (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
296
297    { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
298      (uintptr_t) ngx_ssl_get_raw_certificate,
299      NGX_HTTP_VAR_CHANGEABLE, 0 },
300
301    { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
302      (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
303
304    { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
305      (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
306
307    { ngx_string("ssl_client_s_dn_legacy"), NULL, ngx_http_ssl_variable,
308      (uintptr_t) ngx_ssl_get_subject_dn_legacy, NGX_HTTP_VAR_CHANGEABLE, 0 },
309
310    { ngx_string("ssl_client_i_dn_legacy"), NULL, ngx_http_ssl_variable,
311      (uintptr_t) ngx_ssl_get_issuer_dn_legacy, NGX_HTTP_VAR_CHANGEABLE, 0 },
312
313    { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
314      (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },
315
316    { ngx_string("ssl_client_fingerprint"), NULL, ngx_http_ssl_variable,
317      (uintptr_t) ngx_ssl_get_fingerprint, NGX_HTTP_VAR_CHANGEABLE, 0 },
318
319    { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable,
320      (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 },
321
322    { ngx_string("ssl_client_v_start"), NULL, ngx_http_ssl_variable,
323      (uintptr_t) ngx_ssl_get_client_v_start, NGX_HTTP_VAR_CHANGEABLE, 0 },
324
325    { ngx_string("ssl_client_v_end"), NULL, ngx_http_ssl_variable,
326      (uintptr_t) ngx_ssl_get_client_v_end, NGX_HTTP_VAR_CHANGEABLE, 0 },
327
328    { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,
329      (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },
330
331    { ngx_null_string, NULL, NULL, 0, 0, 0 }
332};
333
334
335static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
336
337
338#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
339
340static int
341ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
342    unsigned char *outlen, const unsigned char *in, unsigned int inlen,
343    void *arg)
344{
345    unsigned int            srvlen;
346    unsigned char          *srv;
347#if (NGX_DEBUG)
348    unsigned int            i;
349#endif
350#if (NGX_HTTP_V2)
351    ngx_http_connection_t  *hc;
352#endif
353#if (NGX_HTTP_V2 || NGX_DEBUG)
354    ngx_connection_t       *c;
355
356    c = ngx_ssl_get_connection(ssl_conn);
357#endif
358
359#if (NGX_DEBUG)
360    for (i = 0; i < inlen; i += in[i] + 1) {
361        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
362                       "SSL ALPN supported by client: %*s",
363                       (size_t) in[i], &in[i + 1]);
364    }
365#endif
366
367#if (NGX_HTTP_V2)
368    hc = c->data;
369
370    if (hc->addr_conf->http2) {
371        srv =
372           (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
373        srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
374
375    } else
376#endif
377    {
378        srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
379        srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
380    }
381
382    if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
383                              in, inlen)
384        != OPENSSL_NPN_NEGOTIATED)
385    {
386        return SSL_TLSEXT_ERR_NOACK;
387    }
388
389    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
390                   "SSL ALPN selected: %*s", (size_t) *outlen, *out);
391
392    return SSL_TLSEXT_ERR_OK;
393}
394
395#endif
396
397
398#ifdef TLSEXT_TYPE_next_proto_neg
399
400static int
401ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
402    const unsigned char **out, unsigned int *outlen, void *arg)
403{
404#if (NGX_HTTP_V2 || NGX_DEBUG)
405    ngx_connection_t  *c;
406
407    c = ngx_ssl_get_connection(ssl_conn);
408    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised");
409#endif
410
411#if (NGX_HTTP_V2)
412    {
413    ngx_http_connection_t  *hc;
414
415    hc = c->data;
416
417    if (hc->addr_conf->http2) {
418        *out =
419            (unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
420        *outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
421
422        return SSL_TLSEXT_ERR_OK;
423    }
424    }
425#endif
426
427    *out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
428    *outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
429
430    return SSL_TLSEXT_ERR_OK;
431}
432
433#endif
434
435
436static ngx_int_t
437ngx_http_ssl_static_variable(ngx_http_request_t *r,
438    ngx_http_variable_value_t *v, uintptr_t data)
439{
440    ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
441
442    size_t     len;
443    ngx_str_t  s;
444
445    if (r->connection->ssl) {
446
447        (void) handler(r->connection, NULL, &s);
448
449        v->data = s.data;
450
451        for (len = 0; v->data[len]; len++) { /* void */ }
452
453        v->len = len;
454        v->valid = 1;
455        v->no_cacheable = 0;
456        v->not_found = 0;
457
458        return NGX_OK;
459    }
460
461    v->not_found = 1;
462
463    return NGX_OK;
464}
465
466
467static ngx_int_t
468ngx_http_ssl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
469    uintptr_t data)
470{
471    ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
472
473    ngx_str_t  s;
474
475    if (r->connection->ssl) {
476
477        if (handler(r->connection, r->pool, &s) != NGX_OK) {
478            return NGX_ERROR;
479        }
480
481        v->len = s.len;
482        v->data = s.data;
483
484        if (v->len) {
485            v->valid = 1;
486            v->no_cacheable = 0;
487            v->not_found = 0;
488
489            return NGX_OK;
490        }
491    }
492
493    v->not_found = 1;
494
495    return NGX_OK;
496}
497
498
499static ngx_int_t
500ngx_http_ssl_add_variables(ngx_conf_t *cf)
501{
502    ngx_http_variable_t  *var, *v;
503
504    for (v = ngx_http_ssl_vars; v->name.len; v++) {
505        var = ngx_http_add_variable(cf, &v->name, v->flags);
506        if (var == NULL) {
507            return NGX_ERROR;
508        }
509
510        var->get_handler = v->get_handler;
511        var->data = v->data;
512    }
513
514    return NGX_OK;
515}
516
517
518static void *
519ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
520{
521    ngx_http_ssl_srv_conf_t  *sscf;
522
523    sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
524    if (sscf == NULL) {
525        return NULL;
526    }
527
528    /*
529     * set by ngx_pcalloc():
530     *
531     *     sscf->protocols = 0;
532     *     sscf->dhparam = { 0, NULL };
533     *     sscf->ecdh_curve = { 0, NULL };
534     *     sscf->client_certificate = { 0, NULL };
535     *     sscf->trusted_certificate = { 0, NULL };
536     *     sscf->crl = { 0, NULL };
537     *     sscf->ciphers = { 0, NULL };
538     *     sscf->shm_zone = NULL;
539     *     sscf->stapling_file = { 0, NULL };
540     *     sscf->stapling_responder = { 0, NULL };
541     */
542
543    sscf->enable = NGX_CONF_UNSET;
544    sscf->prefer_server_ciphers = NGX_CONF_UNSET;
545    sscf->buffer_size = NGX_CONF_UNSET_SIZE;
546    sscf->verify = NGX_CONF_UNSET_UINT;
547    sscf->verify_depth = NGX_CONF_UNSET_UINT;
548    sscf->certificates = NGX_CONF_UNSET_PTR;
549    sscf->certificate_keys = NGX_CONF_UNSET_PTR;
550    sscf->passwords = NGX_CONF_UNSET_PTR;
551    sscf->builtin_session_cache = NGX_CONF_UNSET;
552    sscf->session_timeout = NGX_CONF_UNSET;
553    sscf->session_tickets = NGX_CONF_UNSET;
554    sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
555    sscf->stapling = NGX_CONF_UNSET;
556    sscf->stapling_verify = NGX_CONF_UNSET;
557
558    return sscf;
559}
560
561
562static char *
563ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
564{
565    ngx_http_ssl_srv_conf_t *prev = parent;
566    ngx_http_ssl_srv_conf_t *conf = child;
567
568    ngx_pool_cleanup_t  *cln;
569
570    if (conf->enable == NGX_CONF_UNSET) {
571        if (prev->enable == NGX_CONF_UNSET) {
572            conf->enable = 0;
573
574        } else {
575            conf->enable = prev->enable;
576            conf->file = prev->file;
577            conf->line = prev->line;
578        }
579    }
580
581    ngx_conf_merge_value(conf->session_timeout,
582                         prev->session_timeout, 300);
583
584    ngx_conf_merge_value(conf->prefer_server_ciphers,
585                         prev->prefer_server_ciphers, 0);
586
587    ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
588                         (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
589                          |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
590
591    ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
592                         NGX_SSL_BUFSIZE);
593
594    ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
595    ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
596
597    ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
598    ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
599                         NULL);
600
601    ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
602
603    ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
604
605    ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
606                         "");
607    ngx_conf_merge_str_value(conf->trusted_certificate,
608                         prev->trusted_certificate, "");
609    ngx_conf_merge_str_value(conf->crl, prev->crl, "");
610
611    ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
612                         NGX_DEFAULT_ECDH_CURVE);
613
614    ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
615
616    ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
617    ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
618    ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
619    ngx_conf_merge_str_value(conf->stapling_responder,
620                         prev->stapling_responder, "");
621
622    conf->ssl.log = cf->log;
623
624    if (conf->enable) {
625
626        if (conf->certificates == NULL) {
627            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
628                          "no \"ssl_certificate\" is defined for "
629                          "the \"ssl\" directive in %s:%ui",
630                          conf->file, conf->line);
631            return NGX_CONF_ERROR;
632        }
633
634        if (conf->certificate_keys == NULL) {
635            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
636                          "no \"ssl_certificate_key\" is defined for "
637                          "the \"ssl\" directive in %s:%ui",
638                          conf->file, conf->line);
639            return NGX_CONF_ERROR;
640        }
641
642        if (conf->certificate_keys->nelts < conf->certificates->nelts) {
643            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
644                          "no \"ssl_certificate_key\" is defined "
645                          "for certificate \"%V\" and "
646                          "the \"ssl\" directive in %s:%ui",
647                          ((ngx_str_t *) conf->certificates->elts)
648                          + conf->certificates->nelts - 1,
649                          conf->file, conf->line);
650            return NGX_CONF_ERROR;
651        }
652
653    } else {
654
655        if (conf->certificates == NULL) {
656            return NGX_CONF_OK;
657        }
658
659        if (conf->certificate_keys == NULL
660            || conf->certificate_keys->nelts < conf->certificates->nelts)
661        {
662            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
663                          "no \"ssl_certificate_key\" is defined "
664                          "for certificate \"%V\"",
665                          ((ngx_str_t *) conf->certificates->elts)
666                          + conf->certificates->nelts - 1);
667            return NGX_CONF_ERROR;
668        }
669    }
670
671    if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
672        return NGX_CONF_ERROR;
673    }
674
675#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
676
677    if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
678                                               ngx_http_ssl_servername)
679        == 0)
680    {
681        ngx_log_error(NGX_LOG_WARN, cf->log, 0,
682            "nginx was built with SNI support, however, now it is linked "
683            "dynamically to an OpenSSL library which has no tlsext support, "
684            "therefore SNI is not available");
685    }
686
687#endif
688
689#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
690    SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL);
691#endif
692
693#ifdef TLSEXT_TYPE_next_proto_neg
694    SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx,
695                                          ngx_http_ssl_npn_advertised, NULL);
696#endif
697
698    cln = ngx_pool_cleanup_add(cf->pool, 0);
699    if (cln == NULL) {
700        return NGX_CONF_ERROR;
701    }
702
703    cln->handler = ngx_ssl_cleanup_ctx;
704    cln->data = &conf->ssl;
705
706    if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
707                             conf->certificate_keys, conf->passwords)
708        != NGX_OK)
709    {
710        return NGX_CONF_ERROR;
711    }
712
713    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
714                        conf->prefer_server_ciphers)
715        != NGX_OK)
716    {
717        return NGX_CONF_ERROR;
718    }
719
720    conf->ssl.buffer_size = conf->buffer_size;
721
722    if (conf->verify) {
723
724        if (conf->client_certificate.len == 0 && conf->verify != 3) {
725            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
726                          "no ssl_client_certificate for ssl_client_verify");
727            return NGX_CONF_ERROR;
728        }
729
730        if (ngx_ssl_client_certificate(cf, &conf->ssl,
731                                       &conf->client_certificate,
732                                       conf->verify_depth)
733            != NGX_OK)
734        {
735            return NGX_CONF_ERROR;
736        }
737    }
738
739    if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
740                                    &conf->trusted_certificate,
741                                    conf->verify_depth)
742        != NGX_OK)
743    {
744        return NGX_CONF_ERROR;
745    }
746
747    if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
748        return NGX_CONF_ERROR;
749    }
750
751    if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
752        return NGX_CONF_ERROR;
753    }
754
755    if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
756        return NGX_CONF_ERROR;
757    }
758
759    ngx_conf_merge_value(conf->builtin_session_cache,
760                         prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
761
762    if (conf->shm_zone == NULL) {
763        conf->shm_zone = prev->shm_zone;
764    }
765
766    if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
767                              conf->builtin_session_cache,
768                              conf->shm_zone, conf->session_timeout)
769        != NGX_OK)
770    {
771        return NGX_CONF_ERROR;
772    }
773
774    ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1);
775
776#ifdef SSL_OP_NO_TICKET
777    if (!conf->session_tickets) {
778        SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
779    }
780#endif
781
782    ngx_conf_merge_ptr_value(conf->session_ticket_keys,
783                         prev->session_ticket_keys, NULL);
784
785    if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
786        != NGX_OK)
787    {
788        return NGX_CONF_ERROR;
789    }
790
791    if (conf->stapling) {
792
793        if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
794                             &conf->stapling_responder, conf->stapling_verify)
795            != NGX_OK)
796        {
797            return NGX_CONF_ERROR;
798        }
799
800    }
801
802    return NGX_CONF_OK;
803}
804
805
806static char *
807ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
808{
809    ngx_http_ssl_srv_conf_t *sscf = conf;
810
811    char  *rv;
812
813    rv = ngx_conf_set_flag_slot(cf, cmd, conf);
814
815    if (rv != NGX_CONF_OK) {
816        return rv;
817    }
818
819    sscf->file = cf->conf_file->file.name.data;
820    sscf->line = cf->conf_file->line;
821
822    return NGX_CONF_OK;
823}
824
825
826static char *
827ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
828{
829    ngx_http_ssl_srv_conf_t *sscf = conf;
830
831    ngx_str_t  *value;
832
833    if (sscf->passwords != NGX_CONF_UNSET_PTR) {
834        return "is duplicate";
835    }
836
837    value = cf->args->elts;
838
839    sscf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
840
841    if (sscf->passwords == NULL) {
842        return NGX_CONF_ERROR;
843    }
844
845    return NGX_CONF_OK;
846}
847
848
849static char *
850ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
851{
852    ngx_http_ssl_srv_conf_t *sscf = conf;
853
854    size_t       len;
855    ngx_str_t   *value, name, size;
856    ngx_int_t    n;
857    ngx_uint_t   i, j;
858
859    value = cf->args->elts;
860
861    for (i = 1; i < cf->args->nelts; i++) {
862
863        if (ngx_strcmp(value[i].data, "off") == 0) {
864            sscf->builtin_session_cache = NGX_SSL_NO_SCACHE;
865            continue;
866        }
867
868        if (ngx_strcmp(value[i].data, "none") == 0) {
869            sscf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
870            continue;
871        }
872
873        if (ngx_strcmp(value[i].data, "builtin") == 0) {
874            sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
875            continue;
876        }
877
878        if (value[i].len > sizeof("builtin:") - 1
879            && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
880               == 0)
881        {
882            n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
883                         value[i].len - (sizeof("builtin:") - 1));
884
885            if (n == NGX_ERROR) {
886                goto invalid;
887            }
888
889            sscf->builtin_session_cache = n;
890
891            continue;
892        }
893
894        if (value[i].len > sizeof("shared:") - 1
895            && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
896               == 0)
897        {
898            len = 0;
899
900            for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
901                if (value[i].data[j] == ':') {
902                    break;
903                }
904
905                len++;
906            }
907
908            if (len == 0) {
909                goto invalid;
910            }
911
912            name.len = len;
913            name.data = value[i].data + sizeof("shared:") - 1;
914
915            size.len = value[i].len - j - 1;
916            size.data = name.data + len + 1;
917
918            n = ngx_parse_size(&size);
919
920            if (n == NGX_ERROR) {
921                goto invalid;
922            }
923
924            if (n < (ngx_int_t) (8 * ngx_pagesize)) {
925                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
926                                   "session cache \"%V\" is too small",
927                                   &value[i]);
928
929                return NGX_CONF_ERROR;
930            }
931
932            sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
933                                                   &ngx_http_ssl_module);
934            if (sscf->shm_zone == NULL) {
935                return NGX_CONF_ERROR;
936            }
937
938            sscf->shm_zone->init = ngx_ssl_session_cache_init;
939
940            continue;
941        }
942
943        goto invalid;
944    }
945
946    if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
947        sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
948    }
949
950    return NGX_CONF_OK;
951
952invalid:
953
954    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
955                       "invalid session cache \"%V\"", &value[i]);
956
957    return NGX_CONF_ERROR;
958}
959
960
961static ngx_int_t
962ngx_http_ssl_init(ngx_conf_t *cf)
963{
964    ngx_uint_t                   s;
965    ngx_http_ssl_srv_conf_t     *sscf;
966    ngx_http_core_loc_conf_t    *clcf;
967    ngx_http_core_srv_conf_t   **cscfp;
968    ngx_http_core_main_conf_t   *cmcf;
969
970    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
971    cscfp = cmcf->servers.elts;
972
973    for (s = 0; s < cmcf->servers.nelts; s++) {
974
975        sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
976
977        if (sscf->ssl.ctx == NULL || !sscf->stapling) {
978            continue;
979        }
980
981        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
982
983        if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
984                                      clcf->resolver_timeout)
985            != NGX_OK)
986        {
987            return NGX_ERROR;
988        }
989    }
990
991    return NGX_OK;
992}
993