static char * ngx_stream_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_geoip_conf_t *gcf = conf; ngx_str_t *value; if (gcf->org) { return "is duplicate"; } value = cf->args->elts; gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); if (gcf->org == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "GeoIP_open(\"%V\") failed", &value[1]); return NGX_CONF_ERROR; } if (cf->args->nelts == 3) { if (ngx_strcmp(value[2].data, "utf8") == 0) { GeoIP_set_charset(gcf->org, GEOIP_CHARSET_UTF8); } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[2]); return NGX_CONF_ERROR; } } switch (gcf->org->databaseType) { case GEOIP_ISP_EDITION: case GEOIP_ORG_EDITION: case GEOIP_DOMAIN_EDITION: case GEOIP_ASNUM_EDITION: return NGX_CONF_OK; #if (NGX_HAVE_GEOIP_V6) case GEOIP_ISP_EDITION_V6: case GEOIP_ORG_EDITION_V6: case GEOIP_DOMAIN_EDITION_V6: case GEOIP_ASNUM_EDITION_V6: gcf->org_v6 = 1; return NGX_CONF_OK; #endif default: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid GeoIP database \"%V\" type:%d", &value[1], gcf->org->databaseType); return NGX_CONF_ERROR; } }
static PyObject * GeoIP_set_charset_Py(PyObject *self, PyObject * args) { GeoIP_GeoIPObject* GeoIP = (GeoIP_GeoIPObject*)self; int charset; if (!PyArg_ParseTuple(args, "i", &charset)) { return NULL; } return Py_BuildValue("i", GeoIP_set_charset(GeoIP->gi, charset)); }
/* Open the given GeoLocation database and set its charset. * * On error, it aborts. * On success, a new geolocation structure is returned. */ GeoIP * geoip_open_db (const char *db) { GeoIP *geoip; geoip = GeoIP_open (db, GEOIP_MEMORY_CACHE); if (geoip == NULL) FATAL ("Unable to open GeoIP database: %s\n", db); GeoIP_set_charset (geoip, GEOIP_CHARSET_UTF8); LOG_DEBUG (("Opened GeoIP City database: %s\n", db)); return geoip; }
static char * ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_geoip_conf_t *gcf = conf; ngx_str_t *value; if (gcf->country) { return "is duplicate"; } value = cf->args->elts; gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); if (gcf->country == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "GeoIP_open(\"%V\") failed", &value[1]); return NGX_CONF_ERROR; } if (cf->args->nelts == 3) { if (ngx_strcmp(value[2].data, "utf8") == 0) { GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8); } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[2]); return NGX_CONF_ERROR; } } switch (gcf->country->databaseType) { case GEOIP_COUNTRY_EDITION: case GEOIP_PROXY_EDITION: case GEOIP_NETSPEED_EDITION: return NGX_CONF_OK; default: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid GeoIP database \"%V\" type:%d", &value[1], gcf->country->databaseType); return NGX_CONF_ERROR; } }
static PyObject *GeoIP_set_charset_Py(PyObject * self, PyObject * args) { GeoIP_GeoIPObject *GeoIP = (GeoIP_GeoIPObject *)self; int charset; if (!PyArg_ParseTuple(args, "i", &charset)) { return NULL; } #if PY_MAJOR_VERSION >= 3 if (charset != GEOIP_CHARSET_UTF8) { PyErr_SetString(PyExc_ValueError, "Only UTF-8 is supported for Python 3+."); return NULL; } #endif return Py_BuildValue("i", GeoIP_set_charset(GeoIP->gi, charset)); }
static void geoip_child_init(apr_pool_t * p, server_rec * s) { geoip_server_config_rec *cfg; int i, flags; cfg = (geoip_server_config_rec *) ap_get_module_config(s->module_config, &geoip_module); if (cfg->gips) { if (cfg->GeoIPFilenames != NULL) { for (i = 0; i < cfg->numGeoIPFiles; i++) { flags = (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]; if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) continue; if (cfg->gips[i]) { GeoIP_delete(cfg->gips[i]); } cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], flags); if (cfg->gips[i]) { if (cfg->GeoIPEnableUTF8) { GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]); continue; } } } else { if (cfg->gips[0]) GeoIP_delete(cfg->gips[0]); cfg->gips[0] = GeoIP_new(GEOIP_STANDARD); if (!cfg->gips[0]) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "[mod_geoip]: Error while opening data file"); } cfg->numGeoIPFiles = 1; } } }
/* initialize geoip once per server ( even virtal server! ) */ static void geoip_server_init(apr_pool_t * p, server_rec * s) { geoip_server_config_rec *cfg; int i; cfg = (geoip_server_config_rec *) ap_get_module_config(s->module_config, &geoip_module); if (!cfg->gips) { if (cfg->GeoIPFilenames != NULL) { cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles); for (i = 0; i < cfg->numGeoIPFiles; i++) { cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]); if (cfg->gips[i]) { if (cfg->GeoIPEnableUTF8) { GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]); continue; } } } else { cfg->gips = malloc(sizeof(GeoIP *)); cfg->gips[0] = GeoIP_new(GEOIP_STANDARD); if (!cfg->gips[0]) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "[mod_geoip]: Error while opening data file"); } cfg->numGeoIPFiles = 1; } } apr_pool_cleanup_register(p, (void *)cfg, geoip_cleanup, geoip_cleanup); }
vmod_event(VRT_CTX, struct vmod_priv *pp, enum vcl_event_e evt) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); if (pp->priv == NULL) { xxxassert(evt == VCL_EVENT_LOAD); /* The README says: * If GEOIP_MMAP_CACHE doesn't work on a 64bit machine, try * adding * the flag "MAP_32BIT" to the mmap call. MMAP is not * avail for WIN32. */ pp->priv = GeoIP_new(GEOIP_MMAP_CACHE); AN(pp->priv); pp->free = (vmod_priv_free_f *)GeoIP_delete; GeoIP_set_charset((GeoIP *)pp->priv, GEOIP_CHARSET_UTF8); } return (0); }
GeoIP* Geolocation::loadGeoDB(char *base_path, const char *db_name) { char path[MAX_PATH]; GeoIP *geo; struct stat buf; bool found; snprintf(path, sizeof(path), "%s/%s", base_path, db_name); ntop->fixPath(path); found = ((stat(path, &buf) == 0) && (S_ISREG(buf.st_mode))) ? true : false; if(!found) return(NULL); geo = GeoIP_open(path, GEOIP_CHECK_CACHE); if(geo == NULL) ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to read GeoIP database %s", path); else GeoIP_set_charset(geo, GEOIP_CHARSET_UTF8); /* Avoid UTF-8 issues (hopefully) */ return(geo); }
static int GeoIP_GeoIP_init(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "filename", "flags", NULL }; GeoIP_GeoIPObject *GeoIP = (GeoIP_GeoIPObject *)self; char *filename = NULL; int flags; /* For consistency with the C API, positional arguments are in the order filename, flags; but it is filename that is optional. */ if (PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist + 1, &flags)) { GeoIP->gi = GeoIP_new(flags); } else{ PyErr_Clear(); if (PyArg_ParseTupleAndKeywords(args, kwargs, "si", kwlist, &filename, &flags)) { GeoIP->gi = GeoIP_open(filename, flags); } else{ return -1; } } if (!GeoIP->gi) { /* Failure is probably due to a system-call-level failure. */ if (!filename) { filename = GeoIPDBFileName[GEOIP_COUNTRY_EDITION]; } PyErr_SetFromErrnoWithFilename(GeoIP_GeoIPError, filename); return -1; } #if PY_MAJOR_VERSION >= 3 GeoIP_set_charset(GeoIP->gi, GEOIP_CHARSET_UTF8); #endif return 0; }
static int geoip_header_parser(request_rec * r) { char *orgorisp; char *ipaddr; char *free_me = NULL; short int country_id; const char *continent_code; const char *country_code; const char *country_name; const char *region_name; geoip_server_config_rec *cfg; unsigned char databaseType; GeoIPRecord *gir; GeoIPRegion *giregion; int i; int netspeed; /* For splitting proxy headers */ char *ipaddr_ptr = NULL; char *comma_ptr; cfg = ap_get_module_config(r->server->module_config, &geoip_module); if (!cfg) return DECLINED; if (!cfg->scanProxyHeaders) { ipaddr = _get_client_ip(r); } else { ap_add_common_vars(r); if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) { ipaddr_ptr = (char *)apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP"); } else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) { ipaddr_ptr = (char *)apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR"); } else if (apr_table_get(r->headers_in, "X-Forwarded-For")) { ipaddr_ptr = (char *)apr_table_get(r->headers_in, "X-Forwarded-For"); } else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) { ipaddr_ptr = (char *)apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR"); } if (!ipaddr_ptr) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR."); ipaddr = _get_client_ip(r); } else { /* Found XFF like header */ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr); if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP) { ipaddr = free_me = _get_ip_from_xff(ipaddr_ptr); if (!ipaddr) ipaddr = _get_client_ip(r); } else { ipaddr = free_me = (char *)calloc(8 * 4 + 7 + 1, sizeof(char)); /* proxyHeaderMode is * GEOIP_PROXY_HEADER_MODE_LAST_IP or GEOIP_PROXY_HEADER_MODE_FIRST_IP */ /* * Check to ensure that the HTTP_CLIENT_IP or * X-Forwarded-For header is not a comma separated * list of addresses, which would cause mod_geoip to * return no country code. If the header is a comma * separated list, return the first IP address in the * list, which is (hopefully!) the real client IP. */ if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_LAST_IP) { comma_ptr = strrchr(ipaddr_ptr, ','); if (comma_ptr) { /* skip over whitespace */ ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t"); } } strncpy(ipaddr, ipaddr_ptr, 8 * 4 + 7); comma_ptr = strchr(ipaddr, ','); if (comma_ptr != 0) *comma_ptr = '\0'; } } } /* this block should be removed! */ #if 1 if (!cfg->gips) { if (cfg->GeoIPFilenames != NULL) { cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles); for (i = 0; i < cfg->numGeoIPFiles; i++) { cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]); if (cfg->gips[i]) { if (cfg->GeoIPEnableUTF8) { GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]); return DECLINED; } } } else { cfg->gips = malloc(sizeof(GeoIP *)); cfg->gips[0] = GeoIP_new(GEOIP_STANDARD); if (!cfg->gips[0]) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file"); return DECLINED; } cfg->numGeoIPFiles = 1; } } #endif set_geoip_output(cfg, r, "GEOIP_ADDR", ipaddr); for (i = 0; i < cfg->numGeoIPFiles; i++) { /* * skip database handles that can not be opned for some * reason */ if (cfg->gips[i] == NULL) continue; databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1; /* -1 is "magic value" * in case file not * found */ switch (databaseType) { case GEOIP_NETSPEED_EDITION_REV1: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_NETSPEED", orgorisp); break; case GEOIP_NETSPEED_EDITION: netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr); if (netspeed == GEOIP_UNKNOWN_SPEED) { netspeedstring = "unknown"; } else if (netspeed == GEOIP_DIALUP_SPEED) { netspeedstring = "dialup"; } else if (netspeed == GEOIP_CABLEDSL_SPEED) { netspeedstring = "cabledsl"; } else if (netspeed == GEOIP_CORPORATE_SPEED) { netspeedstring = "corporate"; } setn_geoip_output(cfg, r, "GEOIP_NETSPEED", netspeedstring); break; case GEOIP_COUNTRY_EDITION_V6: /* Get the Country ID */ country_id = GeoIP_id_by_addr_v6(cfg->gips[i], ipaddr); if (country_id > 0) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6", continent_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6", country_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6", country_name); } break; case GEOIP_COUNTRY_EDITION: /* Get the Country ID */ country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr); if (country_id > 0) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE", continent_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", country_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", country_name); } break; case GEOIP_REGION_EDITION_REV0: case GEOIP_REGION_EDITION_REV1: giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr); if (giregion != NULL) { region_name = NULL; if (giregion->country_code[0]) { region_name = GeoIP_region_name_by_code (giregion->country_code, giregion->region); set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", giregion->country_code); country_id = GeoIP_id_by_code(giregion->country_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", GeoIP_country_name[country_id]); setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE", GeoIP_country_continent[country_id]); } if (giregion->region[0]) { set_geoip_output(cfg, r, "GEOIP_REGION", giregion->region); } if (region_name != NULL) { set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name); } GeoIPRegion_delete(giregion); } break; case GEOIP_CITY_EDITION_REV0_V6: case GEOIP_CITY_EDITION_REV1_V6: gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr); if (gir != NULL) { if (gir->country_code != NULL) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6", gir->continent_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6", gir->country_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6", gir->country_name); set_geoip_output(cfg, r, "GEOIP_REGION_V6", gir->region); set_geoip_output(cfg, r, "GEOIP_REGION_NAME_V6", region_name); set_geoip_output(cfg, r, "GEOIP_CITY_V6", gir->city); set_geoip_output(cfg, r, "GEOIP_DMA_CODE_V6", metrocodestr); set_geoip_output(cfg, r, "GEOIP_METRO_CODE_V6", metrocodestr); set_geoip_output(cfg, r, "GEOIP_AREA_CODE_V6", areacodestr); sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); set_geoip_output(cfg, r, "GEOIP_LATITUDE_V6", latstr); set_geoip_output(cfg, r, "GEOIP_LONGITUDE_V6", lonstr); set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE_V6", gir->postal_code); GeoIPRecord_delete(gir); } break; case GEOIP_CITY_EDITION_REV0: case GEOIP_CITY_EDITION_REV1: gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr); if (gir != NULL) { if (gir->country_code != NULL) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE", gir->continent_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", gir->country_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", gir->country_name); set_geoip_output(cfg, r, "GEOIP_REGION", gir->region); set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name); set_geoip_output(cfg, r, "GEOIP_CITY", gir->city); set_geoip_output(cfg, r, "GEOIP_DMA_CODE", metrocodestr); set_geoip_output(cfg, r, "GEOIP_METRO_CODE", metrocodestr); set_geoip_output(cfg, r, "GEOIP_AREA_CODE", areacodestr); sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); set_geoip_output(cfg, r, "GEOIP_LATITUDE", latstr); set_geoip_output(cfg, r, "GEOIP_LONGITUDE", lonstr); set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE", gir->postal_code); GeoIPRecord_delete(gir); } break; case GEOIP_ORG_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_ORGANIZATION", orgorisp); break; case GEOIP_ISP_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_ISP", orgorisp); break; case GEOIP_DOMAIN_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_DOMAIN", orgorisp); break; } } if (free_me) free(free_me); return OK; }
static int geoip_header_parser(request_rec * r) { char *orgorisp; char *ipaddr; short int country_id; GeoIP *gip; const char *continent_code; const char *country_code; const char *country_name; const char *region_name; geoip_server_config_rec *cfg; unsigned char databaseType; GeoIPRecord *gir; GeoIPRegion *giregion; int i; int netspeed; /* For splitting proxy headers */ char *ipaddr_ptr = 0; char *comma_ptr; char *found_ip; apr_sockaddr_t *sa; char *hostname = 0; cfg = ap_get_module_config(r->server->module_config, &geoip_module); if (!cfg) return DECLINED; if (!cfg->scanProxyHeaders) { ipaddr = r->connection->remote_ip; } else { ap_add_common_vars(r); if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) { ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP"); } else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) { ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR"); } else if (apr_table_get(r->headers_in, "X-Forwarded-For")) { ipaddr_ptr = (char *) apr_table_get(r->headers_in, "X-Forwarded-For"); } else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) { ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR"); } if (!ipaddr_ptr) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR."); ipaddr = r->connection->remote_ip; } else { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr); if (cfg->use_left_public_x_forwarded_for_ip) { // find the first public IP address in a potentially comma-separated list, // fall back to remote_ip if we can't find one ipaddr = first_public_ip_in_list(ipaddr_ptr, r->connection->remote_ip); } else { // leaving some of the following inconsistent indenting intact for easier diff to original maxmind src /* * Check to ensure that the HTTP_CLIENT_IP or * X-Forwarded-For header is not a comma separated * list of addresses, which would cause mod_geoip to * return no country code. If the header is a comma * separated list, return the first IP address in the * list, which is (hopefully!) the real client IP. */ ipaddr = (char *) calloc(8*4+7+1, sizeof(char)); if (cfg->use_last_x_forwarded_for_ip ){ comma_ptr = strrchr(ipaddr_ptr, ','); if ( comma_ptr ) { /* skip over whitespace */ ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t"); } } strncpy(ipaddr, ipaddr_ptr, 8*4+7); comma_ptr = strchr(ipaddr, ','); if (comma_ptr != 0) *comma_ptr = '\0'; } } } /* this block should be removed! */ #if 1 if (!cfg->gips) { if (cfg->GeoIPFilenames != NULL) { cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles); for (i = 0; i < cfg->numGeoIPFiles; i++) { cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]); if (cfg->gips[i]) { if (cfg->GeoIPEnableUTF8) { GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]); return DECLINED; } } } else { cfg->gips = malloc(sizeof(GeoIP *)); cfg->gips[0] = GeoIP_new(GEOIP_STANDARD); if (!cfg->gips[0]) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file"); return DECLINED; } cfg->numGeoIPFiles = 1; } } #endif if (cfg->GeoIPEnableHostnameLookups && apr_sockaddr_info_get(&sa, ipaddr, APR_INET, 0, 0, r->pool) == APR_SUCCESS && apr_getnameinfo(&hostname, sa, 0) == APR_SUCCESS) { ap_str_tolower(hostname); } if (!hostname) hostname = ipaddr; if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_ADDR", ipaddr); apr_table_setn(r->notes, "GEOIP_HOST", hostname); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_ADDR", ipaddr); apr_table_setn(r->subprocess_env, "GEOIP_HOST", hostname); } for (i = 0; i < cfg->numGeoIPFiles; i++) { /* * skip database handles that can not be opned for some * reason */ if (cfg->gips[i] == NULL) continue; databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1; /* -1 is "magic value" * in case file not * found */ switch (databaseType) { case GEOIP_NETSPEED_EDITION_REV1: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_NETSPEED", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_NETSPEED", orgorisp); } } break; case GEOIP_NETSPEED_EDITION: netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr); if (netspeed == GEOIP_UNKNOWN_SPEED) { netspeedstring = "unknown"; } else if (netspeed == GEOIP_DIALUP_SPEED) { netspeedstring = "dialup"; } else if (netspeed == GEOIP_CABLEDSL_SPEED) { netspeedstring = "cabledsl"; } else if (netspeed == GEOIP_CORPORATE_SPEED) { netspeedstring = "corporate"; } if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_NETSPEED", netspeedstring); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_NETSPEED", netspeedstring); } break; case GEOIP_COUNTRY_EDITION_V6: /* Get the Country ID */ country_id = GeoIP_country_id_by_addr_v6(cfg->gips[i], ipaddr); if ( country_id > 0 ) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE_V6", continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE_V6", country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME_V6", country_name); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE_V6", continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE_V6", country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME_V6", country_name); } } break; case GEOIP_COUNTRY_EDITION: /* Get the Country ID */ country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr); if ( country_id > 0 ) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE", continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE", country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME", country_name); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE", continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE", country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME", country_name); } } break; case GEOIP_REGION_EDITION_REV0: case GEOIP_REGION_EDITION_REV1: giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr); if (giregion != NULL) { if ( giregion->country_code[0] ) { region_name = GeoIP_region_name_by_code(giregion->country_code, giregion->region); } if (cfg->GeoIPOutput & GEOIP_NOTES) { if ( giregion->country_code[0] ){ apr_table_set(r->notes, "GEOIP_COUNTRY_CODE", giregion->country_code); } if (giregion->region[0]) { apr_table_set(r->notes, "GEOIP_REGION", giregion->region); } if ( region_name != NULL ){ apr_table_set(r->notes, "GEOIP_REGION_NAME", region_name); } } if (cfg->GeoIPOutput & GEOIP_ENV) { if ( giregion->country_code[0] ){ apr_table_set(r->subprocess_env, "GEOIP_COUNTRY_CODE", giregion->country_code); } if (giregion->region[0]) { apr_table_set(r->subprocess_env, "GEOIP_REGION", giregion->region); } if ( region_name != NULL ){ apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME", region_name); } } GeoIPRegion_delete(giregion); } break; case GEOIP_CITY_EDITION_REV0_V6: case GEOIP_CITY_EDITION_REV1_V6: gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr); if (gir != NULL) { if ( gir->country_code != NULL ) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE_V6", gir->continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE_V6", gir->country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME_V6", gir->country_name); if (gir->region != NULL) { apr_table_set(r->notes, "GEOIP_REGION_V6", gir->region); if ( region_name != NULL ){ apr_table_set(r->notes, "GEOIP_REGION_NAME_V6", region_name); } } if (gir->city != NULL) { apr_table_set(r->notes, "GEOIP_CITY_V6", gir->city); } apr_table_setn(r->notes, "GEOIP_DMA_CODE_V6", metrocodestr); apr_table_setn(r->notes, "GEOIP_METRO_CODE_V6", metrocodestr); apr_table_setn(r->notes, "GEOIP_AREA_CODE_V6", areacodestr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE_V6", gir->continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE_V6", gir->country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME_V6", gir->country_name); if (gir->region != NULL) { apr_table_set(r->subprocess_env, "GEOIP_REGION_V6", gir->region); if ( region_name != NULL ){ apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME_V6", region_name); } } if (gir->city != NULL) { apr_table_set(r->subprocess_env, "GEOIP_CITY_V6", gir->city); } apr_table_setn(r->subprocess_env, "GEOIP_DMA_CODE_V6", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_METRO_CODE_V6", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_AREA_CODE_V6", areacodestr); } sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LATITUDE_V6", latstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE_V6", latstr); } if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LONGITUDE_V6", lonstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LONGITUDE_V6", lonstr); } if (gir->postal_code != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_set(r->notes, "GEOIP_POSTAL_CODE_V6", gir->postal_code); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_set(r->subprocess_env, "GEOIP_POSTAL_CODE_V6", gir->postal_code); } } GeoIPRecord_delete(gir); } break; case GEOIP_CITY_EDITION_REV0: case GEOIP_CITY_EDITION_REV1: gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr); if (gir != NULL) { if ( gir->country_code != NULL ) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE", gir->continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE", gir->country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME", gir->country_name); if (gir->region != NULL) { apr_table_set(r->notes, "GEOIP_REGION", gir->region); if ( region_name != NULL ){ apr_table_set(r->notes, "GEOIP_REGION_NAME", region_name); } } if (gir->city != NULL) { apr_table_set(r->notes, "GEOIP_CITY", gir->city); } apr_table_setn(r->notes, "GEOIP_DMA_CODE", metrocodestr); apr_table_setn(r->notes, "GEOIP_METRO_CODE", metrocodestr); apr_table_setn(r->notes, "GEOIP_AREA_CODE", areacodestr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE", gir->continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE", gir->country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME", gir->country_name); if (gir->region != NULL) { apr_table_set(r->subprocess_env, "GEOIP_REGION", gir->region); if ( region_name != NULL ){ apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME", region_name); } } if (gir->city != NULL) { apr_table_set(r->subprocess_env, "GEOIP_CITY", gir->city); } apr_table_setn(r->subprocess_env, "GEOIP_DMA_CODE", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_METRO_CODE", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_AREA_CODE", areacodestr); } sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LATITUDE", latstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE", latstr); } if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LONGITUDE", lonstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LONGITUDE", lonstr); } if (gir->postal_code != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_set(r->notes, "GEOIP_POSTAL_CODE", gir->postal_code); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_set(r->subprocess_env, "GEOIP_POSTAL_CODE", gir->postal_code); } } GeoIPRecord_delete(gir); } break; case GEOIP_ORG_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_ORGANIZATION", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_ORGANIZATION", orgorisp); } } break; case GEOIP_ISP_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_ISP", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_ISP", orgorisp); } } break; case GEOIP_DOMAIN_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_DOMAIN", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_DOMAIN", orgorisp); } } break; } } return OK; }
char *geo_lookup(GeoIP *gi, char *ipaddr, int bird) { /* * Lookup the country_code by ip address, we can * extend this in the future with more granular data * such as region,city or even zipcode. */ static char area[MAX_BUF_LENGTH]; // set the charset to UTF8 GeoIP_set_charset(gi, GEOIP_CHARSET_UTF8); switch(bird){ case COUNTRY: { const char *country= GeoIP_country_code_by_addr(gi, ipaddr); if (country==NULL){ strncpy(area, unknown_geography, MAX_BUF_LENGTH); } else { strncpy(area, country, MAX_BUF_LENGTH); } } break; case REGION:{ GeoIPRegion *gir; gir=GeoIP_region_by_addr(gi,ipaddr); if(gir == NULL || strlen(gir->region)==0){ strncpy(area, unknown_geography, MAX_BUF_LENGTH); } else { strncpy(area, gir->region, MAX_BUF_LENGTH); } if(gir != NULL) { GeoIPRegion_delete(gir); } break; } case CITY:{ GeoIPRecord *grecord; char *city; int mustFreeCity = 0; grecord = GeoIP_record_by_addr(gi, ipaddr); if (grecord !=NULL){ if (grecord->city == NULL){ strncpy(area, unknown_geography, MAX_BUF_LENGTH); } else { int len = strlen(grecord->city); city = strdup(grecord->city); mustFreeCity = 1; strncpy(area,city, MAX_BUF_LENGTH); replace_space_with_underscore(area, len); } if (mustFreeCity) { free(city); } GeoIPRecord_delete(grecord); } else { strncpy(area, unknown_geography, MAX_BUF_LENGTH); } break; } case LAT_LON: { GeoIPRecord *grecord; grecord = GeoIP_record_by_addr(gi, ipaddr); if (grecord!=NULL){ snprintf(area, MAX_BUF_LENGTH, "%f,%f", grecord->latitude, grecord->longitude); GeoIPRecord_delete(grecord); } else { strncpy(area, unknown_geography, MAX_BUF_LENGTH); } break; } case EVERYTHING: { GeoIPRecord *grecord; char *country = unknown_geography, *region = unknown_geography, *city = unknown_geography; int mustFreeCity = 0; float lat = 0.0, lon = 0.0; grecord = GeoIP_record_by_addr(gi, ipaddr); if (grecord != NULL) { if (grecord->city != NULL) { city = strdup(grecord->city); mustFreeCity = 1; } replace_space_with_underscore(city, strlen(city)); if (grecord->region != NULL) { region = grecord->region; } if (grecord->country_code != NULL) { country = grecord->country_code; } lat = grecord->latitude; lon = grecord->longitude; } snprintf(area, MAX_BUF_LENGTH, "%s|%s|%s|%f,%f", country, region, city, lat, lon); if (grecord != NULL) { GeoIPRecord_delete(grecord); } if (mustFreeCity) { free(city); } break; } default: break; } return area; }
static void get_geoip_tables(array_header *geoips, int filter_flags) { config_rec *c; c = find_config(main_server->conf, CONF_PARAM, "GeoIPTable", FALSE); while (c) { GeoIP *gi; const char *path; int flags, use_utf8 = FALSE; pr_signals_handle(); path = c->argv[0]; flags = *((int *) c->argv[1]); use_utf8 = *((int *) c->argv[2]); /* Make sure we open tables that are marked with the default * GEOIP_STANDARD flag, which has a value of zero. */ if ((flags == GEOIP_STANDARD && filter_flags != GEOIP_STANDARD) || !(flags & filter_flags)) { c = find_config_next(c, c->next, CONF_PARAM, "GeoIPTable", FALSE); continue; } PRIVS_ROOT gi = GeoIP_open(path, flags); if (gi == NULL && (flags & GEOIP_INDEX_CACHE)) { /* Per Bug#3975, a common cause of this error is the fact that some * of the Maxmind GeoIP Lite database files simply do not have indexes. * So try to open them as standard databases as a fallback. */ pr_log_debug(DEBUG8, MOD_GEOIP_VERSION ": unable to open GeoIPTable '%s' using the IndexCache flag " "(database lacks index?), retrying without IndexCache flag", path); flags &= ~GEOIP_INDEX_CACHE; gi = GeoIP_open(path, flags); } PRIVS_RELINQUISH if (gi != NULL) { if (use_utf8) { GeoIP_set_charset(gi, GEOIP_CHARSET_UTF8); } *((GeoIP **) push_array(geoips)) = gi; pr_trace_msg(trace_channel, 15, "loaded GeoIP table '%s': %s (type %d)", path, GeoIP_database_info(gi), GeoIP_database_edition(gi)); } else { /* XXX Sigh. Stupid libGeoIP library logs to stdout/stderr, rather * than providing a strerror function. Grr! */ pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION ": warning: unable to open/use GeoIPTable '%s'", path); } c = find_config_next(c, c->next, CONF_PARAM, "GeoIPTable", FALSE); } if (geoips->nelts == 0 && static_geoips->nelts == 0 && ((filter_flags == GEOIP_STANDARD) || (filter_flags & GEOIP_CHECK_CACHE))) { GeoIP *gi; /* Let the library use its own default database file(s), if no others * have been configured. */ PRIVS_ROOT gi = GeoIP_new(GEOIP_STANDARD); PRIVS_RELINQUISH if (gi != NULL) { *((GeoIP **) push_array(geoips)) = gi; pr_trace_msg(trace_channel, 15, "loaded default GeoIP table: %s (type %d)", GeoIP_database_info(gi), GeoIP_database_edition(gi)); } else { pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION ": warning: unable to open/use default GeoIP library database file(s)"); } }
/* Error message capture code inspired by code by Wolfgang Oertl. */ int luageoip_common_open_db( lua_State * L, const luaL_reg * M, int default_type, int default_flags, const char * mt_name, unsigned int bad_flags, size_t num_allowed_types, const int * allowed_types ) { /* First argument is checked later */ int flags = luaL_optint(L, 2, default_flags); int charset = luaL_optint(L, 2, GEOIP_CHARSET_UTF8); GeoIP * pGeoIP = NULL; luageoip_DB * pResult = NULL; int old_stderr; int pipefd[2]; char buf[256]; int error_reported = 0; if (bad_flags && (flags & bad_flags) == bad_flags) { /* TODO: Or is it concrete DB file problem? */ return luaL_error( L, "%s error: can't open db with these flags", mt_name ); } /* Errors are printed to stderr, capture them */ { /* TODO: Handle failures */ int result = pipe(pipefd); result = 0 + result; /* While we're not handling failures, shut up compiler */ fcntl(pipefd[0], F_SETFL, O_NONBLOCK); fcntl(pipefd[1], F_SETFL, O_NONBLOCK); old_stderr = dup(2); dup2(pipefd[1], 2); } if (lua_isnoneornil(L, 1)) { pGeoIP = GeoIP_open_type(default_type, flags); } else { const char * filename = luaL_checkstring(L, 1); pGeoIP = GeoIP_open(filename, flags); } /* Cleanup error handling */ { int n = read(pipefd[0], buf, sizeof(buf)); if (n >= 0) { buf[n] = 0; if (!pGeoIP) /* ?! What to do otherwise? */ { lua_pushnil(L); lua_pushstring(L, buf); error_reported = 1; } } close(pipefd[0]); close(pipefd[1]); dup2(old_stderr, 2); close(old_stderr); } if (pGeoIP) { int type = GeoIP_database_edition(pGeoIP); int found = 0; size_t i = 0; for (i = 0; i < num_allowed_types; ++i) { if (type == allowed_types[i]) { found = 1; break; } } if (!found) { lua_pushnil(L); lua_pushfstring( L, "%s error: unexpected db type in that file (%s)", mt_name, GeoIP_database_info(pGeoIP) ); error_reported = 1; GeoIP_delete(pGeoIP); pGeoIP = NULL; } } if (pGeoIP == NULL) { if (!error_reported) { lua_pushnil(L); lua_pushfstring( L, "%s error: failed to open database file", mt_name ); error_reported = 1; } return 2; /* nil and error message already on stack */ } GeoIP_set_charset(pGeoIP, charset); pResult = (luageoip_DB *)lua_newuserdata(L, sizeof(luageoip_DB)); pResult->pGeoIP = pGeoIP; if (luaL_newmetatable(L, mt_name)) { luaL_register(L, NULL, M); lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); } lua_setmetatable(L, -2); return 1; }
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { struct options *opts; FILE *fh; char *username; /* username requesting access */ char *rhost; /* remote host */ char *srv; /* PAM service we're running as */ char buf[LINE_LENGTH]; int retval, action; int is_v6 = 0; struct locations *geo; unsigned char gi_type; GeoIP *gi = NULL; #ifdef HAVE_GEOIP_010408 GeoIP *gi6 = NULL; int is_city6_db = 0; #endif GeoIPRecord *rec = NULL; opts = malloc(sizeof(struct options)); if (opts == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'opts': %m"); return PAM_SERVICE_ERR; } opts->charset = GEOIP_CHARSET_UTF8; opts->debug = 0; opts->action = PAM_PERM_DENIED; opts->system_file = NULL; opts->service_file = NULL; opts->by_service = 0; opts->geoip_db = NULL; #ifdef HAVE_GEOIP_010408 opts->use_v6 = 0; opts->v6_first = 0; opts->geoip6_db = NULL; #endif opts->is_city_db = 0; geo = malloc(sizeof(struct locations)); if (geo == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'geo': %m"); free_opts(opts); return PAM_SERVICE_ERR; } geo->country = NULL; geo->city = NULL; geo->next = NULL; _parse_args(pamh, argc, argv, opts); if (opts->system_file == NULL) opts->system_file = strdup(SYSTEM_FILE); if (opts->system_file == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'opts->system_file': %m"); free_opts(opts); return PAM_SERVICE_ERR; } if (opts->geoip_db == NULL) opts->geoip_db = strdup(GEOIPDB_FILE); if (opts->geoip_db == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'opts->geoip_db': %m"); free_opts(opts); return PAM_SERVICE_ERR; } #ifdef HAVE_GEOIP_010408 if (opts->geoip6_db == NULL) opts->geoip6_db = strdup(GEOIP6DB_FILE); if (opts->geoip6_db == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'opts->geoip6_db': %m"); free_opts(opts); return PAM_SERVICE_ERR; } #endif retval = pam_get_item(pamh, PAM_USER, (void*) &username); if (username == NULL || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "error recovering username"); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } retval = pam_get_item(pamh, PAM_RHOST, (void*) &rhost); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "error fetching rhost"); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } if (rhost == NULL) { pam_syslog(pamh, LOG_INFO, "rhost is NULL, allowing"); free_opts(opts); free_locations(geo); return PAM_SUCCESS; } retval = pam_get_item(pamh, PAM_SERVICE, (void*) &srv); if (srv == NULL || retval != PAM_SUCCESS ) { pam_syslog(pamh, LOG_CRIT, "error requesting service name"); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } opts->service_file = malloc(PATH_MAX); if (opts->service_file == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'service_file': %m"); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } if (snprintf(opts->service_file, PATH_MAX-1, SERVICE_FILE, srv) < 0) { pam_syslog(pamh, LOG_CRIT, "snprintf error 'service_file'"); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } gi = GeoIP_open(opts->geoip_db, GEOIP_INDEX_CACHE); if (gi == NULL) { pam_syslog(pamh, LOG_CRIT, "failed to open geoip db (%s): %m", opts->geoip_db); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } gi_type = GeoIP_database_edition(gi); if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP edition: %d", gi_type); switch (gi_type) { case GEOIP_COUNTRY_EDITION: if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP v4 edition: country"); opts->is_city_db = 0; break; case GEOIP_CITY_EDITION_REV0: if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP v4 edition: city rev0"); opts->is_city_db = 1; break; case GEOIP_CITY_EDITION_REV1: if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP v4 edition: city rev1"); opts->is_city_db = 1; break; default: pam_syslog(pamh, LOG_CRIT, "invalid GeoIP DB type `%d' found", gi_type); GeoIP_delete(gi); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } GeoIP_set_charset(gi, opts->charset); if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP DB is City: %s", opts->is_city_db ? "yes" : "no"); #ifdef HAVE_GEOIP_010408 if (opts->use_v6 != 0) { gi6 = GeoIP_open(opts->geoip6_db, GEOIP_INDEX_CACHE); if (gi6 == NULL) { pam_syslog(pamh, LOG_CRIT, "failed to open geoip6 db (%s): %m", opts->geoip6_db); GeoIP_delete(gi); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } gi_type = GeoIP_database_edition(gi6); switch (gi_type) { case GEOIP_COUNTRY_EDITION_V6: if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP v6 edition: country"); is_city6_db = 0; break; case GEOIP_CITY_EDITION_REV0_V6: if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP v6 edition: city rev0"); is_city6_db = 1; break; case GEOIP_CITY_EDITION_REV1_V6: if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP v6 edition: city rev1"); is_city6_db = 1; break; default: pam_syslog(pamh, LOG_CRIT, "invalid GeoIP DB type `%d' found", gi_type); GeoIP_delete(gi); GeoIP_delete(gi6); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP DB is City v6: %s", is_city6_db ? "yes" : "no"); GeoIP_set_charset(gi6, opts->charset); if (opts->is_city_db != is_city6_db) { pam_syslog(pamh, LOG_CRIT, "IPv4 DB type is not the same as IPv6 (not both Country edition or both City edition)"); GeoIP_delete(gi); GeoIP_delete(gi6); free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } if (opts->v6_first != 0) { rec = GeoIP_record_by_name_v6(gi6, rhost); if (rec == NULL) { if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "no IPv6 record for %s, trying IPv4", rhost); rec = GeoIP_record_by_name(gi, rhost); } else is_v6 = 1; } else { rec = GeoIP_record_by_name(gi, rhost); if (rec == NULL) { if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "no IPv4 record for %s, trying IPv6", rhost); rec = GeoIP_record_by_name_v6(gi6, rhost); if (rec != NULL) is_v6 = 1; } } } else #endif /* HAVE_GEOIP_010408 */ rec = GeoIP_record_by_name(gi, rhost); if (rec == NULL) { pam_syslog(pamh, LOG_INFO, "no record for %s, setting GeoIP to 'UNKNOWN,*'", rhost); geo->city = strdup("*"); geo->country = strdup("UNKNOWN"); if (geo->city == NULL || geo->country == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'geo->{city,country}': %m"); GeoIP_delete(gi); #ifdef HAVE_GEOIP_010408 GeoIP_delete(gi6); #endif free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } } else { if (rec->city == NULL || opts->is_city_db == 0) geo->city = strdup("*"); else geo->city = strdup(rec->city); if (rec->country_code == NULL) geo->country = strdup("UNKNOWN"); else geo->country = strdup(rec->country_code); if (geo->city == NULL || geo->country == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc error 'geo->{city,country}': %m"); GeoIP_delete(gi); #ifdef HAVE_GEOIP_010408 GeoIP_delete(gi6); #endif free_opts(opts); free_locations(geo); return PAM_SERVICE_ERR; } if (opts->is_city_db) { geo->latitude = rec->latitude; geo->longitude = rec->longitude; } } if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "GeoIP record for %s: %s,%s", rhost, geo->country, geo->city); if (opts->debug && strcmp(geo->country, "UNKNOWN") != 0 && opts->is_city_db) pam_syslog(pamh, LOG_DEBUG, "GeoIP coordinates for %s: %f,%f", rhost, geo->latitude, geo->longitude); if ((fh = fopen(opts->service_file, "r")) != NULL) { opts->by_service = 1; if (opts->debug) pam_syslog(pamh, LOG_DEBUG, "using services file %s", opts->service_file); } else { if ((fh = fopen(opts->system_file, "r")) == NULL) { pam_syslog(pamh, LOG_CRIT, "error opening %s: %m", opts->system_file); #ifdef HAVE_GEOIP_010408 if (gi6) GeoIP_delete(gi6); #endif if (gi) GeoIP_delete(gi); if (rec) GeoIPRecord_delete(rec); free_opts(opts); return PAM_SERVICE_ERR; } } action = opts->action; char location[LINE_LENGTH]; while (fgets(buf, LINE_LENGTH, fh) != NULL) { char *line, *ptr; char domain[LINE_LENGTH], service[LINE_LENGTH]; action = opts->action; line = buf; /* skip the leading white space */ while (*line && isspace(*line)) line++; /* Rip off the comments */ ptr = strchr(line,'#'); if (ptr) *ptr = '\0'; /* Rip off the newline char */ ptr = strchr(line,'\n'); if (ptr) *ptr = '\0'; /* Anything left ? */ if (!strlen(line)) continue; if (opts->by_service) action = parse_line_srv(pamh, line, domain, location); else action = parse_line_sys(pamh, line, domain, service, location); if (action < 0) { /* parsing failed */ action = opts->action; continue; } if (!opts->by_service) { if (!check_service(pamh, service, srv)) continue; } if ((strcmp(domain, "*") == 0) || (strcmp(username, domain) == 0)) { if (check_location(pamh, opts, location, geo)) break; } else if (domain[0] == '@') { if (pam_modutil_user_in_group_nam_nam(pamh, username, domain+1)) { if (check_location(pamh, opts, location, geo)) break; } } } fclose(fh); if (gi) GeoIP_delete(gi); #ifdef HAVE_GEOIP_010408 if (gi6) GeoIP_delete(gi6); #endif if (rec) GeoIPRecord_delete(rec); free_locations(geo); switch (action) { case PAM_SUCCESS: pam_syslog(pamh, LOG_DEBUG, "location %s allowed for user %s from %s (IPv%d)", location, username, rhost, is_v6 ? 6 : 4); break; case PAM_PERM_DENIED: pam_syslog(pamh, LOG_DEBUG, "location %s denied for user %s from %s (IPv%d)", location, username, rhost, is_v6 ? 6 : 4); break; case PAM_IGNORE: pam_syslog(pamh, LOG_DEBUG, "location %s ignored for user %s from %s (IPv%d)", location, username, rhost, is_v6 ? 6 : 4); break; default: /* should not happen */ pam_syslog(pamh, LOG_DEBUG, "location status: %d, IPv%d", action, is_v6 ? 6 : 4); break; }; free_opts(opts); return action; }