Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_ssl_module.c
Go to the documentation of this file.
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 
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 "prime256v1"
19 
20 
21 #ifdef TLSEXT_TYPE_next_proto_neg
22 static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
23  const unsigned char **out, unsigned int *outlen, void *arg);
24 #endif
25 
26 static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
27  ngx_http_variable_value_t *v, uintptr_t data);
28 static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
29  ngx_http_variable_value_t *v, uintptr_t data);
30 
31 static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
32 static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
33 static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
34  void *parent, void *child);
35 
36 static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
37  void *conf);
38 static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
39  void *conf);
40 
41 static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
42 
43 
44 static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
45  { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
46  { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
47  { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
48  { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
49  { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
50  { ngx_null_string, 0 }
51 };
52 
53 
54 static ngx_conf_enum_t ngx_http_ssl_verify[] = {
55  { ngx_string("off"), 0 },
56  { ngx_string("on"), 1 },
57  { ngx_string("optional"), 2 },
58  { ngx_string("optional_no_ca"), 3 },
59  { ngx_null_string, 0 }
60 };
61 
62 
63 static ngx_command_t ngx_http_ssl_commands[] = {
64 
65  { ngx_string("ssl"),
67  ngx_http_ssl_enable,
69  offsetof(ngx_http_ssl_srv_conf_t, enable),
70  NULL },
71 
72  { ngx_string("ssl_certificate"),
76  offsetof(ngx_http_ssl_srv_conf_t, certificate),
77  NULL },
78 
79  { ngx_string("ssl_certificate_key"),
83  offsetof(ngx_http_ssl_srv_conf_t, certificate_key),
84  NULL },
85 
86  { ngx_string("ssl_dhparam"),
90  offsetof(ngx_http_ssl_srv_conf_t, dhparam),
91  NULL },
92 
93  { ngx_string("ssl_ecdh_curve"),
97  offsetof(ngx_http_ssl_srv_conf_t, ecdh_curve),
98  NULL },
99 
100  { ngx_string("ssl_protocols"),
104  offsetof(ngx_http_ssl_srv_conf_t, protocols),
105  &ngx_http_ssl_protocols },
106 
107  { ngx_string("ssl_ciphers"),
111  offsetof(ngx_http_ssl_srv_conf_t, ciphers),
112  NULL },
113 
114  { ngx_string("ssl_verify_client"),
118  offsetof(ngx_http_ssl_srv_conf_t, verify),
119  &ngx_http_ssl_verify },
120 
121  { ngx_string("ssl_verify_depth"),
125  offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
126  NULL },
127 
128  { ngx_string("ssl_client_certificate"),
132  offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
133  NULL },
134 
135  { ngx_string("ssl_trusted_certificate"),
139  offsetof(ngx_http_ssl_srv_conf_t, trusted_certificate),
140  NULL },
141 
142  { ngx_string("ssl_prefer_server_ciphers"),
146  offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers),
147  NULL },
148 
149  { ngx_string("ssl_session_cache"),
151  ngx_http_ssl_session_cache,
153  0,
154  NULL },
155 
156  { ngx_string("ssl_session_timeout"),
160  offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
161  NULL },
162 
163  { ngx_string("ssl_crl"),
167  offsetof(ngx_http_ssl_srv_conf_t, crl),
168  NULL },
169 
170  { ngx_string("ssl_stapling"),
174  offsetof(ngx_http_ssl_srv_conf_t, stapling),
175  NULL },
176 
177  { ngx_string("ssl_stapling_file"),
181  offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
182  NULL },
183 
184  { ngx_string("ssl_stapling_responder"),
188  offsetof(ngx_http_ssl_srv_conf_t, stapling_responder),
189  NULL },
190 
191  { ngx_string("ssl_stapling_verify"),
195  offsetof(ngx_http_ssl_srv_conf_t, stapling_verify),
196  NULL },
197 
199 };
200 
201 
202 static ngx_http_module_t ngx_http_ssl_module_ctx = {
203  ngx_http_ssl_add_variables, /* preconfiguration */
204  ngx_http_ssl_init, /* postconfiguration */
205 
206  NULL, /* create main configuration */
207  NULL, /* init main configuration */
208 
209  ngx_http_ssl_create_srv_conf, /* create server configuration */
210  ngx_http_ssl_merge_srv_conf, /* merge server configuration */
211 
212  NULL, /* create location configuration */
213  NULL /* merge location configuration */
214 };
215 
216 
219  &ngx_http_ssl_module_ctx, /* module context */
220  ngx_http_ssl_commands, /* module directives */
221  NGX_HTTP_MODULE, /* module type */
222  NULL, /* init master */
223  NULL, /* init module */
224  NULL, /* init process */
225  NULL, /* init thread */
226  NULL, /* exit thread */
227  NULL, /* exit process */
228  NULL, /* exit master */
230 };
231 
232 
233 static ngx_http_variable_t ngx_http_ssl_vars[] = {
234 
235  { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
237 
238  { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
240 
241  { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
243 
244  { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
246 
247  { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
248  (uintptr_t) ngx_ssl_get_raw_certificate,
250 
251  { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
253 
254  { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
256 
257  { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
259 
260  { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable,
262 
263  { ngx_null_string, NULL, NULL, 0, 0, 0 }
264 };
265 
266 
267 static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
268 
269 
270 #ifdef TLSEXT_TYPE_next_proto_neg
271 
272 #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1"
273 
274 static int
275 ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
276  const unsigned char **out, unsigned int *outlen, void *arg)
277 {
278 #if (NGX_HTTP_SPDY || NGX_DEBUG)
279  ngx_connection_t *c;
280 
281  c = ngx_ssl_get_connection(ssl_conn);
282  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised");
283 #endif
284 
285 #if (NGX_HTTP_SPDY)
286  {
288 
289  hc = c->data;
290 
291  if (hc->addr_conf->spdy) {
292  *out = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
293  *outlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
294 
295  return SSL_TLSEXT_ERR_OK;
296  }
297  }
298 #endif
299 
300  *out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
301  *outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
302 
303  return SSL_TLSEXT_ERR_OK;
304 }
305 
306 #endif
307 
308 
309 static ngx_int_t
310 ngx_http_ssl_static_variable(ngx_http_request_t *r,
311  ngx_http_variable_value_t *v, uintptr_t data)
312 {
314 
315  size_t len;
316  ngx_str_t s;
317 
318  if (r->connection->ssl) {
319 
320  (void) handler(r->connection, NULL, &s);
321 
322  v->data = s.data;
323 
324  for (len = 0; v->data[len]; len++) { /* void */ }
325 
326  v->len = len;
327  v->valid = 1;
328  v->no_cacheable = 0;
329  v->not_found = 0;
330 
331  return NGX_OK;
332  }
333 
334  v->not_found = 1;
335 
336  return NGX_OK;
337 }
338 
339 
340 static ngx_int_t
341 ngx_http_ssl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
342  uintptr_t data)
343 {
345 
346  ngx_str_t s;
347 
348  if (r->connection->ssl) {
349 
350  if (handler(r->connection, r->pool, &s) != NGX_OK) {
351  return NGX_ERROR;
352  }
353 
354  v->len = s.len;
355  v->data = s.data;
356 
357  if (v->len) {
358  v->valid = 1;
359  v->no_cacheable = 0;
360  v->not_found = 0;
361 
362  return NGX_OK;
363  }
364  }
365 
366  v->not_found = 1;
367 
368  return NGX_OK;
369 }
370 
371 
372 static ngx_int_t
373 ngx_http_ssl_add_variables(ngx_conf_t *cf)
374 {
375  ngx_http_variable_t *var, *v;
376 
377  for (v = ngx_http_ssl_vars; v->name.len; v++) {
378  var = ngx_http_add_variable(cf, &v->name, v->flags);
379  if (var == NULL) {
380  return NGX_ERROR;
381  }
382 
383  var->get_handler = v->get_handler;
384  var->data = v->data;
385  }
386 
387  return NGX_OK;
388 }
389 
390 
391 static void *
392 ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
393 {
395 
396  sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
397  if (sscf == NULL) {
398  return NULL;
399  }
400 
401  /*
402  * set by ngx_pcalloc():
403  *
404  * sscf->protocols = 0;
405  * sscf->certificate = { 0, NULL };
406  * sscf->certificate_key = { 0, NULL };
407  * sscf->dhparam = { 0, NULL };
408  * sscf->ecdh_curve = { 0, NULL };
409  * sscf->client_certificate = { 0, NULL };
410  * sscf->trusted_certificate = { 0, NULL };
411  * sscf->crl = { 0, NULL };
412  * sscf->ciphers = { 0, NULL };
413  * sscf->shm_zone = NULL;
414  * sscf->stapling_file = { 0, NULL };
415  * sscf->stapling_responder = { 0, NULL };
416  */
417 
418  sscf->enable = NGX_CONF_UNSET;
420  sscf->verify = NGX_CONF_UNSET_UINT;
424  sscf->stapling = NGX_CONF_UNSET;
426 
427  return sscf;
428 }
429 
430 
431 static char *
432 ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
433 {
434  ngx_http_ssl_srv_conf_t *prev = parent;
435  ngx_http_ssl_srv_conf_t *conf = child;
436 
437  ngx_pool_cleanup_t *cln;
438 
439  if (conf->enable == NGX_CONF_UNSET) {
440  if (prev->enable == NGX_CONF_UNSET) {
441  conf->enable = 0;
442 
443  } else {
444  conf->enable = prev->enable;
445  conf->file = prev->file;
446  conf->line = prev->line;
447  }
448  }
449 
451  prev->session_timeout, 300);
452 
454  prev->prefer_server_ciphers, 0);
455 
459 
460  ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
462 
465 
466  ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
467 
469  "");
471  prev->trusted_certificate, "");
472  ngx_conf_merge_str_value(conf->crl, prev->crl, "");
473 
476 
478 
479  ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
483  prev->stapling_responder, "");
484 
485  conf->ssl.log = cf->log;
486 
487  if (conf->enable) {
488 
489  if (conf->certificate.len == 0) {
491  "no \"ssl_certificate\" is defined for "
492  "the \"ssl\" directive in %s:%ui",
493  conf->file, conf->line);
494  return NGX_CONF_ERROR;
495  }
496 
497  if (conf->certificate_key.len == 0) {
499  "no \"ssl_certificate_key\" is defined for "
500  "the \"ssl\" directive in %s:%ui",
501  conf->file, conf->line);
502  return NGX_CONF_ERROR;
503  }
504 
505  } else {
506 
507  if (conf->certificate.len == 0) {
508  return NGX_CONF_OK;
509  }
510 
511  if (conf->certificate_key.len == 0) {
513  "no \"ssl_certificate_key\" is defined "
514  "for certificate \"%V\"", &conf->certificate);
515  return NGX_CONF_ERROR;
516  }
517  }
518 
519  if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
520  return NGX_CONF_ERROR;
521  }
522 
523 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
524 
525  if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
526  ngx_http_ssl_servername)
527  == 0)
528  {
530  "nginx was built with SNI support, however, now it is linked "
531  "dynamically to an OpenSSL library which has no tlsext support, "
532  "therefore SNI is not available");
533  }
534 
535 #endif
536 
537 #ifdef TLSEXT_TYPE_next_proto_neg
538  SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx,
539  ngx_http_ssl_npn_advertised, NULL);
540 #endif
541 
542  cln = ngx_pool_cleanup_add(cf->pool, 0);
543  if (cln == NULL) {
544  return NGX_CONF_ERROR;
545  }
546 
548  cln->data = &conf->ssl;
549 
550  if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
551  &conf->certificate_key)
552  != NGX_OK)
553  {
554  return NGX_CONF_ERROR;
555  }
556 
557  if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
558  (const char *) conf->ciphers.data)
559  == 0)
560  {
562  "SSL_CTX_set_cipher_list(\"%V\") failed",
563  &conf->ciphers);
564  }
565 
566  if (conf->verify) {
567 
568  if (conf->client_certificate.len == 0 && conf->verify != 3) {
570  "no ssl_client_certificate for ssl_client_verify");
571  return NGX_CONF_ERROR;
572  }
573 
574  if (ngx_ssl_client_certificate(cf, &conf->ssl,
575  &conf->client_certificate,
576  conf->verify_depth)
577  != NGX_OK)
578  {
579  return NGX_CONF_ERROR;
580  }
581  }
582 
583  if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
584  &conf->trusted_certificate,
585  conf->verify_depth)
586  != NGX_OK)
587  {
588  return NGX_CONF_ERROR;
589  }
590 
591  if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
592  return NGX_CONF_ERROR;
593  }
594 
595  if (conf->prefer_server_ciphers) {
596  SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
597  }
598 
599  /* a temporary 512-bit RSA key is required for export versions of MSIE */
600  SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback);
601 
602  if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
603  return NGX_CONF_ERROR;
604  }
605 
606  if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
607  return NGX_CONF_ERROR;
608  }
609 
612 
613  if (conf->shm_zone == NULL) {
614  conf->shm_zone = prev->shm_zone;
615  }
616 
617  if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
618  conf->builtin_session_cache,
619  conf->shm_zone, conf->session_timeout)
620  != NGX_OK)
621  {
622  return NGX_CONF_ERROR;
623  }
624 
625  if (conf->stapling) {
626 
627  if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
628  &conf->stapling_responder, conf->stapling_verify)
629  != NGX_OK)
630  {
631  return NGX_CONF_ERROR;
632  }
633 
634  }
635 
636  return NGX_CONF_OK;
637 }
638 
639 
640 static char *
641 ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
642 {
643  ngx_http_ssl_srv_conf_t *sscf = conf;
644 
645  char *rv;
646 
647  rv = ngx_conf_set_flag_slot(cf, cmd, conf);
648 
649  if (rv != NGX_CONF_OK) {
650  return rv;
651  }
652 
653  sscf->file = cf->conf_file->file.name.data;
654  sscf->line = cf->conf_file->line;
655 
656  return NGX_CONF_OK;
657 }
658 
659 
660 static char *
661 ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
662 {
663  ngx_http_ssl_srv_conf_t *sscf = conf;
664 
665  size_t len;
666  ngx_str_t *value, name, size;
667  ngx_int_t n;
668  ngx_uint_t i, j;
669 
670  value = cf->args->elts;
671 
672  for (i = 1; i < cf->args->nelts; i++) {
673 
674  if (ngx_strcmp(value[i].data, "off") == 0) {
676  continue;
677  }
678 
679  if (ngx_strcmp(value[i].data, "none") == 0) {
681  continue;
682  }
683 
684  if (ngx_strcmp(value[i].data, "builtin") == 0) {
686  continue;
687  }
688 
689  if (value[i].len > sizeof("builtin:") - 1
690  && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
691  == 0)
692  {
693  n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
694  value[i].len - (sizeof("builtin:") - 1));
695 
696  if (n == NGX_ERROR) {
697  goto invalid;
698  }
699 
700  sscf->builtin_session_cache = n;
701 
702  continue;
703  }
704 
705  if (value[i].len > sizeof("shared:") - 1
706  && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
707  == 0)
708  {
709  len = 0;
710 
711  for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
712  if (value[i].data[j] == ':') {
713  break;
714  }
715 
716  len++;
717  }
718 
719  if (len == 0) {
720  goto invalid;
721  }
722 
723  name.len = len;
724  name.data = value[i].data + sizeof("shared:") - 1;
725 
726  size.len = value[i].len - j - 1;
727  size.data = name.data + len + 1;
728 
729  n = ngx_parse_size(&size);
730 
731  if (n == NGX_ERROR) {
732  goto invalid;
733  }
734 
735  if (n < (ngx_int_t) (8 * ngx_pagesize)) {
737  "session cache \"%V\" is too small",
738  &value[i]);
739 
740  return NGX_CONF_ERROR;
741  }
742 
743  sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
744  &ngx_http_ssl_module);
745  if (sscf->shm_zone == NULL) {
746  return NGX_CONF_ERROR;
747  }
748 
750 
751  continue;
752  }
753 
754  goto invalid;
755  }
756 
757  if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
759  }
760 
761  return NGX_CONF_OK;
762 
763 invalid:
764 
766  "invalid session cache \"%V\"", &value[i]);
767 
768  return NGX_CONF_ERROR;
769 }
770 
771 
772 static ngx_int_t
773 ngx_http_ssl_init(ngx_conf_t *cf)
774 {
775  ngx_uint_t s;
778  ngx_http_core_srv_conf_t **cscfp;
780 
782  cscfp = cmcf->servers.elts;
783 
784  for (s = 0; s < cmcf->servers.nelts; s++) {
785 
786  sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
787 
788  if (sscf->ssl.ctx == NULL || !sscf->stapling) {
789  continue;
790  }
791 
792  clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
793 
794  if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
795  clcf->resolver_timeout)
796  != NGX_OK)
797  {
798  return NGX_ERROR;
799  }
800  }
801 
802  return NGX_OK;
803 }