Blame apache2/msc_geo.c

Packit Service 384592
/*
Packit Service 384592
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
Packit Service 384592
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
Packit Service 384592
*
Packit Service 384592
* You may not use this file except in compliance with
Packit Service 384592
* the License.  You may obtain a copy of the License at
Packit Service 384592
*
Packit Service 384592
*     http://www.apache.org/licenses/LICENSE-2.0
Packit Service 384592
*
Packit Service 384592
* If any of the files related to licensing are missing or if you have any
Packit Service 384592
* other questions related to licensing please contact Trustwave Holdings, Inc.
Packit Service 384592
* directly using the email address security@modsecurity.org.
Packit Service 384592
*/
Packit Service 384592
Packit Service 384592
#include "msc_geo.h"
Packit Service 384592
Packit Service 384592
Packit Service 384592
/* -- Lookup Tables -- */
Packit Service 384592
Packit Service 384592
static const char geo_country_code[GEO_COUNTRY_LAST + 1][4] = {
Packit Service 384592
    "--",
Packit Service 384592
    "AP","EU","AD","AE","AF","AG","AI","AL","AM","AN",
Packit Service 384592
    "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
Packit Service 384592
    "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
Packit Service 384592
    "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
Packit Service 384592
    "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
Packit Service 384592
    "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
Packit Service 384592
    "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
Packit Service 384592
    "FK","FM","FO","FR","FX","GA","GB","GD","GE","GF",
Packit Service 384592
    "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
Packit Service 384592
    "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
Packit Service 384592
    "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
Packit Service 384592
    "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
Packit Service 384592
    "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
Packit Service 384592
    "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
Packit Service 384592
    "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
Packit Service 384592
    "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
Packit Service 384592
    "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
Packit Service 384592
    "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
Packit Service 384592
    "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
Packit Service 384592
    "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
Packit Service 384592
    "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
Packit Service 384592
    "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
Packit Service 384592
    "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
Packit Service 384592
    "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
Packit Service 384592
    "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE"
Packit Service 384592
};
Packit Service 384592
Packit Service 384592
static const char geo_country_code3[GEO_COUNTRY_LAST + 1][4] = {
Packit Service 384592
    "--",
Packit Service 384592
    "AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT",
Packit Service 384592
    "AGO","AQ","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
Packit Service 384592
    "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
Packit Service 384592
    "BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC","COD",
Packit Service 384592
    "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
Packit Service 384592
    "CUB","CPV","CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
Packit Service 384592
    "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
Packit Service 384592
    "FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD","GEO","GUF",
Packit Service 384592
    "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM",
Packit Service 384592
    "GUM","GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN",
Packit Service 384592
    "IRL","ISR","IND","IO","IRQ","IRN","ISL","ITA","JAM","JOR",
Packit Service 384592
    "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
Packit Service 384592
    "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
Packit Service 384592
    "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
Packit Service 384592
    "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
Packit Service 384592
    "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
Packit Service 384592
    "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
Packit Service 384592
    "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
Packit Service 384592
    "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
Packit Service 384592
    "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
Packit Service 384592
    "SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF","TGO","THA",
Packit Service 384592
    "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
Packit Service 384592
    "TZA","UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN",
Packit Service 384592
    "VGB","VIR","VNM","VUT","WLF","WSM","YEM","YT","SRB","ZAF",
Packit Service 384592
    "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY"
Packit Service 384592
};
Packit Service 384592
Packit Service 384592
static const char *const geo_country_name[GEO_COUNTRY_LAST + 1] = {
Packit Service 384592
    "N/A",
Packit Service 384592
    "Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
Packit Service 384592
    "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
Packit Service 384592
    "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
Packit Service 384592
    "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
Packit Service 384592
    "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
Packit Service 384592
    "Cuba","Cape Verde","Christmas Island","Cyprus","Czechia","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
Packit Service 384592
    "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
Packit Service 384592
    "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
Packit Service 384592
    "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
Packit Service 384592
    "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
Packit Service 384592
    "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
Packit Service 384592
    "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
Packit Service 384592
    "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
Packit Service 384592
    "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
Packit Service 384592
    "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
Packit Service 384592
    "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
Packit Service 384592
    "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
Packit Service 384592
    "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
Packit Service 384592
    "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
Packit Service 384592
    "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
Packit Service 384592
    "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
Packit Service 384592
    "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
Packit Service 384592
    "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
Packit Service 384592
    "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
Packit Service 384592
    "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey"
Packit Service 384592
};
Packit Service 384592
Packit Service 384592
static const char geo_country_continent[GEO_COUNTRY_LAST + 1][4] = {
Packit Service 384592
    "--",
Packit Service 384592
    "AS","EU","EU","AS","AS","SA","SA","EU","AS","SA",
Packit Service 384592
    "AF","AN","SA","OC","EU","OC","SA","AS","EU","SA",
Packit Service 384592
    "AS","EU","AF","EU","AS","AF","AF","SA","AS","SA",
Packit Service 384592
    "SA","SA","AS","AF","AF","EU","SA","NA","AS","AF",
Packit Service 384592
    "AF","AF","EU","AF","OC","SA","AF","AS","SA","SA",
Packit Service 384592
    "SA","AF","AS","AS","EU","EU","AF","EU","SA","SA",
Packit Service 384592
    "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
Packit Service 384592
    "SA","OC","EU","EU","EU","AF","EU","SA","AS","SA",
Packit Service 384592
    "AF","EU","SA","AF","AF","SA","AF","EU","SA","SA",
Packit Service 384592
    "OC","AF","SA","AS","AF","SA","EU","SA","EU","AS",
Packit Service 384592
    "EU","AS","AS","AS","AS","AS","EU","EU","SA","AS",
Packit Service 384592
    "AS","AF","AS","AS","OC","AF","SA","AS","AS","AS",
Packit Service 384592
    "SA","AS","AS","AS","SA","EU","AS","AF","AF","EU",
Packit Service 384592
    "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
Packit Service 384592
    "AS","AS","AS","OC","SA","AF","SA","EU","AF","AS",
Packit Service 384592
    "AF","NA","AS","AF","AF","OC","AF","OC","AF","SA",
Packit Service 384592
    "EU","EU","AS","OC","OC","OC","AS","SA","SA","OC",
Packit Service 384592
    "OC","AS","AS","EU","SA","OC","SA","AS","EU","OC",
Packit Service 384592
    "SA","AS","AF","EU","AS","AF","AS","OC","AF","AF",
Packit Service 384592
    "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
Packit Service 384592
    "SA","AF","SA","AS","AF","SA","AF","AF","AF","AS",
Packit Service 384592
    "AS","OC","AS","AF","OC","AS","AS","SA","OC","AS",
Packit Service 384592
    "AF","EU","AF","OC","NA","SA","AS","EU","SA","SA",
Packit Service 384592
    "SA","SA","AS","OC","OC","OC","AS","AF","EU","AF",
Packit Service 384592
    "AF","EU","AF","--","--","--","EU","EU","EU","EU"
Packit Service 384592
};
Packit Service 384592
Packit Service 384592
typedef enum {
Packit Service 384592
GEOIP_COUNTRY_EDITION     = 1,
Packit Service 384592
GEOIP_REGION_EDITION_REV0 = 7,
Packit Service 384592
GEOIP_CITY_EDITION_REV0   = 6,
Packit Service 384592
GEOIP_ORG_EDITION         = 5,
Packit Service 384592
GEOIP_ISP_EDITION         = 4,
Packit Service 384592
GEOIP_CITY_EDITION_REV1   = 2,
Packit Service 384592
GEOIP_REGION_EDITION_REV1 = 3,
Packit Service 384592
GEOIP_PROXY_EDITION       = 8,
Packit Service 384592
GEOIP_ASNUM_EDITION       = 9,
Packit Service 384592
GEOIP_NETSPEED_EDITION    = 10,
Packit Service 384592
GEOIP_DOMAIN_EDITION      = 11
Packit Service 384592
} GeoIPDBTypes;
Packit Service 384592
Packit Service 384592
static void create_segments(geo_db *geo) {
Packit Service 384592
    int i, j;
Packit Service 384592
    unsigned char delim[3];
Packit Service 384592
    unsigned char buf[GEO_SEGMENT_RECORD_LENGTH];
Packit Service 384592
    apr_size_t nbytes;
Packit Service 384592
    apr_off_t offset;
Packit Service 384592
Packit Service 384592
    geo->ctry_offset = 0;
Packit Service 384592
Packit Service 384592
    geo->dbtype = GEOIP_COUNTRY_EDITION;
Packit Service 384592
    offset = -3l;
Packit Service 384592
    apr_file_seek(geo->db, APR_END, &offset);
Packit Service 384592
Packit Service 384592
    for (i = 0; i < GEO_STRUCT_INFO_MAX_SIZE; i++) {
Packit Service 384592
Packit Service 384592
        apr_file_read_full(geo->db, &delim, 3, &nbytes);
Packit Service 384592
Packit Service 384592
        if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
Packit Service 384592
            apr_file_read_full(geo->db, &geo->dbtype, 1, &nbytes);
Packit Service 384592
            if (geo->dbtype >= 106) {
Packit Service 384592
                geo->dbtype -= 105;
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            if (geo->dbtype == GEOIP_REGION_EDITION_REV0) {
Packit Service 384592
                geo->ctry_offset = GEO_STATE_BEGIN_REV0;
Packit Service 384592
            } else if (geo->dbtype == GEOIP_REGION_EDITION_REV1) {
Packit Service 384592
                geo->ctry_offset = GEO_STATE_BEGIN_REV1;
Packit Service 384592
            } else if (geo->dbtype == GEOIP_CITY_EDITION_REV0 ||
Packit Service 384592
                                 geo->dbtype == GEOIP_CITY_EDITION_REV1 ||
Packit Service 384592
                                 geo->dbtype == GEOIP_ORG_EDITION ||
Packit Service 384592
                                 geo->dbtype == GEOIP_ISP_EDITION ||
Packit Service 384592
                                 geo->dbtype == GEOIP_ASNUM_EDITION) {
Packit Service 384592
                geo->ctry_offset = 0;
Packit Service 384592
                apr_file_read_full(geo->db, &buf, GEO_SEGMENT_RECORD_LENGTH, &nbytes);
Packit Service 384592
                for (j = 0; j < GEO_SEGMENT_RECORD_LENGTH; j++) {
Packit Service 384592
                    geo->ctry_offset += (buf[j] << (j * 8));
Packit Service 384592
                }
Packit Service 384592
            }
Packit Service 384592
            break;
Packit Service 384592
        } else {
Packit Service 384592
            offset = -4l;
Packit Service 384592
            apr_file_seek(geo->db, APR_CUR, &offset);
Packit Service 384592
        }
Packit Service 384592
    }
Packit Service 384592
    if (geo->dbtype == GEOIP_COUNTRY_EDITION ||
Packit Service 384592
            geo->dbtype == GEOIP_PROXY_EDITION ||
Packit Service 384592
            geo->dbtype == GEOIP_NETSPEED_EDITION) {
Packit Service 384592
        geo->ctry_offset = GEO_COUNTRY_BEGIN;
Packit Service 384592
    }
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
static int db_open(directory_config *dcfg, char **error_msg)
Packit Service 384592
{
Packit Service 384592
    char errstr[1024];
Packit Service 384592
    apr_pool_t *mp = dcfg->mp;
Packit Service 384592
    geo_db *geo = dcfg->geo;
Packit Service 384592
    apr_status_t rc;
Packit Service 384592
Packit Service 384592
    #ifdef DEBUG_CONF
Packit Service 384592
    fprintf(stderr, "GEO: Initializing geo DB \"%s\".\n", geo->dbfn);
Packit Service 384592
    #endif
Packit Service 384592
Packit Service 384592
    if ((rc = apr_file_open(&geo->db, geo->dbfn, APR_READ, APR_OS_DEFAULT, mp)) != APR_SUCCESS) {
Packit Service 384592
        *error_msg = apr_psprintf(mp, "Could not open geo database \"%s\": %s", geo->dbfn, apr_strerror(rc, errstr, 1024));
Packit Service 384592
        return 0;
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    create_segments(geo);
Packit Service 384592
    return 1;
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
static int field_length(const char *field, int maxlen)
Packit Service 384592
{
Packit Service 384592
    int i;
Packit Service 384592
Packit Service 384592
    if (field == NULL) {
Packit Service 384592
        return 0;
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    for (i = 0; i < maxlen; i++) {
Packit Service 384592
        if (field[i] == '\0') {
Packit Service 384592
            break;
Packit Service 384592
        }
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    return i;
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
/**
Packit Service 384592
 * Initialise Geo data structure
Packit Service 384592
 */
Packit Service 384592
int geo_init(directory_config *dcfg, const char *dbfn, char **error_msg)
Packit Service 384592
{
Packit Service 384592
    *error_msg = NULL;
Packit Service 384592
Packit Service 384592
    if ((dcfg->geo == NULL) || (dcfg->geo == NOT_SET_P)) {
Packit Service 384592
        dcfg->geo = apr_pcalloc(dcfg->mp, sizeof(geo_db));
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    dcfg->geo->db = NULL;
Packit Service 384592
    dcfg->geo->dbfn = apr_pstrdup(dcfg->mp, dbfn);
Packit Service 384592
    dcfg->geo->dbtype = 0;
Packit Service 384592
    dcfg->geo->ctry_offset = 0;
Packit Service 384592
Packit Service 384592
    return db_open(dcfg, error_msg);
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
/**
Packit Service 384592
 * Perform geographical lookup on target.
Packit Service 384592
 */
Packit Service 384592
int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **error_msg)
Packit Service 384592
{
Packit Service 384592
    apr_sockaddr_t *addr;
Packit Service 384592
    long ipnum = 0;
Packit Service 384592
    char *targetip = NULL;
Packit Service 384592
    geo_db *geo = msr->txcfg->geo;
Packit Service 384592
    char errstr[1024];
Packit Service 384592
    unsigned char buf[2* GEO_MAX_RECORD_LEN];
Packit Service 384592
    const int reclen = 3; /* Algorithm needs changed if this changes */
Packit Service 384592
    apr_size_t nbytes;
Packit Service 384592
    unsigned int rec_val = 0;
Packit Service 384592
    apr_off_t seekto = 0;
Packit Service 384592
    apr_status_t ret;
Packit Service 384592
    int rc;
Packit Service 384592
    int country = 0;
Packit Service 384592
    int level;
Packit Service 384592
    double dtmp;
Packit Service 384592
    int itmp;
Packit Service 384592
Packit Service 384592
    *error_msg = NULL;
Packit Service 384592
Packit Service 384592
    /* init */
Packit Service 384592
    georec->country_code = geo_country_code[0];
Packit Service 384592
    georec->country_code3 = geo_country_code3[0];
Packit Service 384592
    georec->country_name = geo_country_name[0];
Packit Service 384592
    georec->country_continent = geo_country_continent[0];
Packit Service 384592
    georec->region = "";
Packit Service 384592
    georec->city = "";
Packit Service 384592
    georec->postal_code = "";
Packit Service 384592
    georec->latitude = 0;
Packit Service 384592
    georec->longitude = 0;
Packit Service 384592
    georec->dma_code = 0;
Packit Service 384592
    georec->area_code = 0;
Packit Service 384592
Packit Service 384592
    if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
        msr_log(msr, 9, "GEO: Looking up \"%s\".", log_escape(msr->mp, target));
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    /* NOTE: This only works with ipv4 */
Packit Service 384592
    if ((rc = apr_sockaddr_info_get(&addr, target, APR_INET, 0, 0, msr->mp)) != APR_SUCCESS) {
Packit Service 384592
Packit Service 384592
        *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" failed: %s", log_escape(msr->mp, target), apr_strerror(rc, errstr, 1024));
Packit Service 384592
        msr_log(msr, 4, "%s", *error_msg);
Packit Service 384592
        return 0;
Packit Service 384592
    }
Packit Service 384592
    if ((rc = apr_sockaddr_ip_get(&targetip, addr)) != APR_SUCCESS) {
Packit Service 384592
        *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" failed: %s", log_escape(msr->mp, target), apr_strerror(rc, errstr, 1024));
Packit Service 384592
        msr_log(msr, 4, "%s", *error_msg);
Packit Service 384592
        return 0;
Packit Service 384592
    };
Packit Service 384592
Packit Service 384592
    /* Why is this in host byte order? */
Packit Service 384592
    ipnum = ntohl(addr->sa.sin.sin_addr.s_addr);
Packit Service 384592
Packit Service 384592
    if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
        msr_log(msr, 9, "GEO: Using address \"%s\" (0x%08lx). %lu", targetip, ipnum, ipnum);
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    ret = apr_global_mutex_lock(msr->modsecurity->geo_lock);
Packit Service 384592
    if (ret != APR_SUCCESS) {
Packit Service 384592
        msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
Packit Service 384592
                get_apr_error(msr->mp, ret));
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    for (level = 31; level >= 0; level--) {
Packit Service 384592
        /* Read the record */
Packit Service 384592
        seekto = 2 * reclen * rec_val;
Packit Service 384592
        apr_file_seek(geo->db, APR_SET, &seekto);
Packit Service 384592
        /* TODO: check rc */
Packit Service 384592
        rc = apr_file_read_full(geo->db, &buf, (2 * reclen), &nbytes);
Packit Service 384592
Packit Service 384592
        /* NOTE: This is hard-coded for size 3 records */
Packit Service 384592
        /* Left */
Packit Service 384592
        if ((ipnum & (1 << level)) == 0) {
Packit Service 384592
            rec_val =   (buf[3*0 + 0] << (0*8)) +
Packit Service 384592
                        (buf[3*0 + 1] << (1*8)) +
Packit Service 384592
                        (buf[3*0 + 2] << (2*8));
Packit Service 384592
        }
Packit Service 384592
        /* Right */
Packit Service 384592
        else {
Packit Service 384592
            rec_val =   (buf[3*1 + 0] << (0*8)) +
Packit Service 384592
                        (buf[3*1 + 1] << (1*8)) +
Packit Service 384592
                        (buf[3*1 + 2] << (2*8));
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* If we are past the country offset, then we are done */
Packit Service 384592
        if (rec_val >= geo->ctry_offset) {
Packit Service 384592
            break;
Packit Service 384592
        }
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    if (rec_val == geo->ctry_offset) {
Packit Service 384592
        *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\").", log_escape(msr->mp, target));
Packit Service 384592
        msr_log(msr, 4, "%s", *error_msg);
Packit Service 384592
Packit Service 384592
        ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
Packit Service 384592
        if (ret != APR_SUCCESS) {
Packit Service 384592
            msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
Packit Service 384592
                    get_apr_error(msr->mp, ret));
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        return 0;
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    if (geo->dbtype == GEO_COUNTRY_DATABASE) {
Packit Service 384592
        country = rec_val;
Packit Service 384592
        country -= geo->ctry_offset;
Packit Service 384592
        if ((country <= 0) || (country > GEO_COUNTRY_LAST)) {
Packit Service 384592
            *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\" (country %d).", log_escape(msr->mp, target), country);
Packit Service 384592
            msr_log(msr, 4, "%s", *error_msg);
Packit Service 384592
Packit Service 384592
            ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
Packit Service 384592
            if (ret != APR_SUCCESS) {
Packit Service 384592
                msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
Packit Service 384592
                        get_apr_error(msr->mp, ret));
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            return 0;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* Country */
Packit Service 384592
        georec->country_code = geo_country_code[country];
Packit Service 384592
        georec->country_code3 = geo_country_code3[country];
Packit Service 384592
        georec->country_name = geo_country_name[country];
Packit Service 384592
        georec->country_continent = geo_country_continent[country];
Packit Service 384592
    }
Packit Service 384592
    else {
Packit Service 384592
        int field_len = 0;
Packit Service 384592
        int rec_offset = 0;
Packit Service 384592
        int remaining = GEO_CITY_RECORD_LEN;
Packit Service 384592
        unsigned char cbuf[GEO_CITY_RECORD_LEN];
Packit Service 384592
Packit Service 384592
        seekto = rec_val + (2 * reclen - 1) * geo->ctry_offset;
Packit Service 384592
        apr_file_seek(geo->db, APR_SET, &seekto);
Packit Service 384592
        /* TODO: check rc */
Packit Service 384592
        rc = apr_file_read_full(geo->db, &cbuf, sizeof(cbuf), &nbytes);
Packit Service 384592
Packit Service 384592
        country = cbuf[0];
Packit Service 384592
        if ((country <= 0) || (country > GEO_COUNTRY_LAST)) {
Packit Service 384592
            *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\" (country %d).", log_escape(msr->mp, target), country);
Packit Service 384592
            msr_log(msr, 4, "%s", *error_msg);
Packit Service 384592
Packit Service 384592
            ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
Packit Service 384592
            if (ret != APR_SUCCESS) {
Packit Service 384592
                msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
Packit Service 384592
                        get_apr_error(msr->mp, ret));
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            return 0;
Packit Service 384592
        }
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: rec=\"%s\"", log_escape_raw(msr->mp, cbuf, sizeof(cbuf)));
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* Country */
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: country=\"%.*s\"", (1*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf)));
Packit Service 384592
        }
Packit Service 384592
        georec->country_code = geo_country_code[country];
Packit Service 384592
        georec->country_code3 = geo_country_code3[country];
Packit Service 384592
        georec->country_name = geo_country_name[country];
Packit Service 384592
        georec->country_continent = geo_country_continent[country];
Packit Service 384592
        rec_offset++;
Packit Service 384592
        remaining -= rec_offset;
Packit Service 384592
Packit Service 384592
        /* Region */
Packit Service 384592
        field_len = field_length((const char *)cbuf+rec_offset, remaining);
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: region=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
Packit Service 384592
        }
Packit Service 384592
        georec->region = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining));
Packit Service 384592
        rec_offset += field_len + 1;
Packit Service 384592
        remaining -= field_len + 1;
Packit Service 384592
Packit Service 384592
        /* City */
Packit Service 384592
        field_len = field_length((const char *)cbuf+rec_offset, remaining);
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: city=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
Packit Service 384592
        }
Packit Service 384592
        georec->city = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining));
Packit Service 384592
        rec_offset += field_len + 1;
Packit Service 384592
        remaining -= field_len + 1;
Packit Service 384592
Packit Service 384592
        /* Postal Code */
Packit Service 384592
        field_len = field_length((const char *)cbuf+rec_offset, remaining);
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: postal_code=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
Packit Service 384592
        }
Packit Service 384592
        georec->postal_code = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining));
Packit Service 384592
        rec_offset += field_len + 1;
Packit Service 384592
        remaining -= field_len + 1;
Packit Service 384592
Packit Service 384592
        /* Latitude */
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: latitude=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
Packit Service 384592
        }
Packit Service 384592
        dtmp = cbuf[rec_offset] +
Packit Service 384592
               (cbuf[rec_offset+1] << 8) +
Packit Service 384592
               (cbuf[rec_offset+2] << 16);
Packit Service 384592
        georec->latitude = dtmp/10000 - 180;
Packit Service 384592
        rec_offset += 3;
Packit Service 384592
        remaining -= 3;
Packit Service 384592
Packit Service 384592
Packit Service 384592
        /* Longitude */
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: longitude=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
Packit Service 384592
        }
Packit Service 384592
        dtmp = cbuf[rec_offset] +
Packit Service 384592
              (cbuf[rec_offset+1] << 8) +
Packit Service 384592
              (cbuf[rec_offset+2] << 16);
Packit Service 384592
        georec->longitude = dtmp/10000 - 180;
Packit Service 384592
        rec_offset += 3;
Packit Service 384592
        remaining -= 3;
Packit Service 384592
Packit Service 384592
        /* dma/area codes are in city rev1 and US only */
Packit Service 384592
        if (msr->txcfg->debuglog_level >= 9) {
Packit Service 384592
            msr_log(msr, 9, "GEO: dma/area=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
Packit Service 384592
        }
Packit Service 384592
        if (geo->dbtype == GEO_CITY_DATABASE_1
Packit Service 384592
            && georec->country_code[0] == 'U'
Packit Service 384592
            && georec->country_code[1] == 'S')
Packit Service 384592
        {
Packit Service 384592
            /* DMA Code */
Packit Service 384592
            itmp = cbuf[rec_offset] +
Packit Service 384592
                  (cbuf[rec_offset+1] << 8) +
Packit Service 384592
                  (cbuf[rec_offset+2] << 16);
Packit Service 384592
            georec->dma_code = itmp / 1000;
Packit Service 384592
            georec->area_code = itmp % 1000;
Packit Service 384592
            rec_offset += 6;
Packit Service 384592
            remaining -= 6;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" succeeded.", log_escape(msr->mp, target));
Packit Service 384592
Packit Service 384592
    ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
Packit Service 384592
    if (ret != APR_SUCCESS) {
Packit Service 384592
        msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
Packit Service 384592
                get_apr_error(msr->mp, ret));
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    return 1;
Packit Service 384592
}
Packit Service 384592
Packit Service 384592