Skip to content
Browse files

Added support for passing CIDRs in RPAF_ProxyIPs.

  • Loading branch information...
1 parent f0f25d0 commit 0694153c3423f598c5dd94b8cc58a3731b3d3fc0 @tail tail committed
Showing with 44 additions and 6 deletions.
  1. +44 −6 mod_rpaf.c
View
50 mod_rpaf.c
@@ -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

Please sign in to comment.
Something went wrong with that request. Please try again.