int geoip_update_pv(str *tomatch, str *name) { sr_geoip_record_t *gr = NULL; if(tomatch->len>255) { LM_DBG("target too long (max 255): %s\n", tomatch->s); return -3; } gr = sr_geoip_get_record(name); if(gr==NULL) { LM_DBG("container not found: %s\n", tomatch->s); return - 4; } strncpy(gr->tomatch, tomatch->s, tomatch->len); gr->tomatch[tomatch->len] = '\0'; gr->record = GeoIP_record_by_name(_handle_GeoIP, (const char*)gr->tomatch); LM_DBG("attempt to match: %s\n", gr->tomatch); if (gr->record == NULL) { LM_DBG("no match for: %s\n", gr->tomatch); return -2; } LM_DBG("geoip PV updated for: %s\n", gr->tomatch); return 1; }
void geoip_get_country (const char *ip, char *location) { GeoIPRecord *rec = NULL; const char *country = NULL, *code = NULL, *addr = ip; int geoid = 0; /* Custom GeoIP database */ if (conf.geoip_city_data != NULL && geo_location_data != NULL) { rec = GeoIP_record_by_name (geo_location_data, addr); if (rec) { code = rec->country_code; country = rec->country_name; } } /* Legacy GeoIP database */ else if (geo_location_data != NULL) { geoid = GeoIP_id_by_name (geo_location_data, addr); country = GeoIP_country_name_by_name (geo_location_data, addr); code = GeoIP_code_by_id (geoid); } geoip_set_country (country, code, location); if (rec != NULL) GeoIPRecord_delete (rec); }
char *GetGeoInfobyIP(char *ip_addr) { GeoIPRecord *geoiprecord; char *geodata = NULL; char geobuffer[256 +1]; if(!geoipdb) { return(NULL); } if(!ip_addr) { return(NULL); } geoiprecord = GeoIP_record_by_name(geoipdb, (const char *)ip_addr); if(geoiprecord == NULL) { return(NULL); } if(geoiprecord->country_code3 == NULL || geoiprecord->country_code == NULL) { GeoIPRecord_delete(geoiprecord); return(NULL); } if(geoiprecord->country_code3[0] == NULL || strlen(geoiprecord->country_code3) < 2) { GeoIPRecord_delete(geoiprecord); return(NULL); } if(geoiprecord->region != NULL && geoiprecord->region[0] != NULL) { char *regionname = NULL; regionname = GeoIP_region_name_by_code(geoiprecord->country_code, geoiprecord->region); if(regionname != NULL) { snprintf(geobuffer, 255, "%s / %s", geoiprecord->country_code3, regionname); geobuffer[255] = '\0'; geodata = strdup(geobuffer); } else { geodata = strdup(geoiprecord->country_code3); } } else { geodata = strdup(geoiprecord->country_code3); } GeoIPRecord_delete(geoiprecord); return(geodata); }
int main(int argc, char **argv) { const char *geoipfilename = DEFAULT_GEOIPFILE; GeoIP *gip = NULL; GeoIPRecord *gir = NULL; char *name; const char *region_name; int edition, i; if ((argc != 2) && (argc != 4)) { printf("Usage: geoiplookup_city [-f custom_file] <hostname_or_ip>\n"); return 1; } i = 1; while (i < argc) { if (strcmp(argv[i],"-f") == 0) { if ((i+1) < argc){ i++; geoipfilename = argv[i]; } } else { name = argv[i]; } i++; } gip = GeoIP_open(geoipfilename, GEOIP_STANDARD); edition = GeoIP_database_edition(gip); if (edition == GEOIP_COUNTRY_EDITION) { short int country_id = GeoIP_country_id_by_name(gip, name); region_name = GeoIP_country_continent[country_id]; printf("%s\n", region_name); } else if ((edition == GEOIP_CITY_EDITION_REV0) || (edition == GEOIP_CITY_EDITION_REV1)) { gir = GeoIP_record_by_name(gip, name); if (NULL == gir) { printf("%s: IP Address not found\n", GeoIPDBDescription[edition]); return 1; } else { printf("Continent: %s\n" "Country: %s\n" "Region id: %s\n" "Region: %s\n" "City: %s\n" "Latitude: %f\n" "Longitude: %f\n", gir->continent_code, gir->country_code, gir->region, GeoIP_region_name_by_code(gir->country_code, gir->region), gir->city, gir->latitude, gir->longitude); } } return 0; }
ipdata_t *ipdata_lookup(const char *inaddr, db_t *dbp) { char *city, *region, *country, *asnum, *empty = "X"; city = region = country = asnum = empty; ipdata_t *ip = NULL; GeoIPRecord *grp = NULL; if(!inaddr) return NULL; ip = MALLOCORDIE(sizeof(ipdata_t), "ipdata_lookup()"); ip->latitude = 0.0; ip->longitude = 0.0; /* Query the city database, if we have it. */ if(dbp->citygp) { if(opts.family == AF_INET6) grp = GeoIP_record_by_name_v6(dbp->citygp, inaddr); else grp = GeoIP_record_by_name(dbp->citygp, inaddr); if(grp) { if(grp->city) city = grp->city; if(grp->region) region = grp->region; if(grp->country_code) country = grp->country_code; ip->latitude = grp->latitude; ip->longitude = grp->longitude; } } /* Query the asnum database, if we have it. */ if(dbp->asgp) { if(opts.family == AF_INET6) asnum = GeoIP_org_by_name_v6(dbp->asgp, inaddr); else asnum = GeoIP_org_by_name(dbp->asgp, inaddr); if(!asnum) asnum = empty; } /* Copy data into ipdata_t for great thread safety. */ ip->address = MALLOCORDIE(strlen(inaddr) + 1, "ipdata_lookup()"); strcpy(ip->address, inaddr); ip->city = MALLOCORDIE(strlen(city) + 1, "ipdata_lookup()"); strcpy(ip->city, city); ip->region = MALLOCORDIE(strlen(region) + 1, "ipdata_lookup()"); strcpy(ip->region, region); ip->country = MALLOCORDIE(strlen(country) + 1, "ipdata_lookup()"); strcpy(ip->country, country); ip->asnum = MALLOCORDIE(strlen(asnum) + 1, "ipdata_lookup()"); strcpy(ip->asnum, asnum); if(strcmp(asnum, empty)) free(asnum); if(grp) GeoIPRecord_delete(grp); return ip; }
static gboolean geoip_parser_process(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const gchar *input, gsize input_len) { GeoIPParser *self = (GeoIPParser *) s; LogMessage *msg = log_msg_make_writable(pmsg, path_options); GeoIPRecord *record; SBGString *value; if (!self->dest.country_code && !self->dest.latitude && !self->dest.longitude) return TRUE; record = GeoIP_record_by_name(self->gi, input); if (!record) { const char *country; country = GeoIP_country_code_by_name(self->gi, input); if (country) log_msg_set_value_by_name(msg, self->dest.country_code, country, strlen(country)); return TRUE; } if (record->country_code) log_msg_set_value_by_name(msg, self->dest.country_code, record->country_code, strlen(record->country_code)); value = sb_gstring_acquire(); g_string_printf(sb_gstring_string(value), "%f", record->latitude); log_msg_set_value_by_name(msg, self->dest.latitude, sb_gstring_string(value)->str, sb_gstring_string(value)->len); g_string_printf(sb_gstring_string(value), "%f", record->longitude); log_msg_set_value_by_name(msg, self->dest.longitude, sb_gstring_string(value)->str, sb_gstring_string(value)->len); GeoIPRecord_delete(record); sb_gstring_release(value); return TRUE; }
int main(int argc, char *argv[]) { FILE *f; GeoIP *gi; GeoIPRecord *gir; int generate = 0; char host[50]; const char *time_zone = NULL; char **ret; if (argc == 2) { if (!strcmp(argv[1], "gen")) { generate = 1; } } gi = GeoIP_open("../data/GeoIPCity.dat", GEOIP_INDEX_CACHE); if (gi == NULL) { fprintf(stderr, "Error opening database\n"); exit(1); } f = fopen("city_test.txt", "r"); if (f == NULL) { fprintf(stderr, "Error opening city_test.txt\n"); exit(1); } while (fscanf(f, "%s", host) != EOF) { gir = GeoIP_record_by_name(gi, (const char *)host); if (gir != NULL) { ret = GeoIP_range_by_ip(gi, (const char *)host); time_zone = GeoIP_time_zone_by_country_and_region(gir->country_code, gir->region); printf("%s\t%s\t%s\t%s\t%s\t%s\t%f\t%f\t%d\t%d\t%s\t%s\t%s\n", host, _mk_NA(gir->country_code), _mk_NA(gir->region), _mk_NA(GeoIP_region_name_by_code (gir->country_code, gir->region)), _mk_NA(gir->city), _mk_NA(gir->postal_code), gir->latitude, gir->longitude, gir->metro_code, gir->area_code, _mk_NA(time_zone), ret[0], ret[1]); GeoIP_range_by_ip_delete(ret); GeoIPRecord_delete(gir); } } GeoIP_delete(gi); fclose(f); return 0; }
/* Get detailed information found in the GeoIP Database about the * given IPv4 or IPv6. * * On error, NULL is returned * On success, GeoIPRecord structure is returned */ static GeoIPRecord * get_geoip_record (const char *addr, GTypeIP type_ip) { GeoIPRecord *rec = NULL; if (TYPE_IPV4 == type_ip) rec = GeoIP_record_by_name (geo_location_data, addr); else if (TYPE_IPV6 == type_ip) rec = GeoIP_record_by_name_v6 (geo_location_data, addr); return rec; }
void set_geoip_info(struct userNode *user) { if(IsLocal(user)) return; /* Need the libs and the headers if this is going to compile properly */ #if defined(HAVE_LIBGEOIP)&&defined(HAVE_GEOIP_H)&&defined(HAVE_GEOIPCITY_H) GeoIPRecord * gir; const char *geoip_data_file = NULL; const char *geoip_city_file = NULL; geoip_data_file = conf_get_data("services/opserv/geoip_data_file", RECDB_QSTRING); geoip_city_file = conf_get_data("services/opserv/geoip_city_data_file", RECDB_QSTRING); if ((!geoip_data_file && !geoip_city_file)) return; /* Admin doesnt want to use geoip functions */ if (geoip_data_file && !gi) gi = GeoIP_open(geoip_data_file, GEOIP_MEMORY_CACHE | GEOIP_CHECK_CACHE); if (geoip_city_file && !cgi) cgi = GeoIP_open(geoip_city_file, GEOIP_MEMORY_CACHE | GEOIP_CHECK_CACHE); if (cgi) { gir = GeoIP_record_by_name(cgi, user->hostname); if (gir) { user->country_name = strdup(gir->country_name ? gir->country_name : ""); user->country_code = strdup(gir->country_code ? gir->country_code : ""); user->city = strdup(gir->city ? gir->city : ""); user->region = strdup(gir->region ? gir->region : ""); user->postal_code = strdup(gir->postal_code ? gir->postal_code : ""); user->latitude = gir->latitude ? gir->latitude : 0; user->longitude = gir->longitude ? gir->longitude : 0; user->dma_code = gir->dma_code ? gir->dma_code : 0; user->area_code = gir->area_code ? gir->area_code : 0; GeoIPRecord_delete(gir); } return; } else if (gi) { const char *country = GeoIP_country_name_by_name(gi, user->hostname); user->country_name = strdup(country ? country : ""); return; } return; #endif }
static PyObject * GeoIP_record_by_name_Py(PyObject *self, PyObject *args) { char * name; GeoIPRecord * gir; GeoIP_GeoIPObject* GeoIP = (GeoIP_GeoIPObject*)self; if (!PyArg_ParseTuple(args, "s", &name)) { return NULL; } gir = GeoIP_record_by_name(GeoIP->gi, name); if (gir == NULL) { Py_INCREF(Py_None); return Py_None; } return GeoIP_populate_dict(GeoIP->gi, gir); }
/* Use the GeoIP API to locate an IP address */ char *GeoIPLookup(char *ip) { GeoIP *gi; GeoIPRecord *gir; char buffer[OS_SIZE_1024 +1]; unsigned long longip; /* Dumb way to detect an IPv6 address */ if (strchr(ip, ':')) { /* Use the IPv6 DB */ gi = GeoIP_open(Config.geoip_db_path, GEOIP_INDEX_CACHE); if (gi == NULL) { merror(INVALID_GEOIP_DB, ARGV0, Config.geoip6_db_path); return("Unknown"); } gir = GeoIP_record_by_name_v6(gi, (const char *)ip); } else { /* Use the IPv4 DB */ /* If we have a RFC1918 IP, do not perform a DB lookup (performance) */ longip = StrIP2Int(ip); if (longip == 0 ) return("Unknown"); if ((longip & NETMASK_8) == RFC1918_10 || (longip & NETMASK_12) == RFC1918_172 || (longip & NETMASK_16) == RFC1918_192) return(""); gi = GeoIP_open(Config.geoip_db_path, GEOIP_INDEX_CACHE); if (gi == NULL) { merror(INVALID_GEOIP_DB, ARGV0, Config.geoip_db_path); return("Unknown"); } gir = GeoIP_record_by_name(gi, (const char *)ip); } if (gir != NULL) { sprintf(buffer,"%s,%s,%s", _mk_NA(gir->country_code), _mk_NA(GeoIP_region_name_by_code(gir->country_code, gir->region)), _mk_NA(gir->city) ); GeoIP_delete(gi); return(buffer); } GeoIP_delete(gi); return("Unknown"); }
/* Custom GeoIP database - i.e., GeoLiteCity.dat */ void geoip_get_city (const char *ip, char *location) { GeoIPRecord *rec = NULL; const char *city = NULL, *region = NULL, *addr = ip; if (geo_location_data != NULL) rec = GeoIP_record_by_name (geo_location_data, addr); if (rec != NULL) { city = rec->city; region = rec->region; } geoip_set_city (city, region, location); if (rec != NULL) GeoIPRecord_delete (rec); }
Array f_geoip_record_by_name(CStrRef hostname) { GeoIP * gi; Array return_value = Array::Create(); if (is_db_avail(GEOIP_CITY_EDITION_REV1, false)) { gi = s_geoip->gi[GEOIP_CITY_EDITION_REV1]; } else if (is_db_avail(GEOIP_CITY_EDITION_REV0)) { gi = s_geoip->gi[GEOIP_CITY_EDITION_REV0]; } else return return_value; GeoIPRecord * gir = GeoIP_record_by_name(gi, hostname); if (NULL == gir) { raise_notice("Host %s not found", hostname.data()); return return_value; } #if LIBGEOIP_VERSION >= 1004003 return_value.set("continent_code", (gir->continent_code == NULL) ? "" : gir->continent_code); #endif return_value.set("country_code", (gir->country_code == NULL) ? "" : gir->country_code); return_value.set("country_code3", (gir->country_code3 == NULL) ? "" : gir->country_code3); return_value.set("country_name", (gir->country_name == NULL) ? "" : gir->country_name); return_value.set("region", (gir->region == NULL) ? "" : gir->region); return_value.set("city", (gir->city == NULL) ? "" : gir->city); return_value.set("postal_code", (gir->postal_code == NULL) ? "" : gir->postal_code); return_value.set("latitude", gir->latitude); return_value.set("longitude", gir->longitude); #if LIBGEOIP_VERSION >= 1004005 return_value.set("dma_code", gir->metro_code); #else return_value.set("dma_code", gir->dma_code); #endif return_value.set("area_code", gir->area_code); GeoIPRecord_delete(gir); return return_value; }
void geoip_get_continent (const char *ip, char *location) { GeoIPRecord *rec = NULL; const char *continent = NULL, *addr = ip; int geoid = 0; /* Custom GeoIP database */ if (conf.geoip_city_data != NULL && geo_location_data != NULL) { rec = GeoIP_record_by_name (geo_location_data, addr); if (rec) continent = rec->continent_code; } /* Legacy GeoIP database */ else if (geo_location_data != NULL) { geoid = GeoIP_id_by_name (geo_location_data, addr); continent = GeoIP_continent_by_id (geoid); } if (rec != NULL) GeoIPRecord_delete (rec); geoip_set_continent (continent, location); }
static int mmg_lookup_cmd(struct sip_msg *msg, char *_fields_pv, char *_ipaddr_pv, char *_dst_spec) { pv_elem_t *fields_pv=(pv_elem_t*)_fields_pv, *ipaddr_pv=(pv_elem_t*)_ipaddr_pv; pv_spec_t *dst_spec=(pv_spec_t*)_dst_spec; GeoIPRecord *gir=0; str field_str, ipaddr_str; char rslt_buf[256], ipaddr_buf[256], field_buf[256]; char *token=0, *saveptr=0; int dst_name=-1; int_str rslt=(int_str)0; unsigned short dstType=0; /* Sanity checks */ if(!(ipaddr_pv && fields_pv && dst_spec)) { LM_ERR("Missing argument(s).\n"); return -1; } if(dst_spec->type != PVT_AVP) { LM_ERR("Invalid destination spec -- expected AVP.\n"); return -1; } if(pv_get_avp_name(msg, &(dst_spec->pvp), &dst_name, &dstType)!=0) { LM_ERR("Internal error getting AVP name.\n"); return -1; } /* Expand input args: lookup field list and IP address.*/ *ipaddr_buf=0; ipaddr_str.s=ipaddr_buf; ipaddr_str.len=sizeof ipaddr_buf; if(pv_printf(msg, ipaddr_pv, ipaddr_buf, &ipaddr_str.len) || ipaddr_str.len==0) { LM_ERR("Internal error parsing IP address.\n"); return -1; } *field_buf=0; field_str.s=field_buf; field_str.len=sizeof field_buf; if(pv_printf(msg, fields_pv, field_buf, &field_str.len) || field_str.len==0) { LM_ERR("Internal error parsing lookup fields.\n"); return -1; } /* Attempt lookup */ if(!(gir=GeoIP_record_by_name (MMG_gi,ipaddr_buf))){ LM_DBG("'%s'--> 'Unknown'.\n", *ipaddr_buf?ipaddr_buf:"Undefined"); return -1; } /* Construct return data. Know fields are: */ /* lat - latitude */ /* lon - longitude */ /* cont - continent */ /* cc - country code */ /* reg - region */ /* city - city */ /* pc - postal code */ /* dma - dma code */ /* ac - area code */ /* tz - timezone */ #define MMG_FAIL_EXIT if(gir) GeoIPRecord_delete(gir); return -1 LM_DBG("ipaddr:'%.*s'; fields:'%.*s'.\n", ipaddr_str.len, ipaddr_str.s, field_str.len, field_str.s); *rslt_buf=0; rslt.s.s=rslt_buf; token=strtok_r(field_buf,MMG_OP_DELIMS,&saveptr); while (token) { if(!strcmp(token,"lat")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%f",gir->latitude); } else if(!strcmp(token,"lon")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%f",gir->longitude); } else if(!strcmp(token,"cont")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%s",gir->continent_code); } else if(!strcmp(token,"cc")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%s",gir->country_code); } else if(!strcmp(token,"reg")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%s",gir->region); } else if(!strcmp(token,"city")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%s",gir->city); } else if(!strcmp(token,"pc")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%s",gir->postal_code); } else if(!strcmp(token,"dma")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%d",gir->dma_code); } else if(!strcmp(token,"ac")) { rslt.s.len=snprintf(rslt_buf,sizeof rslt_buf,"%d",gir->area_code); } else if(!strcmp(token,"rbc")) { rslt.s.len=snprintf( rslt_buf,sizeof rslt_buf,"%s",GeoIP_region_name_by_code(gir->country_code, gir->region)); } else if(!strcmp(token,"tz")) { rslt.s.len=snprintf( rslt_buf,sizeof rslt_buf,"%s",GeoIP_time_zone_by_country_and_region(gir->country_code, gir->region)); } else { LM_ERR("unknown field:'%s'\n",token); MMG_FAIL_EXIT; } if(rslt.s.len<0 || rslt.s.len>sizeof rslt_buf || add_avp(dstType|AVP_VAL_STR,dst_name,rslt)==-1 ) { LM_ERR("Internal error processing field/IP '%s/%s'.\n", token,ipaddr_buf); MMG_FAIL_EXIT; } LM_DBG("field %s[%s] %.*s\n",ipaddr_buf,token,rslt.s.len,rslt.s.s); token=strtok_r(0,MMG_OP_DELIMS,&saveptr); } GeoIPRecord_delete(gir); 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; }