@@ -184,6 +184,11 @@ static void *wsgi_merge_server_config(apr_pool_t *p, void *base_conf,
184
184
else
185
185
config -> map_head_to_get = parent -> map_head_to_get ;
186
186
187
+ if (child -> trusted_proxy_headers )
188
+ config -> trusted_proxy_headers = child -> trusted_proxy_headers ;
189
+ else
190
+ config -> trusted_proxy_headers = parent -> trusted_proxy_headers ;
191
+
187
192
if (child -> enable_sendfile != -1 )
188
193
config -> enable_sendfile = child -> enable_sendfile ;
189
194
else
@@ -219,6 +224,8 @@ typedef struct {
219
224
int chunked_request ;
220
225
int map_head_to_get ;
221
226
227
+ apr_array_header_t * trusted_proxy_headers ;
228
+
222
229
int enable_sendfile ;
223
230
224
231
WSGIScriptFile * access_script ;
@@ -251,6 +258,8 @@ static WSGIDirectoryConfig *newWSGIDirectoryConfig(apr_pool_t *p)
251
258
object -> chunked_request = -1 ;
252
259
object -> map_head_to_get = -1 ;
253
260
261
+ object -> trusted_proxy_headers = NULL ;
262
+
254
263
object -> enable_sendfile = -1 ;
255
264
256
265
object -> access_script = NULL ;
@@ -338,6 +347,11 @@ static void *wsgi_merge_dir_config(apr_pool_t *p, void *base_conf,
338
347
else
339
348
config -> map_head_to_get = parent -> map_head_to_get ;
340
349
350
+ if (child -> trusted_proxy_headers )
351
+ config -> trusted_proxy_headers = child -> trusted_proxy_headers ;
352
+ else
353
+ config -> trusted_proxy_headers = parent -> trusted_proxy_headers ;
354
+
341
355
if (child -> enable_sendfile != -1 )
342
356
config -> enable_sendfile = child -> enable_sendfile ;
343
357
else
@@ -398,6 +412,8 @@ typedef struct {
398
412
int chunked_request ;
399
413
int map_head_to_get ;
400
414
415
+ apr_array_header_t * trusted_proxy_headers ;
416
+
401
417
int enable_sendfile ;
402
418
403
419
WSGIScriptFile * access_script ;
@@ -833,6 +849,11 @@ static WSGIRequestConfig *wsgi_create_req_config(apr_pool_t *p, request_rec *r)
833
849
config -> map_head_to_get = 2 ;
834
850
}
835
851
852
+ config -> trusted_proxy_headers = dconfig -> trusted_proxy_headers ;
853
+
854
+ if (!config -> trusted_proxy_headers )
855
+ config -> trusted_proxy_headers = sconfig -> trusted_proxy_headers ;
856
+
836
857
config -> enable_sendfile = dconfig -> enable_sendfile ;
837
858
838
859
if (config -> enable_sendfile < 0 ) {
@@ -4971,6 +4992,40 @@ static const char *wsgi_set_map_head_to_get(cmd_parms *cmd, void *mconfig,
4971
4992
return NULL ;
4972
4993
}
4973
4994
4995
+ static char * wsgi_http2env (apr_pool_t * a , const char * w );
4996
+
4997
+ static const char * wsgi_set_trusted_proxy_headers (cmd_parms * cmd ,
4998
+ void * mconfig ,
4999
+ const char * args )
5000
+ {
5001
+ apr_array_header_t * headers = NULL ;
5002
+
5003
+ if (cmd -> path ) {
5004
+ WSGIDirectoryConfig * dconfig = NULL ;
5005
+ dconfig = (WSGIDirectoryConfig * )mconfig ;
5006
+
5007
+ headers = apr_array_make (cmd -> pool , 3 , sizeof (char * ));
5008
+ dconfig -> trusted_proxy_headers = headers ;
5009
+ }
5010
+ else {
5011
+ WSGIServerConfig * sconfig = NULL ;
5012
+ sconfig = ap_get_module_config (cmd -> server -> module_config ,
5013
+ & wsgi_module );
5014
+
5015
+ headers = apr_array_make (cmd -> pool , 3 , sizeof (char * ));
5016
+ sconfig -> trusted_proxy_headers = headers ;
5017
+ }
5018
+
5019
+ while (* args ) {
5020
+ const char * * entry = NULL ;
5021
+
5022
+ entry = (const char * * )apr_array_push (headers );
5023
+ * entry = wsgi_http2env (cmd -> pool , ap_getword_conf (cmd -> pool , & args ));
5024
+ }
5025
+
5026
+ return NULL ;
5027
+ }
5028
+
4974
5029
static const char * wsgi_set_enable_sendfile (cmd_parms * cmd , void * mconfig ,
4975
5030
const char * f )
4976
5031
{
@@ -5424,6 +5479,7 @@ static int wsgi_hook_intercept(request_rec *r)
5424
5479
/* Handler for the response handler phase. */
5425
5480
5426
5481
static void wsgi_drop_invalid_headers (request_rec * r );
5482
+ static void wsgi_process_proxy_headers (request_rec * r );
5427
5483
5428
5484
static void wsgi_build_environment (request_rec * r )
5429
5485
{
@@ -5459,6 +5515,8 @@ static void wsgi_build_environment(request_rec *r)
5459
5515
ap_add_cgi_vars (r );
5460
5516
ap_add_common_vars (r );
5461
5517
5518
+ wsgi_process_proxy_headers (r );
5519
+
5462
5520
/*
5463
5521
* Mutate a HEAD request into a GET request. This is
5464
5522
* required because WSGI specification doesn't lay out
@@ -12297,6 +12355,91 @@ static void wsgi_drop_invalid_headers(request_rec *r)
12297
12355
}
12298
12356
}
12299
12357
12358
+ static const char * wsgi_proxy_headers [] = {
12359
+ "HTTP_X_FORWARDED_HTTPS" ,
12360
+ "HTTP_X_FORWARDED_PROTO" ,
12361
+ "HTTP_X_FORWARDED_SCHEME" ,
12362
+ "HTTP_X_FORWARDED_SSL" ,
12363
+ "HTTP_X_SCHEME" ,
12364
+ NULL ,
12365
+ };
12366
+
12367
+ static void wsgi_process_proxy_headers (request_rec * r )
12368
+ {
12369
+ WSGIRequestConfig * config = NULL ;
12370
+
12371
+ apr_array_header_t * trusted_proxy_headers = NULL ;
12372
+
12373
+ int i = 0 ;
12374
+
12375
+ config = (WSGIRequestConfig * )ap_get_module_config (r -> request_config ,
12376
+ & wsgi_module );
12377
+
12378
+ trusted_proxy_headers = config -> trusted_proxy_headers ;
12379
+
12380
+ /* Nothing to do if no trusted headers have been specified. */
12381
+
12382
+ if (!trusted_proxy_headers )
12383
+ return ;
12384
+
12385
+ /*
12386
+ * Check for any special processing required for each trusted
12387
+ * header which has been specified.
12388
+ */
12389
+
12390
+ for (i = 0 ; i < trusted_proxy_headers -> nelts ; i ++ ) {
12391
+ const char * name = NULL ;
12392
+ const char * value = NULL ;
12393
+
12394
+ name = ((const char * * )trusted_proxy_headers -> elts )[i ];
12395
+ value = apr_table_get (r -> subprocess_env , name );
12396
+
12397
+ if (value ) {
12398
+ if (!strcmp (name , "HTTP_X_FORWARDED_PROTO" ) ||
12399
+ !strcmp (name , "HTTP_X_FORWARDED_SCHEME" ) ||
12400
+ !strcmp (name , "HTTP_X_SCHEME" )) {
12401
+
12402
+ /* Value can be either 'http' or 'https'. */
12403
+
12404
+ if (!strcasecmp (value , "https" ))
12405
+ apr_table_setn (r -> subprocess_env , "HTTPS" , "1" );
12406
+ else if (!strcasecmp (value , "http" ))
12407
+ apr_table_unset (r -> subprocess_env , "HTTPS" );
12408
+ }
12409
+ else if (!strcmp (name , "HTTP_X_FORWARDED_HTTPS" ) ||
12410
+ !strcmp (name , "HTTP_X_FORWARDED_SSL" )) {
12411
+
12412
+ /*
12413
+ * Value can be a boolean like flag such as 'On',
12414
+ * 'Off', 'true', 'false', '1' or '0'.
12415
+ */
12416
+
12417
+ if (!strcasecmp (value , "On" ) ||
12418
+ !strcasecmp (value , "true" ) ||
12419
+ !strcasecmp (value , "1" )) {
12420
+
12421
+ apr_table_setn (r -> subprocess_env , "HTTPS" , "1" );
12422
+ }
12423
+ else if (!strcasecmp (value , "Off" ) ||
12424
+ !strcasecmp (value , "false" ) ||
12425
+ !strcasecmp (value , "0" )) {
12426
+
12427
+ apr_table_unset (r -> subprocess_env , "HTTPS" );
12428
+ }
12429
+ }
12430
+ }
12431
+ }
12432
+
12433
+ /*
12434
+ * Remove all trusted proxy headers from request environment
12435
+ * so not reinterpreted by the WSGI applicaton.
12436
+ */
12437
+
12438
+
12439
+ for (i = 0 ; wsgi_proxy_headers [i ]; i ++ )
12440
+ apr_table_unset (r -> subprocess_env , wsgi_proxy_headers [i ]);
12441
+ }
12442
+
12300
12443
static char * wsgi_http2env (apr_pool_t * a , const char * w )
12301
12444
{
12302
12445
char * res = (char * )apr_palloc (a , sizeof ("HTTP_" ) + strlen (w ));
@@ -14428,6 +14571,9 @@ static const command_rec wsgi_commands[] =
14428
14571
AP_INIT_TAKE1 ("WSGIMapHEADToGET" , wsgi_set_map_head_to_get ,
14429
14572
NULL , OR_FILEINFO , "Enable/Disable mapping of HEAD to GET." ),
14430
14573
14574
+ AP_INIT_RAW_ARGS ("WSGITrustedProxyHeaders" , wsgi_set_trusted_proxy_headers ,
14575
+ NULL , OR_FILEINFO , "Specify a list of trusted proxy headers." ),
14576
+
14431
14577
#ifndef WIN32
14432
14578
AP_INIT_TAKE1 ("WSGIEnableSendfile" , wsgi_set_enable_sendfile ,
14433
14579
NULL , OR_FILEINFO , "Enable/Disable support for kernel sendfile." ),
0 commit comments