Added autoconf support for non-dbm file cache.
This change starts on support for a simple file-based cache mechanism for tracking SPA digests. This removes the libgdbm/libndbm dependency by default, but it can be re-enabled with the --disable-file-cache argument to the ./configure script.
This commit is contained in:
parent
2dd7c4aac7
commit
0525cd4a5c
64
configure.ac
64
configure.ac
@ -69,6 +69,19 @@ AC_ARG_ENABLE([digest-cache],
|
||||
[])
|
||||
dnl AM_CONDITIONAL([WANT_DIGEST_CACHE], [test "$want_digest_cache" = yes])
|
||||
|
||||
dnl Decide whether or not to try to look for gdbm/ndbm (default to just
|
||||
dnl use a file-based solution - reduces dependencies)
|
||||
dnl
|
||||
want_file_cache=yes
|
||||
AC_ARG_ENABLE([file-cache],
|
||||
[AS_HELP_STRING([--disable-file-cache],
|
||||
[Replace file cache with gdbm/ndbm @<:@default on@:>@])],
|
||||
[want_file_cache=$enableval],
|
||||
[])
|
||||
AS_IF([test "$want_file_cache" = yes], [
|
||||
AC_DEFINE([USE_FILE_CACHE], [1], [Define this to enable non-gdbm/ndbm digest storing (eliminates gdbm/ndbm dependency).])
|
||||
])
|
||||
|
||||
AC_GNU_SOURCE
|
||||
|
||||
AC_PROG_CC
|
||||
@ -195,36 +208,40 @@ AS_IF([test "$want_server" = yes], [
|
||||
use_ndbm=no
|
||||
have_digest_cache=yes
|
||||
|
||||
# Looking for gdbm or fallback to ndbm or bail
|
||||
#
|
||||
AC_CHECK_LIB([gdbm],[gdbm_open],
|
||||
[
|
||||
AC_DEFINE([HAVE_LIBGDBM], [1], [Define if you have libgdbm])
|
||||
],
|
||||
[ AC_CHECK_LIB([ndbm],[dbm_open],
|
||||
[
|
||||
AC_DEFINE([HAVE_LIBNDBM], [1], [Define if you have libndbm])
|
||||
use_ndbm=yes
|
||||
],
|
||||
[ AC_CHECK_HEADER([ndbm.h],
|
||||
[ AC_CHECK_FUNC([dbm_open],
|
||||
[ AC_DEFINE([HAVE_LIBNDBM], [1], [Define if you have libndbm])],
|
||||
[
|
||||
AC_DEFINE([NO_DIGEST_CACHE], [1], [Define this to disable the digest cache for replay detection.])
|
||||
AC_MSG_WARN([No DBM implementation found. Replay detection will be disabled.])
|
||||
have_digest_cache=no
|
||||
]
|
||||
)]
|
||||
)]
|
||||
)]
|
||||
AS_IF([test "$want_file_cache" = no], [
|
||||
|
||||
# Looking for gdbm or fallback to ndbm or bail
|
||||
#
|
||||
AC_CHECK_LIB([gdbm],[gdbm_open],
|
||||
[
|
||||
AC_DEFINE([HAVE_LIBGDBM], [1], [Define if you have libgdbm])
|
||||
],
|
||||
[ AC_CHECK_LIB([ndbm],[dbm_open],
|
||||
[
|
||||
AC_DEFINE([HAVE_LIBNDBM], [1], [Define if you have libndbm])
|
||||
use_ndbm=yes
|
||||
],
|
||||
[ AC_CHECK_HEADER([ndbm.h],
|
||||
[ AC_CHECK_FUNC([dbm_open],
|
||||
[ AC_DEFINE([HAVE_LIBNDBM], [1], [Define if you have libndbm])],
|
||||
[
|
||||
AC_DEFINE([NO_DIGEST_CACHE], [1], [Define this to disable the digest cache for replay detection - not recommended.])
|
||||
AC_MSG_WARN([No DBM implementation found. Replay detection will be disabled.])
|
||||
have_digest_cache=no
|
||||
]
|
||||
)]
|
||||
)]
|
||||
)]
|
||||
)]
|
||||
)],
|
||||
[
|
||||
AC_DEFINE([NO_DIGEST_CACHE], [1], [Define this to disable the digest cache for replay detection.])
|
||||
AC_DEFINE([NO_DIGEST_CACHE], [1], [Define this to disable the digest cache for replay detection - not recommended.])
|
||||
have_digest_cache=no
|
||||
]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([USE_NDBM], [test x$use_ndbm = xyes])
|
||||
AM_CONDITIONAL([CONFIG_FILE_CACHE], [test x$want_file_cache = xyes])
|
||||
|
||||
dnl Check for iptables
|
||||
dnl
|
||||
@ -312,6 +329,7 @@ dnl
|
||||
[test "$want_server" = no], [
|
||||
use_ndbm=no
|
||||
AM_CONDITIONAL([USE_NDBM], [test x$use_ndbm = xno])
|
||||
AM_CONDITIONAL([CONFIG_FILE_CACHE], [test x$use_ndbm = xno])
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@ -12,11 +12,14 @@ fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
|
||||
fw_util_ipfw.c fw_util_ipfw.h
|
||||
|
||||
fwknopd_LDADD = $(top_builddir)/lib/libfko.la -lpcap
|
||||
|
||||
if ! CONFIG_FILE_CACHE
|
||||
if USE_NDBM
|
||||
fwknopd_LDADD += -lndbm
|
||||
else
|
||||
fwknopd_LDADD += -lgdbm
|
||||
endif
|
||||
endif
|
||||
|
||||
fwknopd_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common -DSYSCONFDIR=\"$(sysconfdir)\" -DSYSRUNDIR=\"$(localstatedir)\"
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ static pid_t get_running_pid(fko_srv_options_t *opts);
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int res, last_sig, rpdb_count;
|
||||
int res, last_sig, rp_cache_count;
|
||||
char *locale;
|
||||
pid_t old_pid;
|
||||
|
||||
@ -239,14 +239,15 @@ main(int argc, char **argv)
|
||||
dump_access_list(&opts);
|
||||
}
|
||||
|
||||
/* Initialize the digest cache for replay attack detection
|
||||
/* Initialize the digest cache for replay attack detection (either
|
||||
* with dbm support or with the default simple cache file strategy)
|
||||
* if so configured.
|
||||
*/
|
||||
if(strncasecmp(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
|
||||
{
|
||||
rpdb_count = replay_db_init(&opts);
|
||||
rp_cache_count = replay_cache_init(&opts);
|
||||
|
||||
if(rpdb_count < 0)
|
||||
if(rp_cache_count < 0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"Error opening digest cache file. Incoming digests will not be remembered."
|
||||
@ -257,7 +258,7 @@ main(int argc, char **argv)
|
||||
if(opts.verbose)
|
||||
log_msg(LOG_ERR,
|
||||
"Using Digest Cache: '%s' (entry count = %i)",
|
||||
opts.config[CONF_DIGEST_FILE], rpdb_count
|
||||
opts.config[CONF_DIGEST_FILE], rp_cache_count
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,9 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_LIBGDBM
|
||||
#if USE_FILE_CACHE
|
||||
|
||||
#elif HAVE_LIBGDBM
|
||||
#include <gdbm.h>
|
||||
|
||||
#define MY_DBM_FETCH(d, k) gdbm_fetch(d, k)
|
||||
@ -61,7 +63,7 @@
|
||||
#define MY_DBM_INSERT DBM_INSERT
|
||||
|
||||
#else
|
||||
#error "No GDBM or NDBM header file found. WTF?"
|
||||
#error "File cache method disabled, and No GDBM or NDBM header file found. WTF?"
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
@ -108,11 +110,39 @@ rotate_digest_cache_file(fko_srv_options_t *opts)
|
||||
#endif /* NO_DIGEST_CACHE */
|
||||
}
|
||||
|
||||
int
|
||||
replay_cache_init(fko_srv_options_t *opts)
|
||||
{
|
||||
#ifdef NO_DIGEST_CACHE
|
||||
return 0;
|
||||
#else
|
||||
|
||||
#if USE_FILE_CACHE
|
||||
return replay_file_cache_init(opts);
|
||||
#else
|
||||
return replay_db_cache_init(opts);
|
||||
#endif
|
||||
|
||||
#endif /* NO_DIGEST_CACHE */
|
||||
}
|
||||
|
||||
#if USE_FILE_CACHE
|
||||
int
|
||||
replay_file_cache_init(fko_srv_options_t *opts)
|
||||
{
|
||||
/* if the file exists, import the previous SPA digests into
|
||||
* the cache list
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* USE_FILE_CACHE */
|
||||
|
||||
/* Check for the existence of the replay dbm file, and create it if it does
|
||||
* not exist. Returns the number of db entries or -1 on error.
|
||||
*/
|
||||
int
|
||||
replay_db_init(fko_srv_options_t *opts)
|
||||
replay_db_cache_init(fko_srv_options_t *opts)
|
||||
{
|
||||
#ifdef NO_DIGEST_CACHE
|
||||
return 0;
|
||||
@ -173,6 +203,7 @@ replay_db_init(fko_srv_options_t *opts)
|
||||
return(db_count);
|
||||
#endif /* NO_DIGEST_CACHE */
|
||||
}
|
||||
#endif /* USE_FILE_CACHE */
|
||||
|
||||
/* Take an fko context, pull the digest and use it as the key to check the
|
||||
* replay db (digest cache). Returns 1 if there was a match (a replay),
|
||||
@ -185,6 +216,82 @@ replay_check(fko_srv_options_t *opts, fko_ctx_t ctx)
|
||||
return 0;
|
||||
#else
|
||||
|
||||
#if USE_FILE_CACHE
|
||||
return replay_check_file_cache(opts, ctx);
|
||||
#else
|
||||
return replay_check_dbm_cache(opts, ctx);
|
||||
#endif
|
||||
#endif /* NO_DIGEST_CACHE */
|
||||
}
|
||||
|
||||
#if USE_FILE_CACHE
|
||||
int
|
||||
replay_check_file_cache(fko_srv_options_t *opts, fko_ctx_t ctx)
|
||||
{
|
||||
char *digest = NULL;
|
||||
char src_ip[INET_ADDRSTRLEN+1] = {0};
|
||||
char dst_ip[INET_ADDRSTRLEN+1] = {0};
|
||||
int res = 0, digest_len = 0;
|
||||
FILE *digest_file_cache_ptr = NULL;
|
||||
|
||||
digest_cache_info_t dc_info, *dci_p;
|
||||
|
||||
res = fko_get_spa_digest(ctx, &digest);
|
||||
if(res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING, "Error getting digest from SPA data: %s",
|
||||
fko_errstr(res));
|
||||
|
||||
return(SPA_MSG_DIGEST_ERROR);
|
||||
}
|
||||
|
||||
digest_len = strlen(digest);
|
||||
|
||||
/* Check the cache for the key
|
||||
*/
|
||||
|
||||
if (0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a new SPA packet that needs to be added to the cache.
|
||||
*/
|
||||
|
||||
/* First, add the digest into the digest cache list
|
||||
*/
|
||||
|
||||
/* Now, write the digest to disk
|
||||
*/
|
||||
if ((digest_file_cache_ptr = fopen(opts->config[CONF_DIGEST_FILE], "a")) == NULL)
|
||||
{
|
||||
log_msg(LOG_WARNING, "Could not open digest cache: %s",
|
||||
opts->config[CONF_DIGEST_FILE]);
|
||||
return(SPA_MSG_DIGEST_CACHE_ERROR);
|
||||
}
|
||||
|
||||
inet_ntop(AF_INET, &(opts->spa_pkt.packet_src_ip),
|
||||
src_ip, INET_ADDRSTRLEN);
|
||||
fprintf(digest_file_cache_ptr, "%s %s %d\n",
|
||||
digest, src_ip, (unsigned int) time(NULL));
|
||||
|
||||
fclose(digest_file_cache_ptr);
|
||||
|
||||
res = SPA_MSG_SUCCESS;
|
||||
}
|
||||
|
||||
return(res);
|
||||
}
|
||||
#endif /* USE_FILE_CACHE */
|
||||
|
||||
#if !USE_FILE_CACHE
|
||||
int
|
||||
replay_check_dbm_cache(fko_srv_options_t *opts, fko_ctx_t ctx)
|
||||
{
|
||||
#ifdef NO_DIGEST_CACHE
|
||||
return 0;
|
||||
#else
|
||||
|
||||
#ifdef HAVE_LIBGDBM
|
||||
GDBM_FILE rpdb;
|
||||
#elif HAVE_LIBNDBM
|
||||
@ -250,7 +357,7 @@ replay_check(fko_srv_options_t *opts, fko_ctx_t ctx)
|
||||
inet_ntop(AF_INET, &(opts->spa_pkt.packet_src_ip),
|
||||
curr_ip, INET_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &(dci_p->src_ip), last_ip, INET_ADDRSTRLEN);
|
||||
|
||||
|
||||
/* Mark the last_replay time.
|
||||
*/
|
||||
dci_p->last_replay = time(NULL);
|
||||
@ -322,5 +429,6 @@ replay_check(fko_srv_options_t *opts, fko_ctx_t ctx)
|
||||
return(res);
|
||||
#endif /* NO_DIGEST_CACHE */
|
||||
}
|
||||
#endif /* USE_FILE_CACHE */
|
||||
|
||||
/***EOF***/
|
||||
|
||||
@ -28,8 +28,8 @@
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef REPLAY_DBM_H
|
||||
#define REPLAY_DBM_H
|
||||
#ifndef REPLAY_CACHE_H
|
||||
#define REPLAY_CACHE_H
|
||||
|
||||
#include "fwknopd_common.h"
|
||||
#include "fko.h"
|
||||
@ -44,7 +44,14 @@ typedef struct digest_cache_info {
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
int replay_db_init(fko_srv_options_t *opts);
|
||||
int replay_cache_init(fko_srv_options_t *opts);
|
||||
int replay_check(fko_srv_options_t *opts, fko_ctx_t ctx);
|
||||
#ifdef USE_FILE_CACHE
|
||||
int replay_file_cache_init(fko_srv_options_t *opts);
|
||||
int replay_check_file_cache(fko_srv_options_t *opts, fko_ctx_t ctx);
|
||||
#else
|
||||
int replay_db_cache_init(fko_srv_options_t *opts);
|
||||
int replay_check_dbm_cache(fko_srv_options_t *opts, fko_ctx_t ctx);
|
||||
#endif
|
||||
|
||||
#endif /* REPLAY_DBM_H */
|
||||
#endif /* REPLAY_CACHE_H */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user