|
|
@@ -107,12 +107,49 @@ static const char *rpaf_setport(cmd_parms *cmd, void *dummy, int flag) { |
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static int is_in_array(const char *remote_ip, apr_array_header_t *proxy_ips) {
|
|
|
+static int check_cidr(apr_pool_t *pool, const char *ipcidr, const char *testip) {
|
|
|
+ char *ip;
|
|
|
+ int ipcidr_len;
|
|
|
+ int cidr_val;
|
|
|
+ unsigned int netmask;
|
|
|
+ char *cidr;
|
|
|
+ /* TODO: this might not be portable. just use struct in_addr instead? */
|
|
|
+ uint32_t ipval, testipval;
|
|
|
+
|
|
|
+ ip = apr_pstrdup(pool, ipcidr);
|
|
|
+ /* TODO: this iterates once to copy and iterates again for length */
|
|
|
+ ipcidr_len = strlen(ip);
|
|
|
+ cidr = (char *) memchr(ip + (ipcidr_len - 3), '/', 3);
|
|
|
+
|
|
|
+ if (cidr == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ *cidr = '\0';
|
|
|
+ cidr++;
|
|
|
+ cidr_val = atoi(cidr);
|
|
|
+ if (cidr_val < 1 || cidr_val > 32) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ netmask = 0xffffffff << (32 - atoi(cidr));
|
|
|
+ ipval = ntohl(inet_addr(ip));
|
|
|
+ testipval = ntohl(inet_addr(testip));
|
|
|
+
|
|
|
+ return (ipval & netmask) == (testipval & netmask);
|
|
|
+}
|
|
|
+
|
|
|
+static int is_in_array(apr_pool_t *pool, const char *remote_ip, apr_array_header_t *proxy_ips) {
|
|
|
int i;
|
|
|
char **list = (char**)proxy_ips->elts;
|
|
|
for (i = 0; i < proxy_ips->nelts; i++) {
|
|
|
- if (strcmp(remote_ip, list[i]) == 0)
|
|
|
+ if (check_cidr(pool, list[i], remote_ip) == 1) {
|
|
|
return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (strcmp(remote_ip, list[i]) == 0) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -124,11 +161,12 @@ static apr_status_t rpaf_cleanup(void *data) { |
|
|
return APR_SUCCESS;
|
|
|
}
|
|
|
|
|
|
-static char* last_not_in_array(apr_array_header_t *forwarded_for,
|
|
|
+static char* last_not_in_array(apr_pool_t *pool,
|
|
|
+ apr_array_header_t *forwarded_for,
|
|
|
apr_array_header_t *proxy_ips) {
|
|
|
int i;
|
|
|
for (i = (forwarded_for->nelts)-1; i > 0; i--) {
|
|
|
- if (!is_in_array(((char **)forwarded_for->elts)[i], proxy_ips))
|
|
|
+ if (!is_in_array(pool, ((char **)forwarded_for->elts)[i], proxy_ips))
|
|
|
break;
|
|
|
}
|
|
|
return ((char **)forwarded_for->elts)[i];
|
|
|
@@ -143,7 +181,7 @@ static int change_remote_ip(request_rec *r) { |
|
|
if (!cfg->enable)
|
|
|
return DECLINED;
|
|
|
|
|
|
- if (is_in_array(r->connection->remote_ip, cfg->proxy_ips) == 1) {
|
|
|
+ if (is_in_array(r->pool, r->connection->remote_ip, cfg->proxy_ips) == 1) {
|
|
|
/* check if cfg->headername is set and if it is use
|
|
|
that instead of X-Forwarded-For by default */
|
|
|
if (cfg->headername && (fwdvalue = apr_table_get(r->headers_in, cfg->headername))) {
|
|
|
@@ -165,7 +203,7 @@ static int change_remote_ip(request_rec *r) { |
|
|
rcr->old_ip = apr_pstrdup(r->connection->pool, r->connection->remote_ip);
|
|
|
rcr->r = r;
|
|
|
apr_pool_cleanup_register(r->pool, (void *)rcr, rpaf_cleanup, apr_pool_cleanup_null);
|
|
|
- r->connection->remote_ip = apr_pstrdup(r->connection->pool, last_not_in_array(arr, cfg->proxy_ips));
|
|
|
+ r->connection->remote_ip = apr_pstrdup(r->connection->pool, last_not_in_array(r->pool, arr, cfg->proxy_ips));
|
|
|
r->connection->remote_addr->sa.sin.sin_addr.s_addr = apr_inet_addr(r->connection->remote_ip);
|
|
|
|
|
|
if (cfg->sethostname) {
|
|
|
|
0 comments on commit
0694153