SSL support in the uwsgi module.

Based on patch by Roberto De Ioris.
This commit is contained in:
Maxim Dounin 2013-12-04 23:01:27 +04:00
parent 84f5c2136e
commit 24e1db93a8

View File

@ -34,6 +34,12 @@ typedef struct {
ngx_uint_t modifier1;
ngx_uint_t modifier2;
#if (NGX_HTTP_SSL)
ngx_uint_t ssl;
ngx_uint_t ssl_protocols;
ngx_str_t ssl_ciphers;
#endif
} ngx_http_uwsgi_loc_conf_t;
@ -66,6 +72,11 @@ static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
#if (NGX_HTTP_SSL)
static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
ngx_http_uwsgi_loc_conf_t *uwcf);
#endif
static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = {
ngx_conf_check_num_bounds, 0, 255
@ -86,6 +97,20 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
};
#if (NGX_HTTP_SSL)
static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = {
{ ngx_string("SSLv2"), NGX_SSL_SSLv2 },
{ ngx_string("SSLv3"), NGX_SSL_SSLv3 },
{ ngx_string("TLSv1"), NGX_SSL_TLSv1 },
{ ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
{ ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
{ ngx_null_string, 0 }
};
#endif
ngx_module_t ngx_http_uwsgi_module;
@ -361,6 +386,31 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
&ngx_http_upstream_ignore_headers_masks },
#if (NGX_HTTP_SSL)
{ ngx_string("uwsgi_ssl_session_reuse"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
NULL },
{ ngx_string("uwsgi_ssl_protocols"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
ngx_conf_set_bitmask_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
&ngx_http_uwsgi_ssl_protocols },
{ ngx_string("uwsgi_ssl_ciphers"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
NULL },
#endif
ngx_null_command
};
@ -448,15 +498,29 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
if (uwcf->uwsgi_lengths) {
u = r->upstream;
if (uwcf->uwsgi_lengths == NULL) {
#if (NGX_HTTP_SSL)
u->ssl = (uwcf->upstream.ssl != NULL);
if (u->ssl) {
ngx_str_set(&u->schema, "suwsgi://");
} else {
ngx_str_set(&u->schema, "uwsgi://");
}
#else
ngx_str_set(&u->schema, "uwsgi://");
#endif
} else {
if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
u = r->upstream;
ngx_str_set(&u->schema, "uwsgi://");
u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;
u->conf = &uwcf->upstream;
@ -494,6 +558,7 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
static ngx_int_t
ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
{
size_t add;
ngx_url_t url;
ngx_http_upstream_t *u;
@ -506,6 +571,41 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
return NGX_ERROR;
}
if (url.url.len > 8
&& ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
{
add = 8;
} else if (url.url.len > 9
&& ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
{
#if (NGX_HTTP_SSL)
add = 9;
r->upstream->ssl = 1;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"suwsgi protocol requires SSL support");
return NGX_CONF_ERROR;
#endif
} else {
add = 0;
}
u = r->upstream;
if (add) {
u->schema.len = add;
u->schema.data = url.url.data;
url.url.data += add;
url.url.len -= add;
} else {
ngx_str_set(&u->schema, (u_char *) "uwsgi://");
}
url.no_resolve = 1;
if (ngx_parse_url(r->pool, &url) != NGX_OK) {
@ -517,8 +617,6 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
return NGX_ERROR;
}
u = r->upstream;
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
if (u->resolved == NULL) {
return NGX_ERROR;
@ -1145,6 +1243,9 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
conf->upstream.intercept_errors = NGX_CONF_UNSET;
#if (NGX_HTTP_SSL)
conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
#endif
/* "uwsgi_cyclic_temp_file" is disabled */
conf->upstream.cyclic_temp_file = 0;
@ -1392,6 +1493,27 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.intercept_errors,
prev->upstream.intercept_errors, 0);
#if (NGX_HTTP_SSL)
ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
prev->upstream.ssl_session_reuse, 1);
ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
(NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3
|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
|NGX_SSL_TLSv1_2));
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
"DEFAULT");
if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (conf->upstream.ssl == NULL) {
conf->upstream.ssl = prev->upstream.ssl;
}
#endif
ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
hash.max_size = 512;
@ -1670,6 +1792,7 @@ ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_uwsgi_loc_conf_t *uwcf = conf;
size_t add;
ngx_url_t u;
ngx_str_t *value, *url;
ngx_uint_t n;
@ -1705,12 +1828,35 @@ ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
#if (NGX_HTTP_SSL)
uwcf->ssl = 1;
#endif
return NGX_CONF_OK;
}
if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) {
add = 8;
} else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) {
#if (NGX_HTTP_SSL)
add = 9;
uwcf->ssl = 1;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"suwsgi protocol requires SSL support");
return NGX_CONF_ERROR;
#endif
} else {
add = 0;
}
ngx_memzero(&u, sizeof(ngx_url_t));
u.url = value[1];
u.url.len = url->len - add;
u.url.data = url->data + add;
u.no_resolve = 1;
uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
@ -1844,3 +1990,47 @@ ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
#endif
#if (NGX_HTTP_SSL)
static ngx_int_t
ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
{
ngx_pool_cleanup_t *cln;
uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
if (uwcf->upstream.ssl == NULL) {
return NGX_ERROR;
}
uwcf->upstream.ssl->log = cf->log;
if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
!= NGX_OK)
{
return NGX_ERROR;
}
if (SSL_CTX_set_cipher_list(uwcf->upstream.ssl->ctx,
(const char *) uwcf->ssl_ciphers.data)
== 0)
{
ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
"SSL_CTX_set_cipher_list(\"%V\") failed",
&uwcf->ssl_ciphers);
return NGX_ERROR;
}
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NGX_ERROR;
}
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = uwcf->upstream.ssl;
return NGX_OK;
}
#endif