mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-17 01:36:08 +03:00
MODSEC-196
This commit is contained in:
parent
d0e2546f9b
commit
8e9582bede
@ -137,6 +137,71 @@ static const char *geo_country_continent[GEO_COUNTRY_LAST + 1] = {
|
|||||||
"AF","EU","AF","--","--","--","EU","EU","EU","EU"
|
"AF","EU","AF","--","--","--","EU","EU","EU","EU"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GEOIP_COUNTRY_EDITION = 1,
|
||||||
|
GEOIP_REGION_EDITION_REV0 = 7,
|
||||||
|
GEOIP_CITY_EDITION_REV0 = 6,
|
||||||
|
GEOIP_ORG_EDITION = 5,
|
||||||
|
GEOIP_ISP_EDITION = 4,
|
||||||
|
GEOIP_CITY_EDITION_REV1 = 2,
|
||||||
|
GEOIP_REGION_EDITION_REV1 = 3,
|
||||||
|
GEOIP_PROXY_EDITION = 8,
|
||||||
|
GEOIP_ASNUM_EDITION = 9,
|
||||||
|
GEOIP_NETSPEED_EDITION = 10,
|
||||||
|
GEOIP_DOMAIN_EDITION = 11
|
||||||
|
} GeoIPDBTypes;
|
||||||
|
|
||||||
|
static void create_segments(geo_db *geo) {
|
||||||
|
int i, j;
|
||||||
|
unsigned char delim[3];
|
||||||
|
unsigned char buf[GEO_SEGMENT_RECORD_LENGTH];
|
||||||
|
apr_size_t nbytes;
|
||||||
|
apr_status_t rc;
|
||||||
|
apr_off_t offset;
|
||||||
|
|
||||||
|
geo->ctry_offset = 0;
|
||||||
|
|
||||||
|
geo->dbtype = GEOIP_COUNTRY_EDITION;
|
||||||
|
offset = -3l;
|
||||||
|
apr_file_seek(geo->db, APR_END, &offset);
|
||||||
|
|
||||||
|
for (i = 0; i < GEO_STRUCT_INFO_MAX_SIZE; i++) {
|
||||||
|
|
||||||
|
rc = apr_file_read_full(geo->db, &delim, 3, &nbytes);
|
||||||
|
|
||||||
|
if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
|
||||||
|
rc = apr_file_read_full(geo->db, &geo->dbtype, 1, &nbytes);
|
||||||
|
if (geo->dbtype >= 106) {
|
||||||
|
geo->dbtype -= 105;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geo->dbtype == GEOIP_REGION_EDITION_REV0) {
|
||||||
|
geo->ctry_offset = GEO_STATE_BEGIN_REV0;
|
||||||
|
} else if (geo->dbtype == GEOIP_REGION_EDITION_REV1) {
|
||||||
|
geo->ctry_offset = GEO_STATE_BEGIN_REV1;
|
||||||
|
} else if (geo->dbtype == GEOIP_CITY_EDITION_REV0 ||
|
||||||
|
geo->dbtype == GEOIP_CITY_EDITION_REV1 ||
|
||||||
|
geo->dbtype == GEOIP_ORG_EDITION ||
|
||||||
|
geo->dbtype == GEOIP_ISP_EDITION ||
|
||||||
|
geo->dbtype == GEOIP_ASNUM_EDITION) {
|
||||||
|
geo->ctry_offset = 0;
|
||||||
|
rc = apr_file_read_full(geo->db, &buf, GEO_SEGMENT_RECORD_LENGTH, &nbytes);
|
||||||
|
for (j = 0; j < GEO_SEGMENT_RECORD_LENGTH; j++) {
|
||||||
|
geo->ctry_offset += (buf[j] << (j * 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
offset = -4l;
|
||||||
|
apr_file_seek(geo->db, APR_CUR, &offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (geo->dbtype == GEOIP_COUNTRY_EDITION ||
|
||||||
|
geo->dbtype == GEOIP_PROXY_EDITION ||
|
||||||
|
geo->dbtype == GEOIP_NETSPEED_EDITION) {
|
||||||
|
geo->ctry_offset = GEO_COUNTRY_BEGIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int db_open(directory_config *dcfg, char **error_msg)
|
static int db_open(directory_config *dcfg, char **error_msg)
|
||||||
{
|
{
|
||||||
@ -158,81 +223,7 @@ static int db_open(directory_config *dcfg, char **error_msg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = -3;
|
create_segments(geo);
|
||||||
apr_file_seek(geo->db, APR_END, &offset);
|
|
||||||
/* TODO check offset */
|
|
||||||
|
|
||||||
/* Defaults */
|
|
||||||
geo->dbtype = GEO_COUNTRY_DATABASE;
|
|
||||||
geo->ctry_offset = GEO_COUNTRY_OFFSET;
|
|
||||||
|
|
||||||
for (i = 0; i < GEO_STRUCT_INFO_MAX_SIZE; i++) {
|
|
||||||
memset(buf, 0, 3);
|
|
||||||
rc = apr_file_read_full(geo->db, &buf, 3, &nbytes);
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: read 0x%02x%02x%02x\n", buf[0], buf[1], buf[2]);
|
|
||||||
#endif
|
|
||||||
if ((rc != APR_SUCCESS) || (nbytes != 3)) {
|
|
||||||
*error_msg = apr_psprintf(mp, "Could not read from geo database \"%s\" (%" APR_SIZE_T_FMT "/3 bytes read): %s", geo->dbfn, nbytes, apr_strerror(rc, errstr, 1024));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) {
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: Found DB info marker at offset 0x%08x\n", (unsigned int)offset);
|
|
||||||
#endif
|
|
||||||
memset(buf, 0, 3);
|
|
||||||
rc = apr_file_read_full(geo->db, &buf, 1, &nbytes);
|
|
||||||
/* TODO: check rc */
|
|
||||||
geo->dbtype = (int)buf[0];
|
|
||||||
|
|
||||||
/* Backwards compat */
|
|
||||||
if (geo->dbtype >= 106) {
|
|
||||||
geo->dbtype -= 105;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: DB type %d\n", geo->dbtype);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If a cities DB, then get country offset */
|
|
||||||
if ((geo->dbtype == GEO_CITY_DATABASE_0) || (geo->dbtype == GEO_CITY_DATABASE_1)) {
|
|
||||||
memset(buf, 0, 3);
|
|
||||||
rc = apr_file_read_full(geo->db, &buf, 3, &nbytes);
|
|
||||||
if ((rc != APR_SUCCESS) || (nbytes != 3)) {
|
|
||||||
*error_msg = apr_psprintf(mp, "Could not read geo database \"%s\" country offset (%" APR_SIZE_T_FMT "/3 bytes read): %s", geo->dbfn, nbytes, apr_strerror(rc, errstr, 1024));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: read 0x%02x%02x%02x\n", buf[0], buf[1], buf[2]);
|
|
||||||
#endif
|
|
||||||
geo->ctry_offset = 0;
|
|
||||||
for (j = 0; j < 3; j++) {
|
|
||||||
geo->ctry_offset += (buf[j] << (j * 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: Country offset 0x%08x\n", geo->ctry_offset);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Backup a byte from where we started */
|
|
||||||
offset = -4;
|
|
||||||
apr_file_seek(geo->db, APR_CUR, &offset);
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: DB offset 0x%08x\n", (unsigned int)offset);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geo->dbtype != GEO_COUNTRY_DATABASE) {
|
|
||||||
*error_msg = apr_psprintf(mp, "Unknown database format");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_CONF
|
|
||||||
fprintf(stderr, "GEO: DB type %d\n", geo->dbtype);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +284,9 @@ int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **erro
|
|||||||
int level;
|
int level;
|
||||||
double dtmp;
|
double dtmp;
|
||||||
int itmp;
|
int itmp;
|
||||||
|
const unsigned char * p;
|
||||||
|
unsigned int x;
|
||||||
|
int j;
|
||||||
|
|
||||||
*error_msg = NULL;
|
*error_msg = NULL;
|
||||||
|
|
||||||
@ -330,7 +324,7 @@ int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **erro
|
|||||||
ipnum = ntohl(addr->sa.sin.sin_addr.s_addr);
|
ipnum = ntohl(addr->sa.sin.sin_addr.s_addr);
|
||||||
|
|
||||||
if (msr->txcfg->debuglog_level >= 9) {
|
if (msr->txcfg->debuglog_level >= 9) {
|
||||||
msr_log(msr, 9, "GEO: Using address \"%s\" (0x%08lx).", targetip, ipnum);
|
msr_log(msr, 9, "GEO: Using address \"%s\" (0x%08lx). %lu", targetip, ipnum, ipnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = apr_global_mutex_lock(msr->modsecurity->geo_lock);
|
ret = apr_global_mutex_lock(msr->modsecurity->geo_lock);
|
||||||
@ -349,15 +343,41 @@ int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **erro
|
|||||||
/* NOTE: This is hard-coded for size 3 records */
|
/* NOTE: This is hard-coded for size 3 records */
|
||||||
/* Left */
|
/* Left */
|
||||||
if ((ipnum & (1 << level)) == 0) {
|
if ((ipnum & (1 << level)) == 0) {
|
||||||
rec_val = buf[0] +
|
//rec_val = buf[0] +
|
||||||
(buf[1] << 8) +
|
// (buf[1] << 8) +
|
||||||
(buf[2] << 16);
|
// (buf[2] << 16);
|
||||||
|
rec_val = (buf[3*0 + 0] << (0*8)) +
|
||||||
|
(buf[3*0 + 1] << (1*8)) +
|
||||||
|
(buf[3*0 + 2] << (2*8));
|
||||||
|
/*j = 3;
|
||||||
|
p = &buf[2*j];
|
||||||
|
x = 0;
|
||||||
|
do {
|
||||||
|
x <<= 8;
|
||||||
|
x += *(--p);
|
||||||
|
} while ( --j );
|
||||||
|
rec_val = x;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
/* Right */
|
/* Right */
|
||||||
else {
|
else {
|
||||||
rec_val = buf[3] +
|
//rec_val = buf[3] +
|
||||||
(buf[4] << 8) +
|
// (buf[4] << 8) +
|
||||||
(buf[5] << 16);
|
// (buf[5] << 16);
|
||||||
|
rec_val = (buf[3*1 + 0] << (0*8)) +
|
||||||
|
(buf[3*1 + 1] << (1*8)) +
|
||||||
|
(buf[3*1 + 2] << (2*8));
|
||||||
|
|
||||||
|
/*j = 3;
|
||||||
|
p = &buf[1*j];
|
||||||
|
x = 0;
|
||||||
|
do {
|
||||||
|
x <<= 8;
|
||||||
|
x += *(--p);
|
||||||
|
} while ( --j );
|
||||||
|
|
||||||
|
rec_val = x;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are past the country offset, then we are done */
|
/* If we are past the country offset, then we are done */
|
||||||
@ -366,6 +386,19 @@ int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rec_val == geo->ctry_offset) {
|
||||||
|
*error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\").", log_escape(msr->mp, target));
|
||||||
|
msr_log(msr, 4, "%s", *error_msg);
|
||||||
|
|
||||||
|
ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
|
||||||
|
if (ret != APR_SUCCESS) {
|
||||||
|
msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
|
||||||
|
get_apr_error(msr->mp, ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (geo->dbtype == GEO_COUNTRY_DATABASE) {
|
if (geo->dbtype == GEO_COUNTRY_DATABASE) {
|
||||||
country = rec_val;
|
country = rec_val;
|
||||||
country -= geo->ctry_offset;
|
country -= geo->ctry_offset;
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#define GEO_CITY_DATABASE_0 6
|
#define GEO_CITY_DATABASE_0 6
|
||||||
#define GEO_CITY_DATABASE_1 2
|
#define GEO_CITY_DATABASE_1 2
|
||||||
#define GEO_COUNTRY_LAST 250
|
#define GEO_COUNTRY_LAST 250
|
||||||
|
#define GEO_SEGMENT_RECORD_LENGTH 3
|
||||||
|
#define GEO_STATE_BEGIN_REV0 16700000
|
||||||
|
#define GEO_STATE_BEGIN_REV1 16000000
|
||||||
|
#define GEO_COUNTRY_BEGIN 16776960
|
||||||
|
|
||||||
|
|
||||||
typedef struct geo_rec geo_rec;
|
typedef struct geo_rec geo_rec;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user