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:
Michael Rash 2011-08-10 20:56:42 -04:00
parent 2dd7c4aac7
commit 0525cd4a5c
5 changed files with 173 additions and 36 deletions

View File

@ -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])
]
)

View File

@ -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)\"

View File

@ -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
);
}

View File

@ -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***/

View File

@ -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 */