Skip to content
Browse files

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.
  • Loading branch information...
1 parent 2dd7c4a commit 0525cd4a5caebad8c7f16d33df81e8b9cae1f4d9 @mrash committed Aug 10, 2011
Showing with 173 additions and 36 deletions.
  1. +41 −23 configure.ac
  2. +3 −0 server/Makefile.am
  3. +6 −5 server/fwknopd.c
  4. +112 −4 server/replay_cache.c
  5. +11 −4 server/replay_cache.h
View
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])
]
)
View
3 server/Makefile.am
@@ -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
11 server/fwknopd.c
@@ -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
116 server/replay_cache.c
@@ -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
15 server/replay_cache.h
@@ -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 */

0 comments on commit 0525cd4

Please sign in to comment.
Something went wrong with that request. Please try again.