Blame modules/metadata/mod_remoteip.c

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 *
Packit 90a5c9
 * Portions of the input filter code for PROXY protocol support is
Packit 90a5c9
 * Copyright 2014 Cloudzilla Inc.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
#include "ap_config.h"
Packit 90a5c9
#include "ap_mmn.h"
Packit 90a5c9
#include "ap_listen.h"
Packit 90a5c9
#include "httpd.h"
Packit 90a5c9
#include "http_config.h"
Packit 90a5c9
#include "http_connection.h"
Packit 90a5c9
#include "http_protocol.h"
Packit 90a5c9
#include "http_log.h"
Packit 90a5c9
#include "http_main.h"
Packit 90a5c9
#include "apr_strings.h"
Packit 90a5c9
#include "apr_lib.h"
Packit 90a5c9
#define APR_WANT_BYTEFUNC
Packit 90a5c9
#include "apr_want.h"
Packit 90a5c9
#include "apr_network_io.h"
Packit 90a5c9
#include "apr_version.h"
Packit 90a5c9
Packit 90a5c9
module AP_MODULE_DECLARE_DATA remoteip_module;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    /** A proxy IP mask to match */
Packit 90a5c9
    apr_ipsubnet_t *ip;
Packit 90a5c9
    /** Flagged if internal, otherwise an external trusted proxy */
Packit 90a5c9
    void  *internal;
Packit 90a5c9
} remoteip_proxymatch_t;
Packit 90a5c9
Packit 90a5c9
typedef struct remoteip_addr_info {
Packit 90a5c9
    struct remoteip_addr_info *next;
Packit 90a5c9
    apr_sockaddr_t *addr;
Packit 90a5c9
    server_rec *source;
Packit 90a5c9
} remoteip_addr_info;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    /** The header to retrieve a proxy-via IP list */
Packit 90a5c9
    const char *header_name;
Packit 90a5c9
    /** A header to record the proxied IP's
Packit 90a5c9
     * (removed as the physical connection and
Packit 90a5c9
     * from the proxy-via IP header value list)
Packit 90a5c9
     */
Packit 90a5c9
    const char *proxies_header_name;
Packit 90a5c9
    /** A list of trusted proxies, ideally configured
Packit 90a5c9
     *  with the most commonly encountered listed first
Packit 90a5c9
     */
Packit 90a5c9
    apr_array_header_t *proxymatch_ip;
Packit 90a5c9
Packit 90a5c9
    remoteip_addr_info *proxy_protocol_enabled;
Packit 90a5c9
    remoteip_addr_info *proxy_protocol_disabled;
Packit 90a5c9
Packit 90a5c9
    apr_array_header_t *disabled_subnets;
Packit 90a5c9
    apr_pool_t *pool;
Packit 90a5c9
} remoteip_config_t;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    apr_sockaddr_t *useragent_addr;
Packit 90a5c9
    char *useragent_ip;
Packit 90a5c9
    /** The list of proxy IP's ignored as remote IP's */
Packit 90a5c9
    const char *proxy_ips;
Packit 90a5c9
    /** The remaining list of untrusted proxied remote IP's */
Packit 90a5c9
    const char *proxied_remote;
Packit 90a5c9
} remoteip_req_t;
Packit 90a5c9
Packit 90a5c9
/* For PROXY protocol processing */
Packit 90a5c9
static ap_filter_rec_t *remoteip_filter;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    char line[108];
Packit 90a5c9
} proxy_v1;
Packit 90a5c9
Packit 90a5c9
typedef union {
Packit 90a5c9
    struct {        /* for TCP/UDP over IPv4, len = 12 */
Packit 90a5c9
        apr_uint32_t src_addr;
Packit 90a5c9
        apr_uint32_t dst_addr;
Packit 90a5c9
        apr_uint16_t src_port;
Packit 90a5c9
        apr_uint16_t dst_port;
Packit 90a5c9
    } ip4;
Packit 90a5c9
    struct {        /* for TCP/UDP over IPv6, len = 36 */
Packit 90a5c9
         apr_byte_t  src_addr[16];
Packit 90a5c9
         apr_byte_t  dst_addr[16];
Packit 90a5c9
         apr_uint16_t src_port;
Packit 90a5c9
         apr_uint16_t dst_port;
Packit 90a5c9
    } ip6;
Packit 90a5c9
    struct {        /* for AF_UNIX sockets, len = 216 */
Packit 90a5c9
         apr_byte_t src_addr[108];
Packit 90a5c9
         apr_byte_t dst_addr[108];
Packit 90a5c9
    } unx;
Packit 90a5c9
} proxy_v2_addr;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    apr_byte_t  sig[12];  /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */
Packit 90a5c9
    apr_byte_t  ver_cmd;  /* protocol version and command */
Packit 90a5c9
    apr_byte_t  fam;      /* protocol family and address */
Packit 90a5c9
    apr_uint16_t len;     /* number of following bytes part of the header */
Packit 90a5c9
    proxy_v2_addr addr;
Packit 90a5c9
} proxy_v2;
Packit 90a5c9
Packit 90a5c9
typedef union {
Packit 90a5c9
        proxy_v1 v1;
Packit 90a5c9
        proxy_v2 v2;
Packit 90a5c9
} proxy_header;
Packit 90a5c9
Packit 90a5c9
static const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
Packit 90a5c9
#define MIN_V1_HDR_LEN 15
Packit 90a5c9
#define MIN_V2_HDR_LEN 16
Packit 90a5c9
#define MIN_HDR_LEN MIN_V1_HDR_LEN
Packit 90a5c9
Packit 90a5c9
/* XXX: Unsure if this is needed if v6 support is not available on
Packit 90a5c9
   this platform */
Packit 90a5c9
#ifndef INET6_ADDRSTRLEN
Packit 90a5c9
#define INET6_ADDRSTRLEN 46
Packit 90a5c9
#endif
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    char header[sizeof(proxy_header)];
Packit 90a5c9
    apr_size_t rcvd;
Packit 90a5c9
    apr_size_t need;
Packit 90a5c9
    int version;
Packit 90a5c9
    ap_input_mode_t mode;
Packit 90a5c9
    apr_bucket_brigade *bb;
Packit 90a5c9
    int done;
Packit 90a5c9
} remoteip_filter_context;
Packit 90a5c9
Packit 90a5c9
/** Holds the resolved proxy info for this connection and any additional
Packit 90a5c9
  configurable parameters
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    /** The parsed client address in native format */
Packit 90a5c9
    apr_sockaddr_t *client_addr;
Packit 90a5c9
    /** Character representation of the client */
Packit 90a5c9
    char *client_ip;
Packit 90a5c9
} remoteip_conn_config_t;
Packit 90a5c9
Packit 90a5c9
typedef enum { HDR_DONE, HDR_ERROR, HDR_NEED_MORE } remoteip_parse_status_t;
Packit 90a5c9
Packit 90a5c9
static void *create_remoteip_server_config(apr_pool_t *p, server_rec *s)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *config = apr_pcalloc(p, sizeof(*config));
Packit 90a5c9
    config->disabled_subnets = apr_array_make(p, 1, sizeof(apr_ipsubnet_t *));
Packit 90a5c9
    /* config->header_name = NULL;
Packit 90a5c9
     * config->proxies_header_name = NULL;
Packit 90a5c9
     * config->proxy_protocol_enabled = NULL;
Packit 90a5c9
     * config->proxy_protocol_disabled = NULL;
Packit 90a5c9
     */
Packit 90a5c9
    config->pool = p;
Packit 90a5c9
    return config;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv,
Packit 90a5c9
                                          void *serverv)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *global = (remoteip_config_t *) globalv;
Packit 90a5c9
    remoteip_config_t *server = (remoteip_config_t *) serverv;
Packit 90a5c9
    remoteip_config_t *config;
Packit 90a5c9
Packit 90a5c9
    config = (remoteip_config_t *) apr_palloc(p, sizeof(*config));
Packit 90a5c9
    config->header_name = server->header_name
Packit 90a5c9
                        ? server->header_name
Packit 90a5c9
                        : global->header_name;
Packit 90a5c9
    config->proxies_header_name = server->proxies_header_name
Packit 90a5c9
                                ? server->proxies_header_name
Packit 90a5c9
                                : global->proxies_header_name;
Packit 90a5c9
    config->proxymatch_ip = server->proxymatch_ip
Packit 90a5c9
                          ? server->proxymatch_ip
Packit 90a5c9
                          : global->proxymatch_ip;
Packit 90a5c9
    return config;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *header_name_set(cmd_parms *cmd, void *dummy,
Packit 90a5c9
                                   const char *arg)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *config = ap_get_module_config(cmd->server->module_config,
Packit 90a5c9
                                                     &remoteip_module);
Packit 90a5c9
    config->header_name = arg;
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *proxies_header_name_set(cmd_parms *cmd, void *dummy,
Packit 90a5c9
                                           const char *arg)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *config = ap_get_module_config(cmd->server->module_config,
Packit 90a5c9
                                                     &remoteip_module);
Packit 90a5c9
    config->proxies_header_name = arg;
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/* Would be quite nice if APR exported this */
Packit 90a5c9
/* apr:network_io/unix/sockaddr.c */
Packit 90a5c9
static int looks_like_ip(const char *ipstr)
Packit 90a5c9
{
Packit 90a5c9
    if (ap_strchr_c(ipstr, ':')) {
Packit 90a5c9
        /* definitely not a hostname; assume it is intended to be an IPv6 address */
Packit 90a5c9
        return 1;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* simple IPv4 address string check */
Packit 90a5c9
    while ((*ipstr == '.') || apr_isdigit(*ipstr))
Packit 90a5c9
        ipstr++;
Packit 90a5c9
    return (*ipstr == '\0');
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *proxies_set(cmd_parms *cmd, void *cfg,
Packit 90a5c9
                               const char *arg)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *config = ap_get_module_config(cmd->server->module_config,
Packit 90a5c9
                                                     &remoteip_module);
Packit 90a5c9
    remoteip_proxymatch_t *match;
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
    char *ip = apr_pstrdup(cmd->temp_pool, arg);
Packit 90a5c9
    char *s = ap_strchr(ip, '/');
Packit 90a5c9
    if (s) {
Packit 90a5c9
        *s++ = '\0';
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (!config->proxymatch_ip) {
Packit 90a5c9
        config->proxymatch_ip = apr_array_make(cmd->pool, 1, sizeof(*match));
Packit 90a5c9
    }
Packit 90a5c9
    match = (remoteip_proxymatch_t *) apr_array_push(config->proxymatch_ip);
Packit 90a5c9
    match->internal = cmd->info;
Packit 90a5c9
Packit 90a5c9
    if (looks_like_ip(ip)) {
Packit 90a5c9
        /* Note s may be null, that's fine (explicit host) */
Packit 90a5c9
        rv = apr_ipsubnet_create(&match->ip, ip, s, cmd->pool);
Packit 90a5c9
    }
Packit 90a5c9
    else
Packit 90a5c9
    {
Packit 90a5c9
        apr_sockaddr_t *temp_sa;
Packit 90a5c9
Packit 90a5c9
        if (s) {
Packit 90a5c9
            return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg,
Packit 90a5c9
                               " the subnet /", s, " is invalid for ",
Packit 90a5c9
                               cmd->cmd->name, NULL);
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        rv = apr_sockaddr_info_get(&temp_sa,  ip, APR_UNSPEC, 0,
Packit 90a5c9
                                   APR_IPV4_ADDR_OK, cmd->temp_pool);
Packit 90a5c9
        while (rv == APR_SUCCESS)
Packit 90a5c9
        {
Packit 90a5c9
            apr_sockaddr_ip_get(&ip, temp_sa);
Packit 90a5c9
            rv = apr_ipsubnet_create(&match->ip, ip, NULL, cmd->pool);
Packit 90a5c9
            if (!(temp_sa = temp_sa->next)) {
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
            match = (remoteip_proxymatch_t *)
Packit 90a5c9
                    apr_array_push(config->proxymatch_ip);
Packit 90a5c9
            match->internal = cmd->info;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (rv != APR_SUCCESS) {
Packit 90a5c9
        return apr_psprintf(cmd->pool,
Packit 90a5c9
                            "RemoteIP: Error parsing IP %s (%pm error) for %s",
Packit 90a5c9
                            arg, &rv, cmd->cmd->name);
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *proxylist_read(cmd_parms *cmd, void *cfg,
Packit 90a5c9
                                  const char *filename)
Packit 90a5c9
{
Packit 90a5c9
    char lbuf[MAX_STRING_LEN];
Packit 90a5c9
    char *arg;
Packit 90a5c9
    const char *args;
Packit 90a5c9
    const char *errmsg;
Packit 90a5c9
    ap_configfile_t *cfp;
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
Packit 90a5c9
    filename = ap_server_root_relative(cmd->temp_pool, filename);
Packit 90a5c9
    rv = ap_pcfg_openfile(&cfp, cmd->temp_pool, filename);
Packit 90a5c9
    if (rv != APR_SUCCESS) {
Packit 90a5c9
        return apr_psprintf(cmd->pool, "%s: Could not open file %s: %pm",
Packit 90a5c9
                            cmd->cmd->name, filename, &rv;;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    while (!(ap_cfg_getline(lbuf, MAX_STRING_LEN, cfp))) {
Packit 90a5c9
        args = lbuf;
Packit 90a5c9
        while (*(arg = ap_getword_conf(cmd->temp_pool, &args)) != '\0') {
Packit 90a5c9
            if (*arg == '#') {
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
            errmsg = proxies_set(cmd, cfg, arg);
Packit 90a5c9
            if (errmsg) {
Packit 90a5c9
                ap_cfg_closefile(cfp);
Packit 90a5c9
                errmsg = apr_psprintf(cmd->pool, "%s at line %d of %s",
Packit 90a5c9
                                      errmsg, cfp->line_number, filename);
Packit 90a5c9
                return errmsg;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    ap_cfg_closefile(cfp);
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/** Similar to apr_sockaddr_equal, except that it compares ports too. */
Packit 90a5c9
static int remoteip_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
Packit 90a5c9
{
Packit 90a5c9
    return (addr1->port == addr2->port && apr_sockaddr_equal(addr1, addr2));
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
#if !APR_VERSION_AT_LEAST(1,5,0)
Packit 90a5c9
#define apr_sockaddr_is_wildcard sockaddr_is_wildcard
Packit 90a5c9
/* XXX: temp build fix from apr 1.5.x */
Packit 90a5c9
static int sockaddr_is_wildcard(const apr_sockaddr_t *addr)
Packit 90a5c9
{
Packit 90a5c9
    static const char inaddr_any[
Packit 90a5c9
#if APR_HAVE_IPV6
Packit 90a5c9
        sizeof(struct in6_addr)
Packit 90a5c9
#else
Packit 90a5c9
        sizeof(struct in_addr)
Packit 90a5c9
#endif
Packit 90a5c9
    ] = {0};
Packit 90a5c9
Packit 90a5c9
    if (addr->ipaddr_ptr /* IP address initialized */
Packit 90a5c9
        && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
Packit 90a5c9
        if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
Packit 90a5c9
            return 1;
Packit 90a5c9
        }
Packit 90a5c9
#if APR_HAVE_IPV6
Packit 90a5c9
    if (addr->family == AF_INET6
Packit 90a5c9
        && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
Packit 90a5c9
        struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
Packit 90a5c9
Packit 90a5c9
        if (!memcmp(inaddr_any, v4, sizeof *v4)) {
Packit 90a5c9
            return 1;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
#endif
Packit 90a5c9
    }
Packit 90a5c9
    return 0;
Packit 90a5c9
}
Packit 90a5c9
#endif
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/** Similar to remoteip_sockaddr_equal, except that it handles wildcard addresses
Packit 90a5c9
 *  and ports too.
Packit 90a5c9
 */
Packit 90a5c9
static int remoteip_sockaddr_compat(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
Packit 90a5c9
{
Packit 90a5c9
    /* test exact address equality */
Packit 90a5c9
    if (apr_sockaddr_equal(addr1, addr2) &&
Packit 90a5c9
        (addr1->port == addr2->port || addr1->port == 0 || addr2->port == 0)) {
Packit 90a5c9
        return 1;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* test address wildcards */
Packit 90a5c9
    if (apr_sockaddr_is_wildcard(addr1) &&
Packit 90a5c9
        (addr1->port == 0 || addr1->port == addr2->port)) {
Packit 90a5c9
        return 1;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (apr_sockaddr_is_wildcard(addr2) &&
Packit 90a5c9
        (addr2->port == 0 || addr2->port == addr1->port)) {
Packit 90a5c9
        return 1;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return 0;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int remoteip_addr_in_list(remoteip_addr_info *list, apr_sockaddr_t *addr)
Packit 90a5c9
{
Packit 90a5c9
    for (; list; list = list->next) {
Packit 90a5c9
        if (remoteip_sockaddr_compat(list->addr, addr)) {
Packit 90a5c9
            return 1;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return 0;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static void remoteip_warn_enable_conflict(remoteip_addr_info *prev, server_rec *new, int flag)
Packit 90a5c9
{
Packit 90a5c9
    char buf[INET6_ADDRSTRLEN];
Packit 90a5c9
Packit 90a5c9
    apr_sockaddr_ip_getbuf(buf, sizeof(buf), prev->addr);
Packit 90a5c9
Packit 90a5c9
    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, new, APLOGNO(03491)
Packit 90a5c9
                 "RemoteIPProxyProtocol: previous setting for %s:%hu from virtual "
Packit 90a5c9
                 "host {%s:%hu in %s} is being overriden by virtual host "
Packit 90a5c9
                 "{%s:%hu in %s}; new setting is '%s'",
Packit 90a5c9
                 buf, prev->addr->port, prev->source->server_hostname,
Packit 90a5c9
                 prev->source->addrs->host_port, prev->source->defn_name,
Packit 90a5c9
                 new->server_hostname, new->addrs->host_port, new->defn_name,
Packit 90a5c9
                 flag ? "On" : "Off");
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *remoteip_enable_proxy_protocol(cmd_parms *cmd, void *config,
Packit 90a5c9
                                                  int flag)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *conf;
Packit 90a5c9
    server_addr_rec *addr;
Packit 90a5c9
    remoteip_addr_info **add;
Packit 90a5c9
    remoteip_addr_info **rem;
Packit 90a5c9
    remoteip_addr_info *list;
Packit 90a5c9
Packit 90a5c9
    conf = ap_get_module_config(ap_server_conf->module_config,
Packit 90a5c9
                                &remoteip_module);
Packit 90a5c9
Packit 90a5c9
    if (flag) {
Packit 90a5c9
        add = &conf->proxy_protocol_enabled;
Packit 90a5c9
        rem = &conf->proxy_protocol_disabled;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        add = &conf->proxy_protocol_disabled;
Packit 90a5c9
        rem = &conf->proxy_protocol_enabled;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    for (addr = cmd->server->addrs; addr; addr = addr->next) {
Packit 90a5c9
        /* remove address from opposite list */
Packit 90a5c9
        if (*rem) {
Packit 90a5c9
            if (remoteip_sockaddr_equal((*rem)->addr, addr->host_addr)) {
Packit 90a5c9
                remoteip_warn_enable_conflict(*rem, cmd->server, flag);
Packit 90a5c9
                *rem = (*rem)->next;
Packit 90a5c9
            }
Packit 90a5c9
            else {
Packit 90a5c9
                for (list = *rem; list->next; list = list->next) {
Packit 90a5c9
                    if (remoteip_sockaddr_equal(list->next->addr, addr->host_addr)) {
Packit 90a5c9
                        remoteip_warn_enable_conflict(list->next, cmd->server, flag);
Packit 90a5c9
                        list->next = list->next->next;
Packit 90a5c9
                        break;
Packit 90a5c9
                    }
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        /* add address to desired list */
Packit 90a5c9
        if (!remoteip_addr_in_list(*add, addr->host_addr)) {
Packit 90a5c9
            remoteip_addr_info *info = apr_palloc(conf->pool, sizeof(*info));
Packit 90a5c9
            info->addr = addr->host_addr;
Packit 90a5c9
            info->source = cmd->server;
Packit 90a5c9
            info->next = *add;
Packit 90a5c9
            *add = info;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *remoteip_disable_networks(cmd_parms *cmd, void *d,
Packit 90a5c9
                                             int argc, char *const argv[])
Packit 90a5c9
{
Packit 90a5c9
    int i;
Packit 90a5c9
    apr_pool_t *ptemp = cmd->temp_pool;
Packit 90a5c9
    apr_pool_t *p = cmd->pool;
Packit 90a5c9
    remoteip_config_t *conf = ap_get_module_config(ap_server_conf->module_config,
Packit 90a5c9
                                &remoteip_module);
Packit 90a5c9
Packit 90a5c9
    if (argc == 0)
Packit 90a5c9
        return apr_pstrcat(p, cmd->cmd->name, " requires an argument", NULL);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
    for (i=0; i
Packit 90a5c9
        char *addr = apr_pstrdup(ptemp, argv[i]);
Packit 90a5c9
        char *mask;
Packit 90a5c9
        apr_status_t rv;
Packit 90a5c9
        apr_ipsubnet_t **ip = apr_pcalloc(p, sizeof(apr_ipsubnet_t *));
Packit 90a5c9
Packit 90a5c9
        if ((mask = ap_strchr(addr, '/')))
Packit 90a5c9
            *mask++ = '\0';
Packit 90a5c9
Packit 90a5c9
        rv = apr_ipsubnet_create(ip, addr, mask, p);
Packit 90a5c9
Packit 90a5c9
        if (APR_STATUS_IS_EINVAL(rv)) {
Packit 90a5c9
            /* looked nothing like an IP address */
Packit 90a5c9
            return apr_psprintf(p, "ip address '%s' appears to be invalid", addr);
Packit 90a5c9
        }
Packit 90a5c9
        else if (rv != APR_SUCCESS) {
Packit 90a5c9
            return apr_psprintf(p, "ip address '%s' appears to be invalid: %pm",
Packit 90a5c9
                                addr, &rv;;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        *(apr_ipsubnet_t**)apr_array_push(conf->disabled_subnets) = *ip;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int remoteip_hook_post_config(apr_pool_t *pconf, apr_pool_t *plog,
Packit 90a5c9
                               apr_pool_t *ptemp, server_rec *s)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *conf;
Packit 90a5c9
    remoteip_addr_info *info;
Packit 90a5c9
    char buf[INET6_ADDRSTRLEN];
Packit 90a5c9
Packit 90a5c9
    conf = ap_get_module_config(ap_server_conf->module_config,
Packit 90a5c9
                                &remoteip_module);
Packit 90a5c9
Packit 90a5c9
    for (info = conf->proxy_protocol_enabled; info; info = info->next) {
Packit 90a5c9
        apr_sockaddr_ip_getbuf(buf, sizeof(buf), info->addr);
Packit 90a5c9
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(03492)
Packit 90a5c9
                     "RemoteIPProxyProtocol: enabled on %s:%hu", buf, info->addr->port);
Packit 90a5c9
    }
Packit 90a5c9
    for (info = conf->proxy_protocol_disabled; info; info = info->next) {
Packit 90a5c9
        apr_sockaddr_ip_getbuf(buf, sizeof(buf), info->addr);
Packit 90a5c9
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(03494)
Packit 90a5c9
                     "RemoteIPProxyProtocol: disabled on %s:%hu", buf, info->addr->port);
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return OK;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int remoteip_modify_request(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    conn_rec *c = r->connection;
Packit 90a5c9
    remoteip_config_t *config = (remoteip_config_t *)
Packit 90a5c9
        ap_get_module_config(r->server->module_config, &remoteip_module);
Packit 90a5c9
    remoteip_conn_config_t *conn_config = (remoteip_conn_config_t *)
Packit 90a5c9
        ap_get_module_config(r->connection->conn_config, &remoteip_module);
Packit 90a5c9
Packit 90a5c9
    remoteip_req_t *req = NULL;
Packit 90a5c9
    apr_sockaddr_t *temp_sa;
Packit 90a5c9
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
    char *remote;
Packit 90a5c9
    char *proxy_ips = NULL;
Packit 90a5c9
    char *parse_remote;
Packit 90a5c9
    char *eos;
Packit 90a5c9
    unsigned char *addrbyte;
Packit 90a5c9
Packit 90a5c9
    /* If no RemoteIPInternalProxy, RemoteIPInternalProxyList, RemoteIPTrustedProxy
Packit 90a5c9
       or RemoteIPTrustedProxyList directive is configured,
Packit 90a5c9
       all proxies will be considered as external trusted proxies.
Packit 90a5c9
     */
Packit 90a5c9
    void *internal = NULL;
Packit 90a5c9
Packit 90a5c9
    /* No header defined or results from our input filter */
Packit 90a5c9
    if (!config->header_name && !conn_config) {
Packit 90a5c9
        return DECLINED;
Packit 90a5c9
    }
Packit 90a5c9
 
Packit 90a5c9
    /* Easy parsing case - just position the data we already have from PROXY
Packit 90a5c9
       protocol handling allowing it to take precedence and return
Packit 90a5c9
    */
Packit 90a5c9
    if (conn_config) {
Packit 90a5c9
        if (!conn_config->client_addr) {
Packit 90a5c9
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03496)
Packit 90a5c9
                          "RemoteIPProxyProtocol data is missing, but required! Aborting request.");
Packit 90a5c9
            return HTTP_BAD_REQUEST;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        r->useragent_addr = conn_config->client_addr;
Packit 90a5c9
        r->useragent_ip = conn_config->client_ip;
Packit 90a5c9
Packit 90a5c9
        ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
Packit 90a5c9
                      "Using %s as client's IP from PROXY protocol", r->useragent_ip);
Packit 90a5c9
        return OK;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (config->proxymatch_ip) {
Packit 90a5c9
        /* This indicates that a RemoteIPInternalProxy, RemoteIPInternalProxyList, RemoteIPTrustedProxy
Packit 90a5c9
           or RemoteIPTrustedProxyList directive is configured.
Packit 90a5c9
           In this case, default to internal proxy.
Packit 90a5c9
         */
Packit 90a5c9
        internal = (void *) 1;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    remote = (char *) apr_table_get(r->headers_in, config->header_name);
Packit 90a5c9
    if (!remote) {
Packit 90a5c9
        return OK;
Packit 90a5c9
    }
Packit 90a5c9
    remote = apr_pstrdup(r->pool, remote);
Packit 90a5c9
Packit 90a5c9
    temp_sa = r->useragent_addr ? r->useragent_addr : c->client_addr;
Packit 90a5c9
Packit 90a5c9
    while (remote) {
Packit 90a5c9
Packit 90a5c9
        /* verify user agent IP against the trusted proxy list
Packit 90a5c9
         */
Packit 90a5c9
        if (config->proxymatch_ip) {
Packit 90a5c9
            int i;
Packit 90a5c9
            remoteip_proxymatch_t *match;
Packit 90a5c9
            match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts;
Packit 90a5c9
            for (i = 0; i < config->proxymatch_ip->nelts; ++i) {
Packit 90a5c9
                if (apr_ipsubnet_test(match[i].ip, temp_sa)) {
Packit 90a5c9
                    if (internal) {
Packit 90a5c9
                        /* Allow an internal proxy to present an external proxy,
Packit 90a5c9
                           but do not allow an external proxy to present an internal proxy.
Packit 90a5c9
                           In this case, the presented internal proxy will be considered external.
Packit 90a5c9
                         */
Packit 90a5c9
                        internal = match[i].internal;
Packit 90a5c9
                    }
Packit 90a5c9
                    break;
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
            if (i && i >= config->proxymatch_ip->nelts) {
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if ((parse_remote = strrchr(remote, ',')) == NULL) {
Packit 90a5c9
            parse_remote = remote;
Packit 90a5c9
            remote = NULL;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            *(parse_remote++) = '\0';
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        while (*parse_remote == ' ') {
Packit 90a5c9
            ++parse_remote;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        eos = parse_remote + strlen(parse_remote) - 1;
Packit 90a5c9
        while (eos >= parse_remote && *eos == ' ') {
Packit 90a5c9
            *(eos--) = '\0';
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (eos < parse_remote) {
Packit 90a5c9
            if (remote) {
Packit 90a5c9
                *(remote + strlen(remote)) = ',';
Packit 90a5c9
            }
Packit 90a5c9
            else {
Packit 90a5c9
                remote = parse_remote;
Packit 90a5c9
            }
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        /* We map as IPv4 rather than IPv6 for equivalent host names
Packit 90a5c9
         * or IPV4OVERIPV6
Packit 90a5c9
         */
Packit 90a5c9
        rv = apr_sockaddr_info_get(&temp_sa,  parse_remote,
Packit 90a5c9
                                   APR_UNSPEC, temp_sa->port,
Packit 90a5c9
                                   APR_IPV4_ADDR_OK, r->pool);
Packit 90a5c9
        if (rv != APR_SUCCESS) {
Packit 90a5c9
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG,  rv, r, APLOGNO(01568)
Packit 90a5c9
                          "RemoteIP: Header %s value of %s cannot be parsed "
Packit 90a5c9
                          "as a client IP",
Packit 90a5c9
                          config->header_name, parse_remote);
Packit 90a5c9
Packit 90a5c9
            if (remote) {
Packit 90a5c9
                *(remote + strlen(remote)) = ',';
Packit 90a5c9
            }
Packit 90a5c9
            else {
Packit 90a5c9
                remote = parse_remote;
Packit 90a5c9
            }
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        addrbyte = (unsigned char *) &temp_sa->sa.sin.sin_addr;
Packit 90a5c9
Packit 90a5c9
        /* For intranet (Internal proxies) ignore all restrictions below */
Packit 90a5c9
        if (!internal
Packit 90a5c9
              && ((temp_sa->family == APR_INET
Packit 90a5c9
                   /* For internet (non-Internal proxies) deny all
Packit 90a5c9
                    * RFC3330 designated local/private subnets:
Packit 90a5c9
                    * 10.0.0.0/8   169.254.0.0/16  192.168.0.0/16
Packit 90a5c9
                    * 127.0.0.0/8  172.16.0.0/12
Packit 90a5c9
                    */
Packit 90a5c9
                      && (addrbyte[0] == 10
Packit 90a5c9
                       || addrbyte[0] == 127
Packit 90a5c9
                       || (addrbyte[0] == 169 && addrbyte[1] == 254)
Packit 90a5c9
                       || (addrbyte[0] == 172 && (addrbyte[1] & 0xf0) == 16)
Packit 90a5c9
                       || (addrbyte[0] == 192 && addrbyte[1] == 168)))
Packit 90a5c9
#if APR_HAVE_IPV6
Packit 90a5c9
               || (temp_sa->family == APR_INET6
Packit 90a5c9
                   /* For internet (non-Internal proxies) we translated
Packit 90a5c9
                    * IPv4-over-IPv6-mapped addresses as IPv4, above.
Packit 90a5c9
                    * Accept only Global Unicast 2000::/3 defined by RFC4291
Packit 90a5c9
                    */
Packit 90a5c9
                      && ((temp_sa->sa.sin6.sin6_addr.s6_addr[0] & 0xe0) != 0x20))
Packit 90a5c9
#endif
Packit 90a5c9
        )) {
Packit 90a5c9
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG,  rv, r, APLOGNO(01569)
Packit 90a5c9
                          "RemoteIP: Header %s value of %s appears to be "
Packit 90a5c9
                          "a private IP or nonsensical.  Ignored",
Packit 90a5c9
                          config->header_name, parse_remote);
Packit 90a5c9
            if (remote) {
Packit 90a5c9
                *(remote + strlen(remote)) = ',';
Packit 90a5c9
            }
Packit 90a5c9
            else {
Packit 90a5c9
                remote = parse_remote;
Packit 90a5c9
            }
Packit 90a5c9
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        /* save away our results */
Packit 90a5c9
        if (!req) {
Packit 90a5c9
            req = (remoteip_req_t *) apr_palloc(r->pool, sizeof(remoteip_req_t));
Packit 90a5c9
            req->useragent_ip = r->useragent_ip;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        /* Set useragent_ip string */
Packit 90a5c9
        if (!internal) {
Packit 90a5c9
            if (proxy_ips) {
Packit 90a5c9
                proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ",
Packit 90a5c9
                                        req->useragent_ip, NULL);
Packit 90a5c9
            }
Packit 90a5c9
            else {
Packit 90a5c9
                proxy_ips = req->useragent_ip;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        req->useragent_addr = temp_sa;
Packit 90a5c9
        apr_sockaddr_ip_get(&req->useragent_ip, req->useragent_addr);
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* Nothing happened? */
Packit 90a5c9
    if (!req) {
Packit 90a5c9
        return OK;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* Port is not known so set it to zero; otherwise it can be misleading */
Packit 90a5c9
    req->useragent_addr->port = 0;
Packit 90a5c9
Packit 90a5c9
    req->proxied_remote = remote;
Packit 90a5c9
    req->proxy_ips = proxy_ips;
Packit 90a5c9
Packit 90a5c9
    if (req->proxied_remote) {
Packit 90a5c9
        apr_table_setn(r->headers_in, config->header_name,
Packit 90a5c9
                       req->proxied_remote);
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        apr_table_unset(r->headers_in, config->header_name);
Packit 90a5c9
    }
Packit 90a5c9
    if (req->proxy_ips) {
Packit 90a5c9
        apr_table_setn(r->notes, "remoteip-proxy-ip-list", req->proxy_ips);
Packit 90a5c9
        if (config->proxies_header_name) {
Packit 90a5c9
            apr_table_setn(r->headers_in, config->proxies_header_name,
Packit 90a5c9
                           req->proxy_ips);
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    r->useragent_addr = req->useragent_addr;
Packit 90a5c9
    r->useragent_ip = req->useragent_ip;
Packit 90a5c9
Packit 90a5c9
    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
Packit 90a5c9
                  req->proxy_ips
Packit 90a5c9
                      ? "Using %s as client's IP by proxies %s"
Packit 90a5c9
                      : "Using %s as client's IP by internal proxies%s",
Packit 90a5c9
                  req->useragent_ip,
Packit 90a5c9
                  (req->proxy_ips ? req->proxy_ips : ""));
Packit 90a5c9
    return OK;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int remoteip_is_server_port(apr_port_t port)
Packit 90a5c9
{
Packit 90a5c9
    ap_listen_rec *lr;
Packit 90a5c9
Packit 90a5c9
    for (lr = ap_listeners; lr; lr = lr->next) {
Packit 90a5c9
        if (lr->bind_addr && lr->bind_addr->port == port) {
Packit 90a5c9
            return 1;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return 0;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
 * Human readable format:
Packit 90a5c9
 * PROXY {TCP4|TCP6|UNKNOWN} <client-ip-addr> <dest-ip-addr> <client-port> <dest-port><CR><LF>
Packit 90a5c9
 */
Packit 90a5c9
static remoteip_parse_status_t remoteip_process_v1_header(conn_rec *c,
Packit 90a5c9
                                                          remoteip_conn_config_t *conn_conf,
Packit 90a5c9
                                                          proxy_header *hdr, apr_size_t len,
Packit 90a5c9
                                                          apr_size_t *hdr_len)
Packit 90a5c9
{
Packit 90a5c9
    char *end, *word, *host, *valid_addr_chars, *saveptr;
Packit 90a5c9
    char buf[sizeof(hdr->v1.line)];
Packit 90a5c9
    apr_port_t port;
Packit 90a5c9
    apr_status_t ret;
Packit 90a5c9
    apr_int32_t family;
Packit 90a5c9
Packit 90a5c9
#define GET_NEXT_WORD(field) \
Packit 90a5c9
    word = apr_strtok(NULL, " ", &saveptr); \
Packit 90a5c9
    if (!word) { \
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03497) \
Packit 90a5c9
                      "RemoteIPProxyProtocol: no " field " found in header '%s'", \
Packit 90a5c9
                      hdr->v1.line); \
Packit 90a5c9
        return HDR_ERROR; \
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    end = memchr(hdr->v1.line, '\r', len - 1);
Packit 90a5c9
    if (!end || end[1] != '\n') {
Packit 90a5c9
        return HDR_NEED_MORE; /* partial or invalid header */
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    *end = '\0';
Packit 90a5c9
    *hdr_len = end + 2 - hdr->v1.line; /* skip header + CRLF */
Packit 90a5c9
Packit 90a5c9
    /* parse in separate buffer so have the original for error messages */
Packit 90a5c9
    strcpy(buf, hdr->v1.line);
Packit 90a5c9
Packit 90a5c9
    apr_strtok(buf, " ", &saveptr);
Packit 90a5c9
Packit 90a5c9
    /* parse family */
Packit 90a5c9
    GET_NEXT_WORD("family")
Packit 90a5c9
    if (strcmp(word, "UNKNOWN") == 0) {
Packit 90a5c9
        conn_conf->client_addr = c->client_addr;
Packit 90a5c9
        conn_conf->client_ip = c->client_ip;
Packit 90a5c9
        return HDR_DONE;
Packit 90a5c9
    }
Packit 90a5c9
    else if (strcmp(word, "TCP4") == 0) {
Packit 90a5c9
        family = APR_INET;
Packit 90a5c9
        valid_addr_chars = "0123456789.";
Packit 90a5c9
    }
Packit 90a5c9
    else if (strcmp(word, "TCP6") == 0) {
Packit 90a5c9
#if APR_HAVE_IPV6
Packit 90a5c9
        family = APR_INET6;
Packit 90a5c9
        valid_addr_chars = "0123456789abcdefABCDEF:";
Packit 90a5c9
#else
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03498)
Packit 90a5c9
                      "RemoteIPProxyProtocol: Unable to parse v6 address - APR is not compiled with IPv6 support");
Packit 90a5c9
        return HDR_ERROR;
Packit 90a5c9
#endif
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03499)
Packit 90a5c9
                      "RemoteIPProxyProtocol: unknown family '%s' in header '%s'",
Packit 90a5c9
                      word, hdr->v1.line);
Packit 90a5c9
        return HDR_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* parse client-addr */
Packit 90a5c9
    GET_NEXT_WORD("client-address")
Packit 90a5c9
Packit 90a5c9
    if (strspn(word, valid_addr_chars) != strlen(word)) {
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03500)
Packit 90a5c9
                      "RemoteIPProxyProtocol: invalid client-address '%s' found in "
Packit 90a5c9
                      "header '%s'", word, hdr->v1.line);
Packit 90a5c9
        return HDR_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    host = word;
Packit 90a5c9
Packit 90a5c9
    /* parse dest-addr */
Packit 90a5c9
    GET_NEXT_WORD("destination-address")
Packit 90a5c9
Packit 90a5c9
    /* parse client-port */
Packit 90a5c9
    GET_NEXT_WORD("client-port")
Packit 90a5c9
    if (sscanf(word, "%hu", &port) != 1) {
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03501)
Packit 90a5c9
                      "RemoteIPProxyProtocol: error parsing port '%s' in header '%s'",
Packit 90a5c9
                      word, hdr->v1.line);
Packit 90a5c9
        return HDR_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* parse dest-port */
Packit 90a5c9
    /* GET_NEXT_WORD("destination-port") - no-op since we don't care about it */
Packit 90a5c9
Packit 90a5c9
    /* create a socketaddr from the info */
Packit 90a5c9
    ret = apr_sockaddr_info_get(&conn_conf->client_addr, host, family, port, 0,
Packit 90a5c9
                                c->pool);
Packit 90a5c9
    if (ret != APR_SUCCESS) {
Packit 90a5c9
        conn_conf->client_addr = NULL;
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03502)
Packit 90a5c9
                      "RemoteIPProxyProtocol: error converting family '%d', host '%s',"
Packit 90a5c9
                      " and port '%hu' to sockaddr; header was '%s'",
Packit 90a5c9
                      family, host, port, hdr->v1.line);
Packit 90a5c9
        return HDR_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    conn_conf->client_ip = apr_pstrdup(c->pool, host);
Packit 90a5c9
Packit 90a5c9
    return HDR_DONE;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/** Add our filter to the connection if it is requested
Packit 90a5c9
 */
Packit 90a5c9
static int remoteip_hook_pre_connection(conn_rec *c, void *csd)
Packit 90a5c9
{
Packit 90a5c9
    remoteip_config_t *conf;
Packit 90a5c9
    remoteip_conn_config_t *conn_conf;
Packit 90a5c9
    int i;
Packit 90a5c9
Packit 90a5c9
    /* Establish master config in slave connections, so that request processing
Packit 90a5c9
     * finds it. */
Packit 90a5c9
    if (c->master != NULL) {
Packit 90a5c9
        conn_conf = ap_get_module_config(c->master->conn_config, &remoteip_module);
Packit 90a5c9
        if (conn_conf) {
Packit 90a5c9
            ap_set_module_config(c->conn_config, &remoteip_module, conn_conf);
Packit 90a5c9
        }
Packit 90a5c9
        return DECLINED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    conf = ap_get_module_config(ap_server_conf->module_config,
Packit 90a5c9
                                &remoteip_module);
Packit 90a5c9
Packit 90a5c9
    /* check if we're enabled for this connection */
Packit 90a5c9
    if (!remoteip_addr_in_list(conf->proxy_protocol_enabled, c->local_addr)
Packit 90a5c9
        || remoteip_addr_in_list(conf->proxy_protocol_disabled, c->local_addr)) {
Packit 90a5c9
Packit 90a5c9
        return DECLINED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* We are enabled for this IP/port, but check that we aren't
Packit 90a5c9
       explicitly disabled */
Packit 90a5c9
    for (i = 0; i < conf->disabled_subnets->nelts; i++) {
Packit 90a5c9
        apr_ipsubnet_t *ip = ((apr_ipsubnet_t**)conf->disabled_subnets->elts)[i];
Packit 90a5c9
Packit 90a5c9
        if (ip && apr_ipsubnet_test(ip, c->client_addr))
Packit 90a5c9
            return DECLINED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* mod_proxy creates outgoing connections - we don't want those */
Packit 90a5c9
    if (!remoteip_is_server_port(c->local_addr->port)) {
Packit 90a5c9
        return DECLINED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* add our filter */
Packit 90a5c9
    if (!ap_add_input_filter_handle(remoteip_filter, NULL, NULL, c)) {
Packit 90a5c9
        /* XXX: Shouldn't this WARN in log? */
Packit 90a5c9
        return DECLINED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03503)
Packit 90a5c9
                  "RemoteIPProxyProtocol: enabled on connection to %s:%hu",
Packit 90a5c9
                  c->local_ip, c->local_addr->port);
Packit 90a5c9
Packit 90a5c9
    /* this holds the resolved proxy info for this connection */
Packit 90a5c9
    conn_conf = apr_pcalloc(c->pool, sizeof(*conn_conf));
Packit 90a5c9
Packit 90a5c9
    ap_set_module_config(c->conn_config, &remoteip_module, conn_conf);
Packit 90a5c9
Packit 90a5c9
    return OK;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/* Binary format:
Packit 90a5c9
 * <sig><cmd><proto><addr-len><addr>
Packit 90a5c9
 * sig = \x0D \x0A \x0D \x0A \x00 \x0D \x0A \x51 \x55 \x49 \x54 \x0A
Packit 90a5c9
 * cmd = <4-bits-version><4-bits-command>
Packit 90a5c9
 * 4-bits-version = \x02
Packit 90a5c9
 * 4-bits-command = {\x00|\x01}  (\x00 = LOCAL: discard con info; \x01 = PROXY)
Packit 90a5c9
 * proto = <4-bits-family><4-bits-protocol>
Packit 90a5c9
 * 4-bits-family = {\x00|\x01|\x02|\x03}  (AF_UNSPEC, AF_INET, AF_INET6, AF_UNIX)
Packit 90a5c9
 * 4-bits-protocol = {\x00|\x01|\x02}  (UNSPEC, STREAM, DGRAM)
Packit 90a5c9
 */
Packit 90a5c9
static remoteip_parse_status_t remoteip_process_v2_header(conn_rec *c,
Packit 90a5c9
                                              remoteip_conn_config_t *conn_conf,
Packit 90a5c9
                                              proxy_header *hdr)
Packit 90a5c9
{
Packit 90a5c9
    apr_status_t ret;
Packit 90a5c9
Packit 90a5c9
    switch (hdr->v2.ver_cmd & 0xF) {
Packit 90a5c9
        case 0x01: /* PROXY command */
Packit 90a5c9
            switch (hdr->v2.fam) {
Packit 90a5c9
                case 0x11:  /* TCPv4 */
Packit 90a5c9
                    ret = apr_sockaddr_info_get(&conn_conf->client_addr, NULL,
Packit 90a5c9
                                                APR_INET,
Packit 90a5c9
                                                ntohs(hdr->v2.addr.ip4.src_port),
Packit 90a5c9
                                                0, c->pool);
Packit 90a5c9
                    if (ret != APR_SUCCESS) {
Packit 90a5c9
                        conn_conf->client_addr = NULL;
Packit 90a5c9
                        ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03504)
Packit 90a5c9
                                      "RemoteIPPProxyProtocol: error creating sockaddr");
Packit 90a5c9
                        return HDR_ERROR;
Packit 90a5c9
                    }
Packit 90a5c9
Packit 90a5c9
                    conn_conf->client_addr->sa.sin.sin_addr.s_addr =
Packit 90a5c9
                            hdr->v2.addr.ip4.src_addr;
Packit 90a5c9
                    break;
Packit 90a5c9
Packit 90a5c9
                case 0x21:  /* TCPv6 */
Packit 90a5c9
#if APR_HAVE_IPV6
Packit 90a5c9
                    ret = apr_sockaddr_info_get(&conn_conf->client_addr, NULL,
Packit 90a5c9
                                                APR_INET6,
Packit 90a5c9
                                                ntohs(hdr->v2.addr.ip6.src_port),
Packit 90a5c9
                                                0, c->pool);
Packit 90a5c9
                    if (ret != APR_SUCCESS) {
Packit 90a5c9
                        conn_conf->client_addr = NULL;
Packit 90a5c9
                        ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03505)
Packit 90a5c9
                                      "RemoteIPProxyProtocol: error creating sockaddr");
Packit 90a5c9
                        return HDR_ERROR;
Packit 90a5c9
                    }
Packit 90a5c9
                    memcpy(&conn_conf->client_addr->sa.sin6.sin6_addr.s6_addr,
Packit 90a5c9
                           hdr->v2.addr.ip6.src_addr, 16);
Packit 90a5c9
                    break;
Packit 90a5c9
#else
Packit 90a5c9
                    ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03506)
Packit 90a5c9
                                  "RemoteIPProxyProtocol: APR is not compiled with IPv6 support");
Packit 90a5c9
                    return HDR_ERROR;
Packit 90a5c9
#endif
Packit 90a5c9
                default:
Packit df9dbe
                    /* unsupported protocol */
Packit df9dbe
                    ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183)
Packit df9dbe
                                  "RemoteIPProxyProtocol: unsupported protocol %.2hx",
Packit df9dbe
                                  (unsigned short)hdr->v2.fam);
Packit df9dbe
                    return HDR_ERROR;
Packit 90a5c9
            }
Packit 90a5c9
            break;  /* we got a sockaddr now */
Packit 90a5c9
        default:
Packit 90a5c9
            /* not a supported command */
Packit 90a5c9
            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03507)
Packit 90a5c9
                          "RemoteIPProxyProtocol: unsupported command %.2hx",
Packit 90a5c9
                          (unsigned short)hdr->v2.ver_cmd);
Packit 90a5c9
            return HDR_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* got address - compute the client_ip from it */
Packit 90a5c9
    ret = apr_sockaddr_ip_get(&conn_conf->client_ip, conn_conf->client_addr);
Packit 90a5c9
    if (ret != APR_SUCCESS) {
Packit 90a5c9
        conn_conf->client_addr = NULL;
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03508)
Packit 90a5c9
                      "RemoteIPProxyProtocol: error converting address to string");
Packit 90a5c9
        return HDR_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return HDR_DONE;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/** Return length for a v2 protocol header. */
Packit 90a5c9
static apr_size_t remoteip_get_v2_len(proxy_header *hdr)
Packit 90a5c9
{
Packit 90a5c9
    return ntohs(hdr->v2.len);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/** Determine if this is a v1 or v2 PROXY header.
Packit 90a5c9
 */
Packit 90a5c9
static int remoteip_determine_version(conn_rec *c, const char *ptr)
Packit 90a5c9
{
Packit 90a5c9
    proxy_header *hdr = (proxy_header *) ptr;
Packit 90a5c9
Packit 90a5c9
    /* assert len >= 14 */
Packit 90a5c9
Packit 90a5c9
    if (memcmp(&hdr->v2, v2sig, sizeof(v2sig)) == 0 &&
Packit 90a5c9
        (hdr->v2.ver_cmd & 0xF0) == 0x20) {
Packit 90a5c9
        return 2;
Packit 90a5c9
    }
Packit 90a5c9
    else if (memcmp(hdr->v1.line, "PROXY ", 6) == 0) {
Packit 90a5c9
        return 1;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        return -1;
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/* Capture the first bytes on the protocol and parse the PROXY protocol header.
Packit 90a5c9
 * Removes itself when the header is complete.
Packit 90a5c9
 */
Packit 90a5c9
static apr_status_t remoteip_input_filter(ap_filter_t *f,
Packit 90a5c9
                                    apr_bucket_brigade *bb_out,
Packit 90a5c9
                                    ap_input_mode_t mode,
Packit 90a5c9
                                    apr_read_type_e block,
Packit 90a5c9
                                    apr_off_t readbytes)
Packit 90a5c9
{
Packit 90a5c9
    apr_status_t ret;
Packit 90a5c9
    remoteip_filter_context *ctx = f->ctx;
Packit 90a5c9
    remoteip_conn_config_t *conn_conf;
Packit 90a5c9
    apr_bucket *b;
Packit 90a5c9
    remoteip_parse_status_t psts = HDR_NEED_MORE;
Packit 90a5c9
    const char *ptr;
Packit 90a5c9
    apr_size_t len;
Packit 90a5c9
Packit 90a5c9
    if (f->c->aborted) {
Packit 90a5c9
        return APR_ECONNABORTED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* allocate/retrieve the context that holds our header */
Packit 90a5c9
    if (!ctx) {
Packit 90a5c9
        ctx = f->ctx = apr_palloc(f->c->pool, sizeof(*ctx));
Packit 90a5c9
        ctx->rcvd = 0;
Packit 90a5c9
        ctx->need = MIN_HDR_LEN;
Packit 90a5c9
        ctx->version = 0;
Packit 90a5c9
        ctx->mode = AP_MODE_READBYTES;
Packit 90a5c9
        ctx->bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
Packit 90a5c9
        ctx->done = 0;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (ctx->done) {
Packit 90a5c9
        /* Note: because we're a connection filter we can't remove ourselves
Packit 90a5c9
         * when we're done, so we have to stay in the chain and just go into
Packit 90a5c9
         * passthrough mode.
Packit 90a5c9
         */
Packit 90a5c9
        return ap_get_brigade(f->next, bb_out, mode, block, readbytes);
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    conn_conf = ap_get_module_config(f->c->conn_config, &remoteip_module);
Packit 90a5c9
Packit 90a5c9
    /* try to read a header's worth of data */
Packit 90a5c9
    while (!ctx->done) {
Packit 90a5c9
        if (APR_BRIGADE_EMPTY(ctx->bb)) {
Packit df9dbe
            apr_off_t got, want = ctx->need - ctx->rcvd;
Packit df9dbe
Packit df9dbe
            ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want);
Packit 90a5c9
            if (ret != APR_SUCCESS) {
Packit df9dbe
                ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10184)
Packit df9dbe
                              "failed reading input");
Packit 90a5c9
                return ret;
Packit 90a5c9
            }
Packit df9dbe
Packit df9dbe
            ret = apr_brigade_length(ctx->bb, 1, &got;;
Packit df9dbe
            if (ret || got > want) {
Packit df9dbe
                ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10185)
Packit df9dbe
                              "RemoteIPProxyProtocol header too long, "
Packit df9dbe
                              "got %" APR_OFF_T_FMT " expected %" APR_OFF_T_FMT,
Packit df9dbe
                              got, want);
Packit df9dbe
                f->c->aborted = 1;
Packit df9dbe
                return APR_ECONNABORTED;
Packit df9dbe
            }
Packit 90a5c9
        }
Packit 90a5c9
        if (APR_BRIGADE_EMPTY(ctx->bb)) {
Packit 90a5c9
            return block == APR_NONBLOCK_READ ? APR_SUCCESS : APR_EOF;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        while (!ctx->done && !APR_BRIGADE_EMPTY(ctx->bb)) {
Packit 90a5c9
            b = APR_BRIGADE_FIRST(ctx->bb);
Packit 90a5c9
Packit 90a5c9
            ret = apr_bucket_read(b, &ptr, &len, block);
Packit 90a5c9
            if (APR_STATUS_IS_EAGAIN(ret) && block == APR_NONBLOCK_READ) {
Packit 90a5c9
                return APR_SUCCESS;
Packit 90a5c9
            }
Packit 90a5c9
            if (ret != APR_SUCCESS) {
Packit 90a5c9
                return ret;
Packit 90a5c9
            }
Packit 90a5c9
Packit 90a5c9
            memcpy(ctx->header + ctx->rcvd, ptr, len);
Packit 90a5c9
            ctx->rcvd += len;
Packit 90a5c9
Packit 90a5c9
            apr_bucket_delete(b);
Packit 90a5c9
            psts = HDR_NEED_MORE;
Packit 90a5c9
Packit 90a5c9
            if (ctx->version == 0) {
Packit 90a5c9
                /* reading initial chunk */
Packit 90a5c9
                if (ctx->rcvd >= MIN_HDR_LEN) {
Packit 90a5c9
                    ctx->version = remoteip_determine_version(f->c, ctx->header);
Packit 90a5c9
                    if (ctx->version < 0) {
Packit 90a5c9
                        psts = HDR_ERROR;
Packit 90a5c9
                    }
Packit 90a5c9
                    else if (ctx->version == 1) {
Packit 90a5c9
                        ctx->mode = AP_MODE_GETLINE;
Packit 90a5c9
                        ctx->need = sizeof(proxy_v1);
Packit 90a5c9
                    }
Packit 90a5c9
                    else if (ctx->version == 2) {
Packit 90a5c9
                        ctx->need = MIN_V2_HDR_LEN;
Packit 90a5c9
                    }
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
            else if (ctx->version == 1) {
Packit 90a5c9
                psts = remoteip_process_v1_header(f->c, conn_conf,
Packit 90a5c9
                                            (proxy_header *) ctx->header,
Packit 90a5c9
                                            ctx->rcvd, &ctx->need);
Packit 90a5c9
            }
Packit 90a5c9
            else if (ctx->version == 2) {
Packit 90a5c9
                if (ctx->rcvd >= MIN_V2_HDR_LEN) {
Packit 90a5c9
                    ctx->need = MIN_V2_HDR_LEN +
Packit 90a5c9
                        remoteip_get_v2_len((proxy_header *) ctx->header);
Packit df9dbe
                    if (ctx->need > sizeof(proxy_v2)) {
Packit df9dbe
                        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(10186)
Packit df9dbe
                                      "RemoteIPProxyProtocol protocol header length too long");
Packit df9dbe
                        f->c->aborted = 1;
Packit df9dbe
                        apr_brigade_destroy(ctx->bb);
Packit df9dbe
                        return APR_ECONNABORTED;
Packit df9dbe
                    }
Packit 90a5c9
                }
Packit 90a5c9
                if (ctx->rcvd >= ctx->need) {
Packit 90a5c9
                    psts = remoteip_process_v2_header(f->c, conn_conf,
Packit 90a5c9
                                                (proxy_header *) ctx->header);
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
            else {
Packit 90a5c9
                ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(03509)
Packit 90a5c9
                              "RemoteIPProxyProtocol: internal error: unknown version "
Packit 90a5c9
                              "%d", ctx->version);
Packit 90a5c9
                f->c->aborted = 1;
Packit 90a5c9
                apr_brigade_destroy(ctx->bb);
Packit 90a5c9
                return APR_ECONNABORTED;
Packit 90a5c9
            }
Packit 90a5c9
Packit 90a5c9
            switch (psts) {
Packit 90a5c9
                case HDR_ERROR:
Packit 90a5c9
                    f->c->aborted = 1;
Packit 90a5c9
                    apr_brigade_destroy(ctx->bb);
Packit 90a5c9
                    return APR_ECONNABORTED;
Packit 90a5c9
Packit 90a5c9
                case HDR_DONE:
Packit 90a5c9
                    ctx->done = 1;
Packit 90a5c9
                    break;
Packit 90a5c9
Packit 90a5c9
                case HDR_NEED_MORE:
Packit 90a5c9
                    break;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* we only get here when done == 1 */
Packit 90a5c9
    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c, APLOGNO(03511)
Packit 90a5c9
                  "RemoteIPProxyProtocol: received valid PROXY header: %s:%hu",
Packit 90a5c9
                  conn_conf->client_ip, conn_conf->client_addr->port);
Packit 90a5c9
Packit 90a5c9
    if (ctx->rcvd > ctx->need || !APR_BRIGADE_EMPTY(ctx->bb)) {
Packit 90a5c9
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(03513)
Packit 90a5c9
                      "RemoteIPProxyProtocol: internal error: have data left over; "
Packit 90a5c9
                      " need=%" APR_SIZE_T_FMT ", rcvd=%" APR_SIZE_T_FMT
Packit 90a5c9
                      ", brigade-empty=%d", ctx->need, ctx->rcvd,
Packit 90a5c9
                      APR_BRIGADE_EMPTY(ctx->bb));
Packit 90a5c9
        f->c->aborted = 1;
Packit 90a5c9
        apr_brigade_destroy(ctx->bb);
Packit 90a5c9
        return APR_ECONNABORTED;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    /* clean up */
Packit 90a5c9
    apr_brigade_destroy(ctx->bb);
Packit 90a5c9
    ctx->bb = NULL;
Packit 90a5c9
Packit 90a5c9
    /* now do the real read for the upper layer */
Packit 90a5c9
    return ap_get_brigade(f->next, bb_out, mode, block, readbytes);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const command_rec remoteip_cmds[] =
Packit 90a5c9
{
Packit 90a5c9
    AP_INIT_TAKE1("RemoteIPHeader", header_name_set, NULL, RSRC_CONF,
Packit 90a5c9
                  "Specifies a request header to trust as the client IP, "
Packit 90a5c9
                  "e.g. X-Forwarded-For"),
Packit 90a5c9
    AP_INIT_TAKE1("RemoteIPProxiesHeader", proxies_header_name_set,
Packit 90a5c9
                  NULL, RSRC_CONF,
Packit 90a5c9
                  "Specifies a request header to record proxy IP's, "
Packit 90a5c9
                  "e.g. X-Forwarded-By; if not given then do not record"),
Packit 90a5c9
    AP_INIT_ITERATE("RemoteIPTrustedProxy", proxies_set, 0, RSRC_CONF,
Packit 90a5c9
                    "Specifies one or more proxies which are trusted "
Packit 90a5c9
                    "to present IP headers"),
Packit 90a5c9
    AP_INIT_ITERATE("RemoteIPInternalProxy", proxies_set, (void*)1, RSRC_CONF,
Packit 90a5c9
                    "Specifies one or more internal (transparent) proxies "
Packit 90a5c9
                    "which are trusted to present IP headers"),
Packit 90a5c9
    AP_INIT_TAKE1("RemoteIPTrustedProxyList", proxylist_read, 0,
Packit 90a5c9
                  RSRC_CONF | EXEC_ON_READ,
Packit 90a5c9
                  "The filename to read the list of trusted proxies, "
Packit 90a5c9
                  "see the RemoteIPTrustedProxy directive"),
Packit 90a5c9
    AP_INIT_TAKE1("RemoteIPInternalProxyList", proxylist_read, (void*)1,
Packit 90a5c9
                  RSRC_CONF | EXEC_ON_READ,
Packit 90a5c9
                  "The filename to read the list of internal proxies, "
Packit 90a5c9
                  "see the RemoteIPInternalProxy directive"),
Packit 90a5c9
    AP_INIT_FLAG("RemoteIPProxyProtocol", remoteip_enable_proxy_protocol, NULL,
Packit 90a5c9
                  RSRC_CONF, "Enable PROXY protocol handling ('on', 'off')"),
Packit 90a5c9
    AP_INIT_TAKE_ARGV("RemoteIPProxyProtocolExceptions",
Packit 90a5c9
                  remoteip_disable_networks, NULL, RSRC_CONF, "Disable PROXY "
Packit 90a5c9
                  "protocol handling for this list of networks in CIDR format"),
Packit 90a5c9
    { NULL }
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
static void register_hooks(apr_pool_t *p)
Packit 90a5c9
{
Packit 90a5c9
    /* mod_ssl is CONNECTION + 5, so we want something higher (earlier);
Packit 90a5c9
     * mod_reqtimeout is CONNECTION + 8, so we want something lower (later) */
Packit 90a5c9
    remoteip_filter = 
Packit 90a5c9
        ap_register_input_filter("REMOTEIP_INPUT", remoteip_input_filter, NULL,
Packit 90a5c9
                                 AP_FTYPE_CONNECTION + 7);
Packit 90a5c9
Packit 90a5c9
    ap_hook_post_config(remoteip_hook_post_config, NULL, NULL, APR_HOOK_MIDDLE);
Packit 90a5c9
    ap_hook_pre_connection(remoteip_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
Packit 90a5c9
    ap_hook_post_read_request(remoteip_modify_request, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE_MODULE(remoteip) = {
Packit 90a5c9
    STANDARD20_MODULE_STUFF,
Packit 90a5c9
    NULL,                          /* create per-directory config structure */
Packit 90a5c9
    NULL,                          /* merge per-directory config structures */
Packit 90a5c9
    create_remoteip_server_config, /* create per-server config structure */
Packit 90a5c9
    merge_remoteip_server_config,  /* merge per-server config structures */
Packit 90a5c9
    remoteip_cmds,                 /* command apr_table_t */
Packit 90a5c9
    register_hooks                 /* register hooks */
Packit 90a5c9
};