コード例 #1
0
ファイル: geoip_pv.c プロジェクト: GreenfieldTech/kamailio
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;
}
コード例 #2
0
ファイル: geolocation.c プロジェクト: Chilledheart/goaccess
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);
}
コード例 #3
0
ファイル: geoip.c プロジェクト: alexoslabs/ossec-hids
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);
 
}
コード例 #4
0
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;
}
コード例 #5
0
ファイル: ipdata.c プロジェクト: protoben/geotrace
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;
}
コード例 #6
0
ファイル: geoip-parser.c プロジェクト: feelobot/syslog-ng
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;
}
コード例 #7
0
ファイル: test-geoip-city.c プロジェクト: 3sOx/asuswrt-merlin
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;
}
コード例 #8
0
ファイル: geolocation.c プロジェクト: Seravo/goaccess
/* 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;
}
コード例 #9
0
ファイル: hash.c プロジェクト: NX-Andro/x3
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
}
コード例 #10
0
ファイル: py_GeoIP.c プロジェクト: appneta/maxmind-geoip
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);
}
コード例 #11
0
ファイル: log.c プロジェクト: ospatrol/ospatrol
/* 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");
}
コード例 #12
0
ファイル: geolocation.c プロジェクト: Chilledheart/goaccess
/* 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);
}
コード例 #13
0
ファイル: ext_geoip.cpp プロジェクト: cdnewbee/hiphop-php
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;
}
コード例 #14
0
ファイル: geolocation.c プロジェクト: Chilledheart/goaccess
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);
}
コード例 #15
0
ファイル: mmgeoip.c プロジェクト: AndreiPlesa/opensips
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;
}
コード例 #16
0
ファイル: pam_geoip.c プロジェクト: vetinari/pam_geoip
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;
}