Mercurial > hg > nginx
comparison src/http/modules/ngx_http_uwsgi_module.c @ 5457:c82b2e020b9f
SSL support in the uwsgi module.
Based on patch by Roberto De Ioris.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 04 Dec 2013 23:01:27 +0400 |
parents | e68af4e3396f |
children | 4a71ef1aa36d |
comparison
equal
deleted
inserted
replaced
5456:692afcea9d0d | 5457:c82b2e020b9f |
---|---|
32 | 32 |
33 ngx_str_t uwsgi_string; | 33 ngx_str_t uwsgi_string; |
34 | 34 |
35 ngx_uint_t modifier1; | 35 ngx_uint_t modifier1; |
36 ngx_uint_t modifier2; | 36 ngx_uint_t modifier2; |
37 | |
38 #if (NGX_HTTP_SSL) | |
39 ngx_uint_t ssl; | |
40 ngx_uint_t ssl_protocols; | |
41 ngx_str_t ssl_ciphers; | |
42 #endif | |
37 } ngx_http_uwsgi_loc_conf_t; | 43 } ngx_http_uwsgi_loc_conf_t; |
38 | 44 |
39 | 45 |
40 static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r, | 46 static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r, |
41 ngx_http_uwsgi_loc_conf_t *uwcf); | 47 ngx_http_uwsgi_loc_conf_t *uwcf); |
62 static ngx_int_t ngx_http_uwsgi_create_key(ngx_http_request_t *r); | 68 static ngx_int_t ngx_http_uwsgi_create_key(ngx_http_request_t *r); |
63 static char *ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, | 69 static char *ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, |
64 void *conf); | 70 void *conf); |
65 static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, | 71 static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, |
66 void *conf); | 72 void *conf); |
73 #endif | |
74 | |
75 #if (NGX_HTTP_SSL) | |
76 static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, | |
77 ngx_http_uwsgi_loc_conf_t *uwcf); | |
67 #endif | 78 #endif |
68 | 79 |
69 | 80 |
70 static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = { | 81 static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = { |
71 ngx_conf_check_num_bounds, 0, 255 | 82 ngx_conf_check_num_bounds, 0, 255 |
84 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, | 95 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, |
85 { ngx_null_string, 0 } | 96 { ngx_null_string, 0 } |
86 }; | 97 }; |
87 | 98 |
88 | 99 |
100 #if (NGX_HTTP_SSL) | |
101 | |
102 static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = { | |
103 { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, | |
104 { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, | |
105 { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, | |
106 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, | |
107 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, | |
108 { ngx_null_string, 0 } | |
109 }; | |
110 | |
111 #endif | |
112 | |
113 | |
89 ngx_module_t ngx_http_uwsgi_module; | 114 ngx_module_t ngx_http_uwsgi_module; |
90 | 115 |
91 | 116 |
92 static ngx_command_t ngx_http_uwsgi_commands[] = { | 117 static ngx_command_t ngx_http_uwsgi_commands[] = { |
93 | 118 |
358 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | 383 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
359 ngx_conf_set_bitmask_slot, | 384 ngx_conf_set_bitmask_slot, |
360 NGX_HTTP_LOC_CONF_OFFSET, | 385 NGX_HTTP_LOC_CONF_OFFSET, |
361 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers), | 386 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers), |
362 &ngx_http_upstream_ignore_headers_masks }, | 387 &ngx_http_upstream_ignore_headers_masks }, |
388 | |
389 #if (NGX_HTTP_SSL) | |
390 | |
391 { ngx_string("uwsgi_ssl_session_reuse"), | |
392 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
393 ngx_conf_set_flag_slot, | |
394 NGX_HTTP_LOC_CONF_OFFSET, | |
395 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse), | |
396 NULL }, | |
397 | |
398 { ngx_string("uwsgi_ssl_protocols"), | |
399 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
400 ngx_conf_set_bitmask_slot, | |
401 NGX_HTTP_LOC_CONF_OFFSET, | |
402 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols), | |
403 &ngx_http_uwsgi_ssl_protocols }, | |
404 | |
405 { ngx_string("uwsgi_ssl_ciphers"), | |
406 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
407 ngx_conf_set_str_slot, | |
408 NGX_HTTP_LOC_CONF_OFFSET, | |
409 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers), | |
410 NULL }, | |
411 | |
412 #endif | |
363 | 413 |
364 ngx_null_command | 414 ngx_null_command |
365 }; | 415 }; |
366 | 416 |
367 | 417 |
446 | 496 |
447 ngx_http_set_ctx(r, status, ngx_http_uwsgi_module); | 497 ngx_http_set_ctx(r, status, ngx_http_uwsgi_module); |
448 | 498 |
449 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); | 499 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); |
450 | 500 |
451 if (uwcf->uwsgi_lengths) { | 501 u = r->upstream; |
502 | |
503 if (uwcf->uwsgi_lengths == NULL) { | |
504 | |
505 #if (NGX_HTTP_SSL) | |
506 u->ssl = (uwcf->upstream.ssl != NULL); | |
507 | |
508 if (u->ssl) { | |
509 ngx_str_set(&u->schema, "suwsgi://"); | |
510 | |
511 } else { | |
512 ngx_str_set(&u->schema, "uwsgi://"); | |
513 } | |
514 #else | |
515 ngx_str_set(&u->schema, "uwsgi://"); | |
516 #endif | |
517 | |
518 } else { | |
452 if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) { | 519 if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) { |
453 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 520 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
454 } | 521 } |
455 } | 522 } |
456 | 523 |
457 u = r->upstream; | |
458 | |
459 ngx_str_set(&u->schema, "uwsgi://"); | |
460 u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module; | 524 u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module; |
461 | 525 |
462 u->conf = &uwcf->upstream; | 526 u->conf = &uwcf->upstream; |
463 | 527 |
464 #if (NGX_HTTP_CACHE) | 528 #if (NGX_HTTP_CACHE) |
492 | 556 |
493 | 557 |
494 static ngx_int_t | 558 static ngx_int_t |
495 ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf) | 559 ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf) |
496 { | 560 { |
561 size_t add; | |
497 ngx_url_t url; | 562 ngx_url_t url; |
498 ngx_http_upstream_t *u; | 563 ngx_http_upstream_t *u; |
499 | 564 |
500 ngx_memzero(&url, sizeof(ngx_url_t)); | 565 ngx_memzero(&url, sizeof(ngx_url_t)); |
501 | 566 |
504 == NULL) | 569 == NULL) |
505 { | 570 { |
506 return NGX_ERROR; | 571 return NGX_ERROR; |
507 } | 572 } |
508 | 573 |
574 if (url.url.len > 8 | |
575 && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0) | |
576 { | |
577 add = 8; | |
578 | |
579 } else if (url.url.len > 9 | |
580 && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0) | |
581 { | |
582 | |
583 #if (NGX_HTTP_SSL) | |
584 add = 9; | |
585 r->upstream->ssl = 1; | |
586 #else | |
587 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
588 "suwsgi protocol requires SSL support"); | |
589 return NGX_CONF_ERROR; | |
590 #endif | |
591 | |
592 } else { | |
593 add = 0; | |
594 } | |
595 | |
596 u = r->upstream; | |
597 | |
598 if (add) { | |
599 u->schema.len = add; | |
600 u->schema.data = url.url.data; | |
601 | |
602 url.url.data += add; | |
603 url.url.len -= add; | |
604 | |
605 } else { | |
606 ngx_str_set(&u->schema, (u_char *) "uwsgi://"); | |
607 } | |
608 | |
509 url.no_resolve = 1; | 609 url.no_resolve = 1; |
510 | 610 |
511 if (ngx_parse_url(r->pool, &url) != NGX_OK) { | 611 if (ngx_parse_url(r->pool, &url) != NGX_OK) { |
512 if (url.err) { | 612 if (url.err) { |
513 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 613 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
514 "%s in upstream \"%V\"", url.err, &url.url); | 614 "%s in upstream \"%V\"", url.err, &url.url); |
515 } | 615 } |
516 | 616 |
517 return NGX_ERROR; | 617 return NGX_ERROR; |
518 } | 618 } |
519 | |
520 u = r->upstream; | |
521 | 619 |
522 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); | 620 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); |
523 if (u->resolved == NULL) { | 621 if (u->resolved == NULL) { |
524 return NGX_ERROR; | 622 return NGX_ERROR; |
525 } | 623 } |
1143 | 1241 |
1144 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; | 1242 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; |
1145 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; | 1243 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; |
1146 | 1244 |
1147 conf->upstream.intercept_errors = NGX_CONF_UNSET; | 1245 conf->upstream.intercept_errors = NGX_CONF_UNSET; |
1246 #if (NGX_HTTP_SSL) | |
1247 conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; | |
1248 #endif | |
1148 | 1249 |
1149 /* "uwsgi_cyclic_temp_file" is disabled */ | 1250 /* "uwsgi_cyclic_temp_file" is disabled */ |
1150 conf->upstream.cyclic_temp_file = 0; | 1251 conf->upstream.cyclic_temp_file = 0; |
1151 | 1252 |
1152 conf->upstream.change_buffering = 1; | 1253 conf->upstream.change_buffering = 1; |
1389 ngx_conf_merge_value(conf->upstream.pass_request_body, | 1490 ngx_conf_merge_value(conf->upstream.pass_request_body, |
1390 prev->upstream.pass_request_body, 1); | 1491 prev->upstream.pass_request_body, 1); |
1391 | 1492 |
1392 ngx_conf_merge_value(conf->upstream.intercept_errors, | 1493 ngx_conf_merge_value(conf->upstream.intercept_errors, |
1393 prev->upstream.intercept_errors, 0); | 1494 prev->upstream.intercept_errors, 0); |
1495 | |
1496 #if (NGX_HTTP_SSL) | |
1497 ngx_conf_merge_value(conf->upstream.ssl_session_reuse, | |
1498 prev->upstream.ssl_session_reuse, 1); | |
1499 | |
1500 ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols, | |
1501 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3 | |
1502 |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1 | |
1503 |NGX_SSL_TLSv1_2)); | |
1504 | |
1505 ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, | |
1506 "DEFAULT"); | |
1507 | |
1508 if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) { | |
1509 return NGX_CONF_ERROR; | |
1510 } | |
1511 | |
1512 if (conf->upstream.ssl == NULL) { | |
1513 conf->upstream.ssl = prev->upstream.ssl; | |
1514 } | |
1515 #endif | |
1394 | 1516 |
1395 ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, ""); | 1517 ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, ""); |
1396 | 1518 |
1397 hash.max_size = 512; | 1519 hash.max_size = 512; |
1398 hash.bucket_size = ngx_align(64, ngx_cacheline_size); | 1520 hash.bucket_size = ngx_align(64, ngx_cacheline_size); |
1668 static char * | 1790 static char * |
1669 ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1791 ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
1670 { | 1792 { |
1671 ngx_http_uwsgi_loc_conf_t *uwcf = conf; | 1793 ngx_http_uwsgi_loc_conf_t *uwcf = conf; |
1672 | 1794 |
1795 size_t add; | |
1673 ngx_url_t u; | 1796 ngx_url_t u; |
1674 ngx_str_t *value, *url; | 1797 ngx_str_t *value, *url; |
1675 ngx_uint_t n; | 1798 ngx_uint_t n; |
1676 ngx_http_core_loc_conf_t *clcf; | 1799 ngx_http_core_loc_conf_t *clcf; |
1677 ngx_http_script_compile_t sc; | 1800 ngx_http_script_compile_t sc; |
1703 | 1826 |
1704 if (ngx_http_script_compile(&sc) != NGX_OK) { | 1827 if (ngx_http_script_compile(&sc) != NGX_OK) { |
1705 return NGX_CONF_ERROR; | 1828 return NGX_CONF_ERROR; |
1706 } | 1829 } |
1707 | 1830 |
1831 #if (NGX_HTTP_SSL) | |
1832 uwcf->ssl = 1; | |
1833 #endif | |
1834 | |
1708 return NGX_CONF_OK; | 1835 return NGX_CONF_OK; |
1709 } | 1836 } |
1710 | 1837 |
1838 if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) { | |
1839 add = 8; | |
1840 | |
1841 } else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) { | |
1842 | |
1843 #if (NGX_HTTP_SSL) | |
1844 add = 9; | |
1845 uwcf->ssl = 1; | |
1846 #else | |
1847 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1848 "suwsgi protocol requires SSL support"); | |
1849 return NGX_CONF_ERROR; | |
1850 #endif | |
1851 | |
1852 } else { | |
1853 add = 0; | |
1854 } | |
1855 | |
1711 ngx_memzero(&u, sizeof(ngx_url_t)); | 1856 ngx_memzero(&u, sizeof(ngx_url_t)); |
1712 | 1857 |
1713 u.url = value[1]; | 1858 u.url.len = url->len - add; |
1859 u.url.data = url->data + add; | |
1714 u.no_resolve = 1; | 1860 u.no_resolve = 1; |
1715 | 1861 |
1716 uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); | 1862 uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); |
1717 if (uwcf->upstream.upstream == NULL) { | 1863 if (uwcf->upstream.upstream == NULL) { |
1718 return NGX_CONF_ERROR; | 1864 return NGX_CONF_ERROR; |
1842 | 1988 |
1843 return NGX_CONF_OK; | 1989 return NGX_CONF_OK; |
1844 } | 1990 } |
1845 | 1991 |
1846 #endif | 1992 #endif |
1993 | |
1994 | |
1995 #if (NGX_HTTP_SSL) | |
1996 | |
1997 static ngx_int_t | |
1998 ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) | |
1999 { | |
2000 ngx_pool_cleanup_t *cln; | |
2001 | |
2002 uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); | |
2003 if (uwcf->upstream.ssl == NULL) { | |
2004 return NGX_ERROR; | |
2005 } | |
2006 | |
2007 uwcf->upstream.ssl->log = cf->log; | |
2008 | |
2009 if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL) | |
2010 != NGX_OK) | |
2011 { | |
2012 return NGX_ERROR; | |
2013 } | |
2014 | |
2015 if (SSL_CTX_set_cipher_list(uwcf->upstream.ssl->ctx, | |
2016 (const char *) uwcf->ssl_ciphers.data) | |
2017 == 0) | |
2018 { | |
2019 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, | |
2020 "SSL_CTX_set_cipher_list(\"%V\") failed", | |
2021 &uwcf->ssl_ciphers); | |
2022 return NGX_ERROR; | |
2023 } | |
2024 | |
2025 cln = ngx_pool_cleanup_add(cf->pool, 0); | |
2026 if (cln == NULL) { | |
2027 return NGX_ERROR; | |
2028 } | |
2029 | |
2030 cln->handler = ngx_ssl_cleanup_ctx; | |
2031 cln->data = uwcf->upstream.ssl; | |
2032 | |
2033 return NGX_OK; | |
2034 } | |
2035 | |
2036 #endif |