Fixed memory leak issue in libfko when fko_new_with_data() was called with a bad key. Added autoconf checks for gdbm with fallback to ndbm for server builds. Added digest cache capability using gdbm (in ndbm compatibility mode) or ndbm for replay detection.
git-svn-id: file:///home/mbr/svn/fwknop/trunk@153 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
parent
8b4b55fa44
commit
8c1261ca39
19
configure.ac
19
configure.ac
@ -189,15 +189,23 @@ AC_ARG_ENABLE([server],
|
|||||||
[])
|
[])
|
||||||
AM_CONDITIONAL([WANT_SERVER], [test "$want_server" = yes])
|
AM_CONDITIONAL([WANT_SERVER], [test "$want_server" = yes])
|
||||||
|
|
||||||
dnl Check for libpcap if we are building the server component
|
dnl Check for libpcap, gdbm (or ndbm) if we are building the server component
|
||||||
dnl
|
dnl
|
||||||
have_pcap=yes
|
|
||||||
AS_IF([test "$want_server" = yes],
|
AS_IF([test "$want_server" = yes],
|
||||||
AC_CHECK_LIB([pcap],[pcap_open_live],
|
# Looking for libpcap
|
||||||
AC_DEFINE([HAVE_LIBPCAP], [1], [Define if you have libpcap]), [have_pcap=no]
|
#
|
||||||
|
AC_CHECK_LIB([pcap],[pcap_open_live], [],
|
||||||
|
[ AC_MSG_ERROR([fwknopd needs libpcap])]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Looking for gdbm or fallback to ndbm or bail
|
||||||
|
#
|
||||||
|
AC_CHECK_LIB([gdbm],[dbm_open], [],
|
||||||
|
[ AC_CHECK_LIB([ndbm],[dbm_open], [],
|
||||||
|
[ AC_MSG_ERROR([fwknopd needs either gdbm or ndbm])]
|
||||||
|
)]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AM_CONDITIONAL([HAVE_LIBPCAP],[test "$have_pcap" = yes])
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
lib/Makefile
|
lib/Makefile
|
||||||
@ -213,6 +221,5 @@ echo "
|
|||||||
============================================
|
============================================
|
||||||
Client build: $want_client
|
Client build: $want_client
|
||||||
Server build: $want_server
|
Server build: $want_server
|
||||||
- with libpcap: $have_pcap
|
|
||||||
GPG encryption support: $have_gpgme
|
GPG encryption support: $have_gpgme
|
||||||
"
|
"
|
||||||
|
|||||||
@ -111,6 +111,7 @@ _rijndael_decrypt(fko_ctx_t ctx, char *dec_key, int b64_len)
|
|||||||
return(FKO_ERROR_MEMORY_ALLOCATION);
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
memmove(tbuf+strlen(B64_RIJNDAEL_SALT), tbuf, b64_len);
|
memmove(tbuf+strlen(B64_RIJNDAEL_SALT), tbuf, b64_len);
|
||||||
|
|
||||||
ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));
|
ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));
|
||||||
|
|
||||||
/* Adjust b64_len for added SALT value and Make sure we are still
|
/* Adjust b64_len for added SALT value and Make sure we are still
|
||||||
|
|||||||
@ -158,12 +158,11 @@ int
|
|||||||
fko_new_with_data(fko_ctx_t *r_ctx, char *enc_msg, char *dec_key)
|
fko_new_with_data(fko_ctx_t *r_ctx, char *enc_msg, char *dec_key)
|
||||||
{
|
{
|
||||||
fko_ctx_t ctx;
|
fko_ctx_t ctx;
|
||||||
|
int res = FKO_SUCCESS; /* Are we optimistic or what? */
|
||||||
|
|
||||||
int res = fko_new(r_ctx);
|
ctx = calloc(1, sizeof *ctx);
|
||||||
if(res != FKO_SUCCESS)
|
if(ctx == NULL)
|
||||||
return res;
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
|
|
||||||
ctx = *r_ctx;
|
|
||||||
|
|
||||||
/* First, add the data to the context.
|
/* First, add the data to the context.
|
||||||
*/
|
*/
|
||||||
@ -174,13 +173,35 @@ fko_new_with_data(fko_ctx_t *r_ctx, char *enc_msg, char *dec_key)
|
|||||||
return(FKO_ERROR_MEMORY_ALLOCATION);
|
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Consider it initialized here.
|
||||||
|
*/
|
||||||
|
ctx->initval = FKO_CTX_INITIALIZED;
|
||||||
|
FKO_SET_CTX_INITIALIZED(ctx);
|
||||||
|
|
||||||
/* If a decryption password is provided, go ahead and decrypt and
|
/* If a decryption password is provided, go ahead and decrypt and
|
||||||
* decode.
|
* decode.
|
||||||
*/
|
*/
|
||||||
if(dec_key != NULL)
|
if(dec_key != NULL)
|
||||||
return(fko_decrypt_spa_data(ctx, dec_key));
|
{
|
||||||
|
res = fko_decrypt_spa_data(ctx, dec_key);
|
||||||
|
|
||||||
return(FKO_SUCCESS);
|
if(res != FKO_SUCCESS)
|
||||||
|
{
|
||||||
|
fko_destroy(ctx);
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_LIBGPGME
|
||||||
|
/* Set gpg signature verify on.
|
||||||
|
*/
|
||||||
|
ctx->verify_gpg_sigs = 1;
|
||||||
|
#endif /* HAVE_LIBGPGME */
|
||||||
|
|
||||||
|
|
||||||
|
*r_ctx = ctx;
|
||||||
|
|
||||||
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy a context and free its resources
|
/* Destroy a context and free its resources
|
||||||
|
|||||||
@ -4,14 +4,10 @@ fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
|
|||||||
fwknopd_common.h incoming_spa.c incoming_spa.h \
|
fwknopd_common.h incoming_spa.c incoming_spa.h \
|
||||||
pcap_capture.c pcap_capture.h process_packet.c \
|
pcap_capture.c pcap_capture.h process_packet.c \
|
||||||
process_packet.h log_msg.c log_msg.h utils.c utils.h \
|
process_packet.h log_msg.c log_msg.h utils.c utils.h \
|
||||||
sig_handler.c sig_handler.h
|
sig_handler.c sig_handler.h replay_dbm.c replay_dbm.h
|
||||||
|
|
||||||
fwknopd_LDADD = $(top_builddir)/lib/libfko.la
|
fwknopd_LDADD = $(top_builddir)/lib/libfko.la
|
||||||
|
|
||||||
if HAVE_LIBPCAP
|
|
||||||
fwknopd_LDADD += -lpcap
|
|
||||||
endif
|
|
||||||
|
|
||||||
fwknopd_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common -DSYSCONFDIR=\"$(sysconfdir)\"
|
fwknopd_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||||
|
|
||||||
fwknopddir = @sysconfdir@/fwknop
|
fwknopddir = @sysconfdir@/fwknop
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
#include "log_msg.h"
|
#include "log_msg.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sig_handler.h"
|
#include "sig_handler.h"
|
||||||
|
#include "replay_dbm.h"
|
||||||
|
|
||||||
/* Prototypes
|
/* Prototypes
|
||||||
*/
|
*/
|
||||||
@ -44,7 +45,7 @@ int
|
|||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fko_ctx_t ctx;
|
fko_ctx_t ctx;
|
||||||
int res, last_sig;
|
int res, last_sig, rpdb_count;
|
||||||
char *spa_data, *version;
|
char *spa_data, *version;
|
||||||
char access_buf[MAX_LINE_LEN];
|
char access_buf[MAX_LINE_LEN];
|
||||||
pid_t old_pid;
|
pid_t old_pid;
|
||||||
@ -176,11 +177,11 @@ main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_LIBPCAP
|
/* Initialize the digest cache (replay attack detection dbm).
|
||||||
log_msg(LOG_ERR|LOG_STDERR,
|
*/
|
||||||
"libpcap is not avaiable, I'm hosed (for now).");
|
rpdb_count = replay_db_init(&opts);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
#endif
|
fprintf(stderr, "RPDB Count: %i\n", rpdb_count);
|
||||||
|
|
||||||
/* Intiate pcap capture mode...
|
/* Intiate pcap capture mode...
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "fwknopd_common.h"
|
#include "fwknopd_common.h"
|
||||||
#include "incoming_spa.h"
|
#include "incoming_spa.h"
|
||||||
|
#include "log_msg.h"
|
||||||
|
|
||||||
/* The pcap capture routine.
|
/* The pcap capture routine.
|
||||||
*/
|
*/
|
||||||
@ -45,27 +46,35 @@ fprintf(stderr, "SPA Packet: '%s'\n", spa_pkt->packet_data);
|
|||||||
|
|
||||||
/* Get the decryption key
|
/* Get the decryption key
|
||||||
*/
|
*/
|
||||||
|
// TODO: finish me
|
||||||
|
|
||||||
|
/* Decode the packet data
|
||||||
|
* --DSS TEMP note using the hard-coded "sdf" as the password.
|
||||||
|
* this is just for dev testing until I get the
|
||||||
|
* access.conf handling in.
|
||||||
|
*/
|
||||||
res = fko_new_with_data(&ctx, spa_pkt->packet_data, "sdf");
|
res = fko_new_with_data(&ctx, spa_pkt->packet_data, "sdf");
|
||||||
|
|
||||||
if(res == FKO_SUCCESS)
|
|
||||||
{
|
|
||||||
|
|
||||||
fprintf(stderr, "Decode res = %i\n", res);
|
|
||||||
display_ctx(ctx);
|
|
||||||
|
|
||||||
fko_destroy(ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error creating fko context: %s\n", fko_errstr(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset the packet data length to 0.
|
/* Reset the packet data length to 0.
|
||||||
*/
|
*/
|
||||||
spa_pkt->packet_data_len = 0;
|
spa_pkt->packet_data_len = 0;
|
||||||
|
|
||||||
return(0);
|
if(res != FKO_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error creating fko context: %s\n", fko_errstr(res));
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Decode res = %i\n", res);
|
||||||
|
|
||||||
|
|
||||||
|
display_ctx(ctx);
|
||||||
|
|
||||||
|
res = replay_check(opts, ctx);
|
||||||
|
|
||||||
|
fko_destroy(ctx);
|
||||||
|
|
||||||
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***EOF***/
|
/***EOF***/
|
||||||
|
|||||||
156
server/replay_dbm.c
Normal file
156
server/replay_dbm.c
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
*****************************************************************************
|
||||||
|
*
|
||||||
|
* File: replay_dbm.c
|
||||||
|
*
|
||||||
|
* Author: Damien S. Stuart
|
||||||
|
*
|
||||||
|
* Purpose: Provides the functions to check for possible replay attacks
|
||||||
|
* by using a dbm (ndbm or gdbm in ndbm compatibility mode) file
|
||||||
|
* to store a digest of previously received SPA packets.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Damien Stuart (dstuart@dstuart.org)
|
||||||
|
*
|
||||||
|
* License (GNU Public License):
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
*/
|
||||||
|
#include "replay_dbm.h"
|
||||||
|
#include "log_msg.h"
|
||||||
|
|
||||||
|
#if HAVE_LIBGDBM
|
||||||
|
/* NOTE: We are using gdbm in ndbm compatibility mode so we grab its
|
||||||
|
* version of ndbm.h
|
||||||
|
*/
|
||||||
|
// #include <gdbm.h>
|
||||||
|
#include <gdbm/ndbm.h>
|
||||||
|
#elif HAVE_LIBNDBM
|
||||||
|
#include <ndbm.h>
|
||||||
|
#else
|
||||||
|
#error "No DBM header file found. WTF?"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define MAX_DIGEST_SIZE 64
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
DBM *rpdb;
|
||||||
|
datum db_ent;
|
||||||
|
|
||||||
|
int db_count = 0;
|
||||||
|
|
||||||
|
rpdb = dbm_open(opts->config[CONF_DIGEST_FILE], O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
|
||||||
|
|
||||||
|
if(!rpdb)
|
||||||
|
{
|
||||||
|
perror("Unable to create digest cache file: ");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (db_ent = dbm_firstkey(rpdb); db_ent.dptr != NULL; db_ent = dbm_nextkey(rpdb))
|
||||||
|
db_count++;
|
||||||
|
|
||||||
|
dbm_close(rpdb);
|
||||||
|
|
||||||
|
return(db_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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),
|
||||||
|
* 0 for no match, and -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
replay_check(fko_srv_options_t *opts, fko_ctx_t ctx)
|
||||||
|
{
|
||||||
|
DBM *rpdb;
|
||||||
|
datum db_key, db_ent;
|
||||||
|
|
||||||
|
char ipaddr[INET_ADDRSTRLEN+1] = {0};
|
||||||
|
|
||||||
|
char *digest;
|
||||||
|
int digest_len, res;
|
||||||
|
|
||||||
|
res = fko_get_spa_digest(ctx, &digest);
|
||||||
|
if(res != FKO_SUCCESS)
|
||||||
|
{
|
||||||
|
log_msg(LOG_WARNING|LOG_STDERR, "Error getting digest from SPA data: %s",
|
||||||
|
fko_errstr(res));
|
||||||
|
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
digest_len = strlen(digest);
|
||||||
|
|
||||||
|
db_key.dptr = digest;
|
||||||
|
db_key.dsize = digest_len;
|
||||||
|
|
||||||
|
/* Check the db for the key
|
||||||
|
*/
|
||||||
|
rpdb = dbm_open(opts->config[CONF_DIGEST_FILE], O_RDWR, 0);
|
||||||
|
|
||||||
|
if(!rpdb)
|
||||||
|
{
|
||||||
|
log_msg(LOG_WARNING|LOG_STDERR, "Error opening digest_cache: %s",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
db_ent = dbm_fetch(rpdb, db_key);
|
||||||
|
|
||||||
|
/* If the datum is not null, we have a match. Otherwise, we add
|
||||||
|
* this entry to the cache.
|
||||||
|
*/
|
||||||
|
if(db_ent.dptr != NULL)
|
||||||
|
{
|
||||||
|
/* Convert the IP to a human readable form
|
||||||
|
*/
|
||||||
|
inet_ntop(AF_INET, &(opts->spa_pkt.packet_src_ip),
|
||||||
|
ipaddr, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
log_msg(LOG_WARNING|LOG_STDERR,
|
||||||
|
"Replay detected from source IP: %s", ipaddr);
|
||||||
|
|
||||||
|
res = 1;
|
||||||
|
} else {
|
||||||
|
db_ent.dptr = (char*)&(opts->spa_pkt.packet_src_ip);
|
||||||
|
db_ent.dsize = sizeof(opts->spa_pkt.packet_src_ip);
|
||||||
|
|
||||||
|
if(dbm_store(rpdb, db_key, db_ent, DBM_INSERT) != 0)
|
||||||
|
{
|
||||||
|
log_msg(LOG_WARNING|LOG_STDERR, "Error adding entry digest_cache: %s",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbm_close(rpdb);
|
||||||
|
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***EOF***/
|
||||||
37
server/replay_dbm.h
Normal file
37
server/replay_dbm.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
*****************************************************************************
|
||||||
|
*
|
||||||
|
* File: replay_dbm.h
|
||||||
|
*
|
||||||
|
* Author: Damien Stuart (dstuart@dstuart.org)
|
||||||
|
*
|
||||||
|
* Purpose: Header file for fwknopd replay_dbm.c functions.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Damien Stuart (dstuart@dstuart.org)
|
||||||
|
*
|
||||||
|
* License (GNU Public License):
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
*/
|
||||||
|
#ifndef REPLAY_DBM_H
|
||||||
|
#define REPLAY_DBM_H
|
||||||
|
|
||||||
|
#include "fwknopd_common.h"
|
||||||
|
#include "fko.h"
|
||||||
|
|
||||||
|
/* Prototypes
|
||||||
|
*/
|
||||||
|
int replay_db_init(fko_srv_options_t *opts);
|
||||||
|
int replay_check(fko_srv_options_t *opts, fko_ctx_t ctx);
|
||||||
|
|
||||||
|
#endif /* REPLAY_DBM_H */
|
||||||
Loading…
x
Reference in New Issue
Block a user