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])
|
||||
|
||||
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
|
||||
have_pcap=yes
|
||||
AS_IF([test "$want_server" = yes],
|
||||
AC_CHECK_LIB([pcap],[pcap_open_live],
|
||||
AC_DEFINE([HAVE_LIBPCAP], [1], [Define if you have libpcap]), [have_pcap=no]
|
||||
# Looking for libpcap
|
||||
#
|
||||
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
|
||||
lib/Makefile
|
||||
@ -213,6 +221,5 @@ echo "
|
||||
============================================
|
||||
Client build: $want_client
|
||||
Server build: $want_server
|
||||
- with libpcap: $have_pcap
|
||||
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);
|
||||
|
||||
memmove(tbuf+strlen(B64_RIJNDAEL_SALT), tbuf, b64_len);
|
||||
|
||||
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
|
||||
|
||||
@ -158,12 +158,11 @@ int
|
||||
fko_new_with_data(fko_ctx_t *r_ctx, char *enc_msg, char *dec_key)
|
||||
{
|
||||
fko_ctx_t ctx;
|
||||
int res = FKO_SUCCESS; /* Are we optimistic or what? */
|
||||
|
||||
int res = fko_new(r_ctx);
|
||||
if(res != FKO_SUCCESS)
|
||||
return res;
|
||||
|
||||
ctx = *r_ctx;
|
||||
ctx = calloc(1, sizeof *ctx);
|
||||
if(ctx == NULL)
|
||||
return(FKO_ERROR_MEMORY_ALLOCATION);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
* decode.
|
||||
*/
|
||||
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
|
||||
|
||||
@ -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 \
|
||||
pcap_capture.c pcap_capture.h process_packet.c \
|
||||
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
|
||||
|
||||
if HAVE_LIBPCAP
|
||||
fwknopd_LDADD += -lpcap
|
||||
endif
|
||||
|
||||
fwknopd_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
|
||||
fwknopddir = @sysconfdir@/fwknop
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "log_msg.h"
|
||||
#include "utils.h"
|
||||
#include "sig_handler.h"
|
||||
#include "replay_dbm.h"
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
@ -44,7 +45,7 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
fko_ctx_t ctx;
|
||||
int res, last_sig;
|
||||
int res, last_sig, rpdb_count;
|
||||
char *spa_data, *version;
|
||||
char access_buf[MAX_LINE_LEN];
|
||||
pid_t old_pid;
|
||||
@ -176,12 +177,12 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#ifndef HAVE_LIBPCAP
|
||||
log_msg(LOG_ERR|LOG_STDERR,
|
||||
"libpcap is not avaiable, I'm hosed (for now).");
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
/* Initialize the digest cache (replay attack detection dbm).
|
||||
*/
|
||||
rpdb_count = replay_db_init(&opts);
|
||||
|
||||
fprintf(stderr, "RPDB Count: %i\n", rpdb_count);
|
||||
|
||||
/* Intiate pcap capture mode...
|
||||
*/
|
||||
pcap_capture(&opts);
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
*/
|
||||
#include "fwknopd_common.h"
|
||||
#include "incoming_spa.h"
|
||||
#include "log_msg.h"
|
||||
|
||||
/* The pcap capture routine.
|
||||
*/
|
||||
@ -45,27 +46,35 @@ fprintf(stderr, "SPA Packet: '%s'\n", spa_pkt->packet_data);
|
||||
|
||||
/* 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");
|
||||
|
||||
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.
|
||||
*/
|
||||
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***/
|
||||
|
||||
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