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