mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
occtl: use maxminddb when available
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
This commit is contained in:
1
NEWS
1
NEWS
@@ -5,6 +5,7 @@
|
||||
at the same time.
|
||||
- occtl: fixed json output of show status command. Introduced tests
|
||||
for checking its json output using yajl (#220).
|
||||
- occtl: use maxminddb when available.
|
||||
|
||||
|
||||
* Version 0.12.4 (released 2019-07-03)
|
||||
|
||||
18
configure.ac
18
configure.ac
@@ -163,13 +163,28 @@ if test "$test_for_libnl" = yes;then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(maxmind,
|
||||
AS_HELP_STRING([--without-maxmind], [do not try to use the maxmind library]),
|
||||
test_for_maxmind=$withval,
|
||||
test_for_maxmind=yes)
|
||||
|
||||
have_maxmind=no
|
||||
if test "$test_for_maxmind" = yes;then
|
||||
PKG_CHECK_MODULES(MAXMIND, libmaxminddb >= 1.0.0, [have_maxmind=yes], [have_maxmind=no])
|
||||
if test "$have_maxmind" = yes;then
|
||||
AC_DEFINE(HAVE_MAXMIND, 1, [have libmaxminddb])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_MAXMIND, test "x$have_maxmind" != xno)
|
||||
|
||||
AC_ARG_WITH(geoip,
|
||||
AS_HELP_STRING([--without-geoip], [do not try to use the geoip library]),
|
||||
test_for_geoip=$withval,
|
||||
test_for_geoip=yes)
|
||||
|
||||
have_geoip=no
|
||||
if test "$test_for_geoip" = yes;then
|
||||
if test "$test_for_geoip" = yes && test "$have_maxmind" != yes;then
|
||||
PKG_CHECK_MODULES(GEOIP, geoip >= 1.6.0, [have_geoip=yes], [have_geoip=no])
|
||||
if test "$have_geoip" = yes;then
|
||||
AC_DEFINE(HAVE_GEOIP, 1, [have libgeoip])
|
||||
@@ -601,6 +616,7 @@ Summary of build options:
|
||||
libnl3: ${have_libnl3}
|
||||
liboath: ${have_liboath}
|
||||
libgeoip: ${have_geoip}
|
||||
libmaxminddb: ${have_maxmind}
|
||||
glibc (sha2crypt): ${have_glibc}
|
||||
local talloc: ${with_local_talloc}
|
||||
local protobuf-c: ${with_local_protobuf_c}
|
||||
|
||||
@@ -98,15 +98,22 @@ clean-local:
|
||||
|
||||
bin_PROGRAMS = occtl/occtl
|
||||
|
||||
occtl_occtl_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/occtl $(LIBNL3_CFLAGS) $(GEOIP_CFLAGS)
|
||||
occtl_occtl_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/occtl $(LIBNL3_CFLAGS) $(GEOIP_CFLAGS) $(MAXMIND_CFLAGS)
|
||||
occtl_occtl_SOURCES = occtl/occtl.c occtl/pager.c occtl/occtl.h occtl/time.c occtl/cache.c \
|
||||
occtl/ip-cache.c occtl/nl.c occtl/ctl.h occtl/print.c occtl/json.c occtl/json.h \
|
||||
occtl/hex.c occtl/hex.h occtl/unix.c occtl/geoip.c occtl/geoip.h \
|
||||
occtl/hex.c occtl/hex.h occtl/unix.c occtl/geoip.h \
|
||||
occtl/session-cache.c
|
||||
|
||||
if HAVE_MAXMIND
|
||||
occtl_occtl_SOURCES += occtl/maxmind.c
|
||||
else
|
||||
occtl_occtl_SOURCES += occtl/geoip.c
|
||||
endif
|
||||
|
||||
occtl_occtl_LDADD = ../gl/libgnu.a libcommon.a $(LIBREADLINE_LIBS) \
|
||||
$(LIBNL3_LIBS) $(NEEDED_LIBPROTOBUF_LIBS) $(LIBTALLOC_LIBS) libccan.a \
|
||||
libipc.a $(NEEDED_LIBPROTOBUF_LIBS) $(CODE_COVERAGE_LDFLAGS) \
|
||||
$(LIBNETTLE_LIBS) $(GEOIP_LIBS)
|
||||
$(LIBNETTLE_LIBS) $(MAXMIND_LIBS) $(GEOIP_LIBS)
|
||||
|
||||
# Ocpasswd
|
||||
|
||||
|
||||
171
src/occtl/maxmind.c
Normal file
171
src/occtl/maxmind.c
Normal file
@@ -0,0 +1,171 @@
|
||||
#include <config.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "geoip.h"
|
||||
|
||||
#ifdef HAVE_MAXMIND
|
||||
#include <maxminddb.h>
|
||||
|
||||
#ifndef MAXMINDDB_LOCATION_COUNTRY
|
||||
#define MAXMINDDB_LOCATION_COUNTRY "/usr/share/GeoIP/GeoLite2-Country.mmdb"
|
||||
#endif
|
||||
|
||||
#ifndef MAXMINDDB_LOCATION_CITY
|
||||
#define MAXMINDDB_LOCATION_CITY "/usr/share/GeoIP/GeoLite2-City.mmdb"
|
||||
#endif
|
||||
|
||||
#define pMMDB_close MMDB_close
|
||||
#define pMMDB_get_value MMDB_get_value
|
||||
#define pMMDB_lookup_string MMDB_lookup_string
|
||||
#define pMMDB_open MMDB_open
|
||||
|
||||
void process_result_from_mmdb_lookup(MMDB_entry_data_s * entry_data, int status,
|
||||
char **output)
|
||||
{
|
||||
if (MMDB_SUCCESS == status) {
|
||||
if (entry_data->has_data) {
|
||||
if (entry_data->type == MMDB_DATA_TYPE_UTF8_STRING) {
|
||||
*output =
|
||||
(char *)calloc(entry_data->data_size + 1,
|
||||
sizeof(char));
|
||||
if (NULL != *output) {
|
||||
memcpy(*output, entry_data->utf8_string,
|
||||
entry_data->data_size);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Memory allocation failure line %d\n",
|
||||
__LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Else fail silently */
|
||||
}
|
||||
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
{
|
||||
MMDB_s mmdb;
|
||||
MMDB_entry_data_s entry_data;
|
||||
int gai_error, mmdb_error, status, coordinates = 0;
|
||||
double latitude, longitude;
|
||||
char *country = NULL, *ccode = NULL;
|
||||
char *coord = NULL;
|
||||
unsigned found = 0;
|
||||
|
||||
/* Open the system maxmind database with countries */
|
||||
status = pMMDB_open(MAXMINDDB_LOCATION_COUNTRY, MMDB_MODE_MMAP, &mmdb);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
/* Lookup IP address in the database */
|
||||
MMDB_lookup_result_s result =
|
||||
pMMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
|
||||
if (MMDB_SUCCESS == mmdb_error) {
|
||||
/* If the lookup was successfull and an entry was found */
|
||||
if (result.found_entry) {
|
||||
memset(&entry_data, 0,
|
||||
sizeof(MMDB_entry_data_s));
|
||||
/* Travel the path in the tree like structure of the MMDB and store the value if found */
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"country", "names", "en",
|
||||
NULL);
|
||||
process_result_from_mmdb_lookup(&entry_data,
|
||||
status,
|
||||
&country);
|
||||
memset(&entry_data, 0,
|
||||
sizeof(MMDB_entry_data_s));
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"country", "iso_code",
|
||||
NULL);
|
||||
process_result_from_mmdb_lookup(&entry_data,
|
||||
status, &ccode);
|
||||
}
|
||||
}
|
||||
/* Else fail silently */
|
||||
pMMDB_close(&mmdb);
|
||||
}
|
||||
/* Else fail silently */
|
||||
|
||||
/* Open the system maxmind database with cities - which actually does not contain names of the cities */
|
||||
status = pMMDB_open(MAXMINDDB_LOCATION_CITY, MMDB_MODE_MMAP, &mmdb);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
/* Lookup IP address in the database */
|
||||
MMDB_lookup_result_s result =
|
||||
pMMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
|
||||
if (MMDB_SUCCESS == mmdb_error) {
|
||||
/* If the lookup was successfull and an entry was found */
|
||||
if (result.found_entry) {
|
||||
memset(&entry_data, 0,
|
||||
sizeof(MMDB_entry_data_s));
|
||||
// NOTE: Information about the city is not available in the free database, so there is not way
|
||||
// for me to implement this functionality right now, but it should be easy to add for anyone with
|
||||
// access to the paid databases.
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"location", "latitude",
|
||||
NULL);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
if (entry_data.has_data) {
|
||||
if (entry_data.type ==
|
||||
MMDB_DATA_TYPE_DOUBLE) {
|
||||
latitude =
|
||||
entry_data.
|
||||
double_value;
|
||||
++coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"location", "longitude",
|
||||
NULL);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
if (entry_data.has_data) {
|
||||
if (entry_data.type ==
|
||||
MMDB_DATA_TYPE_DOUBLE) {
|
||||
longitude =
|
||||
entry_data.
|
||||
double_value;
|
||||
++coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (coordinates == 2) {
|
||||
asprintf(&coord, "%f,%f", latitude,
|
||||
longitude);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
pMMDB_close(&mmdb);
|
||||
}
|
||||
|
||||
if (country && coord) {
|
||||
snprintf(buf, buf_size, "%s (%s)", country, coord);
|
||||
found = 1;
|
||||
} else if (ccode && coord) {
|
||||
snprintf(buf, buf_size, "%s (%s)", ccode, coord);
|
||||
found = 1;
|
||||
} else if (country) {
|
||||
snprintf(buf, buf_size, "%s", country);
|
||||
found = 1;
|
||||
} else if (ccode) {
|
||||
snprintf(buf, buf_size, "%s", ccode);
|
||||
found = 1;
|
||||
}
|
||||
|
||||
free(ccode);
|
||||
free(country);
|
||||
free(coord);
|
||||
|
||||
if (found)
|
||||
return buf;
|
||||
else
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user