Fossil SCM
Change cgi_accept_forwarded_for() to return the accepted IP address from the X-Forwarded-For header, which could contain multiple addresses (e.g. if the client is also behind a proxy). The last one is the only one we can currently trust.
Commit
59f790bc52e3d9480029fef6467badd663ab3d26
Parent
d8f716e1d1d422a…
1 file changed
+12
-7
+12
-7
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1133,17 +1133,21 @@ | ||
| 1133 | 1133 | fossil_exit(1); |
| 1134 | 1134 | } |
| 1135 | 1135 | } |
| 1136 | 1136 | |
| 1137 | 1137 | /* z[] is the value of an X-FORWARDED-FOR: line in an HTTP header. |
| 1138 | -** Return true if we should accept this value as a real IP address. | |
| 1139 | -** Return false to stick with the IP address previously computed and | |
| 1138 | +** Return a pointer to a string containing the real IP address, or a | |
| 1139 | +** NULL pointer to stick with the IP address previously computed and | |
| 1140 | 1140 | ** loaded into g.zIpAddr. |
| 1141 | 1141 | */ |
| 1142 | -static int cgi_accept_forwarded_for(const char *z){ | |
| 1143 | - if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 ) return 1; | |
| 1144 | - return 0; | |
| 1142 | +static const char *cgi_accept_forwarded_for(const char *z){ | |
| 1143 | + int i; | |
| 1144 | + if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0; | |
| 1145 | + | |
| 1146 | + i = strlen(z)-1; | |
| 1147 | + while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--; | |
| 1148 | + return &z[++i]; | |
| 1145 | 1149 | } |
| 1146 | 1150 | |
| 1147 | 1151 | /* |
| 1148 | 1152 | ** Remove the first space-delimited token from a string and return |
| 1149 | 1153 | ** a pointer to it. Add a NULL to the string to terminate the token. |
| @@ -1255,12 +1259,13 @@ | ||
| 1255 | 1259 | cgi_setenv("HTTP_REFERER", zVal); |
| 1256 | 1260 | #endif |
| 1257 | 1261 | }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ |
| 1258 | 1262 | cgi_setenv("HTTP_USER_AGENT", zVal); |
| 1259 | 1263 | }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){ |
| 1260 | - if( cgi_accept_forwarded_for(zVal) ){ | |
| 1261 | - g.zIpAddr = mprintf("%s", zVal); | |
| 1264 | + const char *zIpAddr = cgi_accept_forwarded_for(zVal); | |
| 1265 | + if( zIpAddr!=0 ){ | |
| 1266 | + g.zIpAddr = mprintf("%s", zIpAddr); | |
| 1262 | 1267 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); |
| 1263 | 1268 | } |
| 1264 | 1269 | } |
| 1265 | 1270 | } |
| 1266 | 1271 | cgi_init(); |
| 1267 | 1272 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1133,17 +1133,21 @@ | |
| 1133 | fossil_exit(1); |
| 1134 | } |
| 1135 | } |
| 1136 | |
| 1137 | /* z[] is the value of an X-FORWARDED-FOR: line in an HTTP header. |
| 1138 | ** Return true if we should accept this value as a real IP address. |
| 1139 | ** Return false to stick with the IP address previously computed and |
| 1140 | ** loaded into g.zIpAddr. |
| 1141 | */ |
| 1142 | static int cgi_accept_forwarded_for(const char *z){ |
| 1143 | if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 ) return 1; |
| 1144 | return 0; |
| 1145 | } |
| 1146 | |
| 1147 | /* |
| 1148 | ** Remove the first space-delimited token from a string and return |
| 1149 | ** a pointer to it. Add a NULL to the string to terminate the token. |
| @@ -1255,12 +1259,13 @@ | |
| 1255 | cgi_setenv("HTTP_REFERER", zVal); |
| 1256 | #endif |
| 1257 | }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ |
| 1258 | cgi_setenv("HTTP_USER_AGENT", zVal); |
| 1259 | }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){ |
| 1260 | if( cgi_accept_forwarded_for(zVal) ){ |
| 1261 | g.zIpAddr = mprintf("%s", zVal); |
| 1262 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); |
| 1263 | } |
| 1264 | } |
| 1265 | } |
| 1266 | cgi_init(); |
| 1267 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1133,17 +1133,21 @@ | |
| 1133 | fossil_exit(1); |
| 1134 | } |
| 1135 | } |
| 1136 | |
| 1137 | /* z[] is the value of an X-FORWARDED-FOR: line in an HTTP header. |
| 1138 | ** Return a pointer to a string containing the real IP address, or a |
| 1139 | ** NULL pointer to stick with the IP address previously computed and |
| 1140 | ** loaded into g.zIpAddr. |
| 1141 | */ |
| 1142 | static const char *cgi_accept_forwarded_for(const char *z){ |
| 1143 | int i; |
| 1144 | if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0; |
| 1145 | |
| 1146 | i = strlen(z)-1; |
| 1147 | while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--; |
| 1148 | return &z[++i]; |
| 1149 | } |
| 1150 | |
| 1151 | /* |
| 1152 | ** Remove the first space-delimited token from a string and return |
| 1153 | ** a pointer to it. Add a NULL to the string to terminate the token. |
| @@ -1255,12 +1259,13 @@ | |
| 1259 | cgi_setenv("HTTP_REFERER", zVal); |
| 1260 | #endif |
| 1261 | }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ |
| 1262 | cgi_setenv("HTTP_USER_AGENT", zVal); |
| 1263 | }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){ |
| 1264 | const char *zIpAddr = cgi_accept_forwarded_for(zVal); |
| 1265 | if( zIpAddr!=0 ){ |
| 1266 | g.zIpAddr = mprintf("%s", zIpAddr); |
| 1267 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); |
| 1268 | } |
| 1269 | } |
| 1270 | } |
| 1271 | cgi_init(); |
| 1272 |