Added some more (stubbed-in) server code and functions. Minor doc tweak.

git-svn-id: file:///home/mbr/svn/fwknop/trunk@148 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart
2009-09-14 00:38:31 +00:00
parent 8a06e36338
commit 61c243f827
18 changed files with 905 additions and 134 deletions

View File

@@ -7,11 +7,11 @@ if WANT_SERVER
endif
SUBDIRS = \
lib \
common \
$(CLIENT_DIR) \
$(SERVER_DIR) \
doc
lib \
common \
$(CLIENT_DIR) \
$(SERVER_DIR) \
doc
EXTRA_DIST = \
perl/legacy \

View File

@@ -1,10 +1,11 @@
bin_PROGRAMS = fwknop
bin_PROGRAMS = fwknop
fwknop_SOURCES = fwknop.c fwknop.h config_init.c config_init.h \
fwknop_common.h spa_comm.c spa_comm.h utils.c utils.h \
http_resolve_host.c getpasswd.c getpasswd.h
fwknop_SOURCES = fwknop.c fwknop.h config_init.c config_init.h \
fwknop_common.h spa_comm.c spa_comm.h utils.c utils.h \
http_resolve_host.c getpasswd.c getpasswd.h
fwknop_LDADD = $(top_builddir)/lib/libfko.la
fwknop_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common
fwknop_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common
dist_man_MANS = fwknop.8
fwknop_LDADD = $(top_builddir)/lib/libfko.la
dist_man_MANS = fwknop.8

View File

@@ -1,6 +1,6 @@
CLEANFILES = libfko.info
CLEANFILES = libfko.info
info_TEXINFOS = libfko.texi
libfko_TEXINFOS = gpl-2.0.texi
info_TEXINFOS = libfko.texi
libfko_TEXINFOS = gpl-2.0.texi
EXTRA_DIST = fwknop.man.asciidoc
EXTRA_DIST = fwknop.man.asciidoc

View File

@@ -708,7 +708,7 @@ main(int argc, char **argv)
rc = fko_new(&ctx);
if(rc != FKO_SUCCESS)
@{
fprintf(stderr, "Error creating context: %s\n", fko_errstr());
fprintf(stderr, "Error creating context: %s\n", fko_errstr(rc));
exit(1);
@}
@@ -716,7 +716,7 @@ main(int argc, char **argv)
rc = fko_set_spa_message(ctx, "0.0.0.0,tcp/22");
if(rc != FKO_SUCCESS)
@{
fprintf(stderr, "Set SPA message failed: %s\n", fko_errstr());
fprintf(stderr, "Set SPA message failed: %s\n", fko_errstr(rc));
exit(1);
@}
@@ -736,7 +736,7 @@ main(int argc, char **argv)
rc = fko_spa_data_final(ctx);
if(rc != FKO_SUCCESS)
@{
fprintf(stderr, "Error encoding SPA data: %s\n", fko_errstr());
fprintf(stderr, "Error encoding SPA data: %s\n", fko_errstr(rc));
exit(1);
@}

View File

@@ -1,16 +1,18 @@
sbin_PROGRAMS = fwknopd
sbin_PROGRAMS = fwknopd
fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
fwknopd_common.h utils.c utils.h
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
fwknopd_LDADD = $(top_builddir)/lib/libfko.la
fwknopd_LDADD = $(top_builddir)/lib/libfko.la
if HAVE_LIBPCAP
fwknopd_LDADD += -lpcap
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
dist_fwknopd_DATA = fwknopd.conf
fwknopddir = @sysconfdir@/fwknop
dist_fwknopd_DATA = fwknopd.conf

View File

@@ -91,7 +91,7 @@ config_entry_index(fko_srv_options_t *opts, char *var)
/* Parse the config file...
*/
static void
parse_config_file(fko_srv_options_t *options, char *config_file)
parse_config_file(fko_srv_options_t *opts, char *config_file)
{
FILE *cfile_ptr;
unsigned int numLines = 0;
@@ -166,15 +166,15 @@ parse_config_file(fko_srv_options_t *options, char *config_file)
{
if(sscanf((val+1), "%[A-Z_]%s", tmp1, tmp2))
{
if((cndx = config_entry_index(options, tmp1)) >= 0)
if((cndx = config_entry_index(opts, tmp1)) >= 0)
{
strlcpy(val, options->config[cndx], MAX_LINE_LEN);
strlcpy(val, opts->config[cndx], MAX_LINE_LEN);
strlcat(val, tmp2, MAX_LINE_LEN);
}
}
}
set_config_entry(options, i, val);
set_config_entry(opts, i, val);
good_ent++;
break;
}
@@ -195,9 +195,28 @@ parse_config_file(fko_srv_options_t *options, char *config_file)
/* Sanity and bounds checks for the various options.
*/
static void
validate_options(fko_srv_options_t *options)
validate_options(fko_srv_options_t *opts)
{
/*** TODO: put stuff here ***/
/* Some options just trigger some output of information, or trigger an
* external function, but do not actually start fwknopd. If any of those
* are set, we can return here an skip the validation routines as all
* other options will be ignored anyway.
*
* These are also mutually exclusive (for now).
*/
if((opts->dump_config + opts->kill + opts->restart + opts->status) == 1)
return;
if((opts->dump_config + opts->kill + opts->restart + opts->status) > 1)
{
fprintf(stderr,
"The -D, -K, -R, and -S options are mutually exclusive. Pick only one.\n"
);
exit(EXIT_FAILURE);
}
/* TODO: Add more validation and sanity checks... --DSS */
return;
}
@@ -206,7 +225,7 @@ validate_options(fko_srv_options_t *options)
* switches.
*/
void
config_init(fko_srv_options_t *options, int argc, char **argv)
config_init(fko_srv_options_t *opts, int argc, char **argv)
{
int cmd_arg, index;
unsigned char got_conf_file = 0, got_override_config = 0;
@@ -216,7 +235,7 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
/* Zero out options and opts_track.
*/
memset(options, 0x00, sizeof(fko_srv_options_t));
memset(opts, 0x00, sizeof(fko_srv_options_t));
/* First, scan the command-line args for an alternate configuration
* file. If we find it, use it, otherwise use the default.
@@ -229,7 +248,7 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
*/
if(cmd_arg == 'c')
{
set_config_entry(options, CONF_CONFIG_FILE, optarg);
set_config_entry(opts, CONF_CONFIG_FILE, optarg);
got_conf_file++;
/* If we already have the config_override option, we are done.
@@ -242,7 +261,7 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
*/
if(cmd_arg == 'O')
{
set_config_entry(options, CONF_OVERRIDE_CONFIG, optarg);
set_config_entry(opts, CONF_OVERRIDE_CONFIG, optarg);
got_conf_file++;
/* If we already have the conf_file option, we are done.
@@ -255,22 +274,22 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
/* If no alternate configuration file was specified, we use the
* default.
*/
if(options->config[CONF_CONFIG_FILE] == NULL)
set_config_entry(options, CONF_CONFIG_FILE, DEF_CONFIG_FILE);
if(opts->config[CONF_CONFIG_FILE] == NULL)
set_config_entry(opts, CONF_CONFIG_FILE, DEF_CONFIG_FILE);
/* Parse configuration file to populate any params not already specified
* via command-line options.
*/
parse_config_file(options, options->config[CONF_CONFIG_FILE]);
parse_config_file(opts, opts->config[CONF_CONFIG_FILE]);
/* If there are override configuration entries, process them
* here.
*/
if(options->config[CONF_OVERRIDE_CONFIG] != NULL)
if(opts->config[CONF_OVERRIDE_CONFIG] != NULL)
{
/* Make a copy of the overrid_config string so we can munge it.
*/
strlcpy(override_file, options->config[CONF_OVERRIDE_CONFIG], MAX_LINE_LEN);
strlcpy(override_file, opts->config[CONF_OVERRIDE_CONFIG], MAX_LINE_LEN);
ndx = override_file;
cmrk = strchr(ndx, ',');
@@ -279,7 +298,7 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
{
/* Only one to process...
*/
parse_config_file(options, ndx);
parse_config_file(opts, ndx);
} else {
/* Walk the string pulling the next config override
@@ -287,14 +306,14 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
*/
while(cmrk != NULL) {
*cmrk = '\0';
parse_config_file(options, ndx);
parse_config_file(opts, ndx);
ndx = cmrk + 1;
cmrk = strchr(ndx, ',');
}
/* Process the last entry
*/
parse_config_file(options, ndx);
parse_config_file(opts, ndx);
}
}
@@ -313,7 +332,10 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
/* This was handled earlier */
break;
case 'D':
options->dump_config = 1;
opts->dump_config = 1;
break;
case 'f':
opts->foreground = 1;
break;
case FIREWALL_LIST:
fprintf(stderr, "*NOT IMPLEMENTED YET*\n");
@@ -328,44 +350,35 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
exit(EXIT_SUCCESS);
break;
case FIREWALL_LOG:
set_config_entry(options, CONF_FIREWALL_LOG, optarg);
set_config_entry(opts, CONF_FIREWALL_LOG, optarg);
break;
case GPG_HOME_DIR:
set_config_entry(options, CONF_GPG_HOME_DIR, optarg);
set_config_entry(opts, CONF_GPG_HOME_DIR, optarg);
break;
case GPG_KEY:
set_config_entry(options, CONF_GPG_KEY, optarg);
set_config_entry(opts, CONF_GPG_KEY, optarg);
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
break;
case 'i':
set_config_entry(options, CONF_PCAP_INTF, optarg);
set_config_entry(opts, CONF_PCAP_INTF, optarg);
break;
case 'K':
fprintf(stderr, "*NOT IMPLEMENTED YET*\n");
// TODO: Add this...
//kill_fwknopd();
exit(EXIT_SUCCESS);
opts->kill = 1;
break;
case 'O':
/* This was handled earlier */
break;
case 'R':
fprintf(stderr, "*NOT IMPLEMENTED YET*\n");
// TODO: Add this...
//restart_fwknopd();
exit(EXIT_SUCCESS);
opts->restart = 1;
break;
case 'S':
fprintf(stderr, "*NOT IMPLEMENTED YET*\n");
// TODO: Add this...
//fwkop_status();
exit(EXIT_SUCCESS);
opts->status = 1;
break;
case 'v':
options->verbose = 1;
opts->verbose = 1;
break;
case 'V':
fprintf(stdout, "fwknopd server %s\n", MY_VERSION);
@@ -377,9 +390,10 @@ config_init(fko_srv_options_t *options, int argc, char **argv)
}
}
/* Now that we have all of our options set, we can validate them.
/* Now that we have all of our options set, and we are actually going to
* start fwknopd, we can validate them.
*/
validate_options(options);
validate_options(opts);
return;
}

View File

@@ -25,12 +25,15 @@
*/
#include "fwknopd.h"
#include "config_init.h"
#include "process_packet.h"
#include "pcap_capture.h"
#include "log_msg.h"
#include "utils.h"
/* prototypes
/* Prototypes
*/
static void display_ctx(fko_ctx_t ctx);
void errmsg(char *msg, int err);
void daemonize_process(const char *pid_file);
void write_pid(const char *pid_file, const pid_t pid);
int
main(int argc, char **argv)
@@ -40,92 +43,149 @@ main(int argc, char **argv)
char *spa_data, *version;
char access_buf[MAX_LINE_LEN];
fko_srv_options_t options;
fko_srv_options_t opts;
/* Handle command line
*/
config_init(&options, argc, argv);
config_init(&opts, argc, argv);
/* Process any options that do their thing and exit. */
/* Show config and exit dump config was wanted.
*/
if(options.dump_config == 1)
if(opts.dump_config == 1)
{
dump_config(&options);
dump_config(&opts);
exit(EXIT_SUCCESS);
}
/* TODO: add fwknop server code below :)
/* Kill the currently running fwknopd?
*/
printf("\nThis is fwknopd. It would do something if it was coded"
" to do something:\n\n");
if(opts.kill == 1)
{
//sendsig_fwknopd(&opts, SIGTERM);
fprintf(stderr, "Kill option no implemented yet.\n");
exit(EXIT_SUCCESS);
}
#if HAVE_LIBPCAP
printf(" - fwknopd would be using libpcap version %s\n\n", pcap_lib_version());
#else
printf(" - fwknopd is not using libpcap\n\n");
/* Restart the currently running fwknopd?
*/
if(opts.restart == 1)
{
//sendsig_fwknopd(&opts, SIGHUP);
fprintf(stderr, "Restart option no implemented yet.\n");
exit(EXIT_SUCCESS);
}
/* Status of the currently running fwknopd?
*/
if(opts.status == 1)
{
//fwknopd_status(&opts, SIGHUP);
fprintf(stderr, "Status option no implemented yet.\n");
exit(EXIT_SUCCESS);
}
/* If foreground mode is not set, the fork off and become a daemon.
*/
if(opts.foreground == 0)
daemonize_process(opts.config[CONF_FWKNOP_PID_FILE]);
log_msg(LOG_INFO, "Starting %s", MY_NAME);
if((strncasecmp(opts.config[CONF_AUTH_MODE], "pcap", 4)) != 0)
{
log_msg(LOG_ERR|LOG_STDERR,
"Capture/auth mode other than 'PCAP' is not supported."
);
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
/* Intiate pcap capture mode...
*/
pcap_capture(&opts);
return(0);
}
/* Display an FKO error message.
/* Become a daemon: fork(), start a new session, chdir "/",
* and close unneeded standard filehandles.
*/
void
errmsg(char *msg, int err) {
fprintf(stderr, "[*] %s: %s: Error %i - %s\n",
MY_NAME, msg, err, fko_errstr(err));
void daemonize_process(const char *pid_file)
{
pid_t child_pid, sid;
if ((child_pid = fork()) < 0) {
perror("Unable to fork: ");
exit(EXIT_FAILURE);
}
/* The parent will write the child PID to the pid_file
* then exit.
*/
if (child_pid > 0) {
write_pid(pid_file, child_pid);
exit(EXIT_SUCCESS);
}
/* Child process from here on out */
/* Start a new session
*/
if ((sid = setsid()) < 0) {
perror("Error from setsid(): ");
exit(EXIT_FAILURE);
}
/* Chdir to "/"
*/
if ((chdir("/")) < 0) {
perror("Could not chdir() to /: ");
exit(EXIT_FAILURE);
}
/* Reset the our umask
*/
umask(0);
/* Close un-needed file handles
*/
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
return;
}
/* Show the fields of the FKO context.
*/
static void
display_ctx(fko_ctx_t ctx)
void write_pid(const char *pid_file, const pid_t pid)
{
char *rand_val = NULL;
char *username = NULL;
char *version = NULL;
char *spa_message = NULL;
char *nat_access = NULL;
char *server_auth = NULL;
char *enc_data = NULL;
char *spa_digest = NULL;
char *spa_data = NULL;
FILE *pidfile_ptr;
time_t timestamp = 0;
short msg_type = -1;
short digest_type = -1;
int client_timeout = -1;
if ((pidfile_ptr = fopen(pid_file, "w")) == NULL) {
fprintf(stderr, "Could not open the pid file: %s: %s",
pid_file, strerror(errno));
exit(EXIT_FAILURE);
}
/* Should be checking return values, but this is temp code. --DSS
/* Write the pid to the pid file
*/
fko_get_rand_value(ctx, &rand_val);
fko_get_username(ctx, &username);
fko_get_timestamp(ctx, &timestamp);
fko_get_version(ctx, &version);
fko_get_spa_message_type(ctx, &msg_type);
fko_get_spa_message(ctx, &spa_message);
fko_get_spa_nat_access(ctx, &nat_access);
fko_get_spa_server_auth(ctx, &server_auth);
fko_get_spa_client_timeout(ctx, &client_timeout);
fko_get_spa_digest_type(ctx, &digest_type);
fko_get_encoded_data(ctx, &enc_data);
fko_get_spa_digest(ctx, &spa_digest);
fko_get_spa_data(ctx, &spa_data);
if (fprintf(pidfile_ptr, "%d\n", pid) == 0) {
fprintf(stderr, "PID: %d could not be written to pid file: %s: %s",
pid, pid_file, strerror(errno));
exit(EXIT_FAILURE);
}
printf("\nFKO Field Values:\n=================\n\n");
printf(" Random Value: %s\n", rand_val == NULL ? "<NULL>" : rand_val);
printf(" Username: %s\n", username == NULL ? "<NULL>" : username);
printf(" Timestamp: %u\n", (unsigned int) timestamp);
printf(" FKO Version: %s\n", version == NULL ? "<NULL>" : version);
printf(" Message Type: %i\n", msg_type);
printf(" Message String: %s\n", spa_message == NULL ? "<NULL>" : spa_message);
printf(" Nat Access: %s\n", nat_access == NULL ? "<NULL>" : nat_access);
printf(" Server Auth: %s\n", server_auth == NULL ? "<NULL>" : server_auth);
printf(" Client Timeout: %u\n", client_timeout);
printf(" Digest Type: %u\n", digest_type);
printf("\n Encoded Data: %s\n", enc_data == NULL ? "<NULL>" : enc_data);
printf("\nSPA Data Digest: %s\n", spa_digest == NULL ? "<NULL>" : spa_digest);
printf("\nFinal Packed/Encrypted/Encoded Data:\n\n%s\n\n", spa_data);
fclose(pidfile_ptr);
chmod(pid_file, 0600);
return;
}
/***EOF***/

View File

@@ -53,6 +53,7 @@
*/
#define MAX_PCAP_FILTER_LEN 1024
#define MAX_IFNAME_LEN 128
#define MAX_SPA_PACKET_LEN 1500 /* --DSS check this? */
/* Data collection modes
*/
@@ -236,9 +237,16 @@ typedef struct fko_srv_options
*/
unsigned char dump_config; /* Dump current configuration flag */
unsigned char foreground; /* Run in foreground flag */
unsigned char restart; /* Restart fwknopd flag*/
unsigned char verbose; /* Verbose mode flag */
unsigned char kill; /* flag to initiate kill of fwknopd */
unsigned char restart; /* Restart fwknopd flag */
unsigned char status; /* Get fwknopd status flag */
unsigned char test; /* Test mode flag */
unsigned char verbose; /* Verbose mode flag */
int data_link_offset;
unsigned int packet_data_len; /* Is > 0 if we have data */
unsigned char packet_data[MAX_SPA_PACKET_LEN+1];
/* This array holds all of the config file entry values as strings
* indexed by their tag name.

70
server/incoming_spa.c Normal file
View File

@@ -0,0 +1,70 @@
/* $Id$
*****************************************************************************
*
* File: incoming_spa.c
*
* Author: Damien S. Stuart
*
* Purpose: The pcap capture routines for fwknopd.
*
* 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 "fwknopd_common.h"
#include "incoming_spa.h"
/* The pcap capture routine.
*/
int
incoming_spa(fko_srv_options_t *opts)
{
fko_ctx_t ctx;
int res;
/* Sanity check
*/
if(opts->packet_data_len <= 0)
return;
/* Reset the packet data length to 0.
*/
opts->packet_data_len = 0;
fprintf(stderr, "SPA Packet: '%s'\n", opts->packet_data);
/* Get the decryption key
*/
res = fko_new_with_data(&ctx, opts->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));
}
return(0);
}
/***EOF***/

34
server/incoming_spa.h Normal file
View File

@@ -0,0 +1,34 @@
/*
*****************************************************************************
*
* File: incoming_spa.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for incoming_spa.c.
*
* 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 INCOMING_SPA_H
#define INCOMING_SPA_H
/* Prototypes
*/
int incoming_spa(fko_srv_options_t *opts);
#endif /* INCOMING_SPA_H */

67
server/log_msg.c Normal file
View File

@@ -0,0 +1,67 @@
/*
*****************************************************************************
*
* File: log_msg.c
*
* Author: Damien S. Stuart
*
* Purpose: General logging routine that can write to syslog and/or stderr
* and can take varibale number of args.
*
* 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 "fwknopd_common.h"
#include "log_msg.h"
void log_msg(int level, char* msg, ...)
{
va_list ap, apse;
va_start(ap, msg);
/* Print msg to stderr if the level was or'ed with LOG_STDERR
*/
if(LOG_STDERR & level)
{
/* Need to make a copy of our va_list so we don't screw
* up the message going to syslog after we print it to stderr.
*/
va_copy(apse, ap);
vfprintf(stderr, msg, apse);
fprintf(stderr, "\n");
va_end(apse);
if(LOG_STDERR_ONLY & level)
return;
/* Remove the log to stderr flag from the log level value.
*/
level &= LOG_STDERR_MASK;
}
/* Send the message to syslog.
*/
openlog(MY_NAME, LOG_PID, LOG_DAEMON);
vsyslog(level, msg, ap);
va_end(ap);
}
/***EOF***/

45
server/log_msg.h Normal file
View File

@@ -0,0 +1,45 @@
/*
*****************************************************************************
*
* File: log_msg.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for pcap_capture.c.
*
* 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 LOG_MSG_H
#define LOG_MSG_H
#include <syslog.h>
#include <stdarg.h>
/* The LOG_STDERR value can be or'ed with the msg_log() level value
* to cause message going to syslog to be printed to stderr as well.
* LOG_STDERR_ONLY can be set to send a message stderr with a copy to
* syslog as well.
*/
#define LOG_STDERR 0x1000
#define LOG_STDERR_ONLY 0x3000
#define LOG_STDERR_MASK 0x0FFF
void log_msg(int, char*, ...);
#endif /* LOG_MSG_H */
/***EOF***/

168
server/pcap_capture.c Normal file
View File

@@ -0,0 +1,168 @@
/* $Id$
*****************************************************************************
*
* File: pcap_capture.c
*
* Author: Damien S. Stuart
*
* Purpose: The pcap capture routines for fwknopd.
*
* 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 <pcap.h>
#include "fwknopd_common.h"
#include "pcap_capture.h"
#include "process_packet.h"
#include "incoming_spa.h"
/* The pcap capture routine.
*/
int
pcap_capture(fko_srv_options_t *opts)
{
#if HAVE_LIBPCAP
pcap_t *pcap;
char errstr[PCAP_ERRBUF_SIZE] = {0};
struct bpf_program fp;
int res, pcap_errcnt = 0;;
pcap = pcap_open_live(
opts->config[CONF_PCAP_INTF],
atoi(opts->config[CONF_MAX_SNIFF_BYTES]),
1, 500, errstr
);
if(pcap == NULL)
{
fprintf(stderr, "* pcap_open_live error: %s\n", errstr);
exit(EXIT_FAILURE);
}
/* We are only interested on seeing packets coming into the interface.
*/
if (pcap_setdirection(pcap, PCAP_D_IN) < 0)
fprintf(stderr, "* Warning: pcap error on setdirection\n");
if (pcap == NULL)
{
fprintf(stderr, "[*] pcap error: %s\n", errstr);
exit(EXIT_FAILURE);
}
/* Set pcap filters, if any.
*/
if (opts->config[CONF_PCAP_FILTER][0] != '\0')
{
if(pcap_compile(pcap, &fp, opts->config[CONF_PCAP_FILTER], 1, 0) == -1)
{
fprintf(stderr, "[*] Error compiling pcap filter: %s\n",
pcap_geterr(pcap)
);
exit(EXIT_FAILURE);
}
if(pcap_setfilter(pcap, &fp) == -1)
{
fprintf(stderr, "[*] Error setting pcap filter: %s\n",
pcap_geterr(pcap)
);
exit(EXIT_FAILURE);
}
pcap_freecode(&fp);
}
/* Determine and set the data link encapsulation offset.
*/
switch(pcap_datalink(pcap)) {
case DLT_EN10MB:
opts->data_link_offset = 14;
break;
case DLT_NULL:
opts->data_link_offset = 4;
break;
default:
opts->data_link_offset = 0;
break;
}
/* Set our pcap handle to nonblocking mode.
*/
if((pcap_setnonblock(pcap, 1, errstr)) == -1)
{
fprintf(stderr, "[*] Error setting pcap to non-blocking: %s\n",
errstr
);
exit(EXIT_FAILURE);
}
/* Jump into our home-grown packet cature loop.
*/
while(1)
{
res = pcap_dispatch(pcap, 1, (pcap_handler)&process_packet, (unsigned char *)opts);
/* If there was a packet and it was processed without error, then
* keep going.
*/
if(res > 0 && opts->packet_data_len > 0)
{
incoming_spa(opts);
pcap_errcnt = 0;
continue;
}
/* If there was an error, complain and go on (to an extent
* before giving up).
*/
else if(res == -1)
{
fprintf(stderr, "[*] Error from pcap_dispatch: %s\n",
pcap_geterr(pcap)
);
if(pcap_errcnt++ > 100) /* --DSS XXX: Shoudl do this better */
{
fprintf(stderr, "[*] %i consecutive pcap errors. Giving up\n",
pcap_errcnt
);
exit(EXIT_FAILURE);
}
}
else if(res == -2)
{
/* pcap_break_loop was called, so we bail. */
break;
}
else
pcap_errcnt = 0;
/* Check for any expired firewall rules and deal with them.
*/
//--DSS TODO: still need to write this part...
//check_firewall_rules(opts);
usleep(10000);
}
#endif /* HAVE_LIBPCAP */
return(0);
}
/***EOF***/

33
server/pcap_capture.h Normal file
View File

@@ -0,0 +1,33 @@
/*
*****************************************************************************
*
* File: pcap_capture.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for pcap_capture.c.
*
* 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 PCAP_CAPTURE_H
#define PCAP_CAPTURE_H
/* Prototypes
*/
int pcap_capture(fko_srv_options_t *opts);
#endif /* PCAP_CAPTURE_H */

182
server/process_packet.c Normal file
View File

@@ -0,0 +1,182 @@
/*
*****************************************************************************
*
* File: process_packet.c
*
* Author: Damien S. Stuart
*
* Purpose: Packet parser/decoder for fwknopd server. Takes the raw packet
* data from libpcap and parses/extracts the packet data payload,
* then creates an FKO context with that data. If the context
* creation is successfull, it is queued for processing.
*
* 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 <pcap.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include "fwknopd_common.h"
#include "process_packet.h"
void
process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header,
const unsigned char *packet)
{
struct ether_header *eth_p;
struct iphdr *iph_p;
struct tcphdr *tcph_p;
struct udphdr *udph_p;
unsigned char *pkt_data;
unsigned short pkt_data_len;
unsigned char *pkt_end;
unsigned int pke_data_len;
unsigned int ip_hdr_words;
unsigned int src_ip;
unsigned int dest_ip;
unsigned short src_port;
unsigned short dest_port;
unsigned short eth_type;
fko_srv_options_t *opts = (fko_srv_options_t *)args;
int offset = opts->data_link_offset;
unsigned short pkt_len = packet_header->len;
/* Determine packet end.
*/
pkt_end = (unsigned char *) packet + packet_header->caplen;
/* The ethernet header.
*/
eth_p = (struct ether_header*) packet;
/* Gotta have a complete ethernet header.
*/
if (packet_header->caplen < ETHER_HDR_LEN)
return;
eth_type = ntohs(*((unsigned short*)&eth_p->ether_type));
if(eth_type == 0x8100) /* 802.1q encapsulated */
{
offset += 4;
eth_type = ntohs(*(((unsigned short*)&eth_p->ether_type)+2));
}
/* When using libpcap, pkthdr->len for 802.3 frames include CRC_LEN,
* but Ethenet_II frames do not.
*/
if (eth_type > 1500)
{
pkt_len += ETHER_CRC_LEN;
if(eth_type == 0xAAAA) /* 802.2 SNAP */
offset += 5;
}
else /* 802.3 Frame */
offset += 3;
/* Make sure the packet length is still valid.
*/
if (! ETHER_IS_VALID_LEN(pkt_len) )
return;
/* Pull the IP header.
*/
iph_p = (struct iphdr*)(packet + offset);
/* If IP header is past calculated packet end, bail.
*/
if ((unsigned char*)(iph_p + 1) > pkt_end)
return;
/* ip_hdr_words is the number of 32 bit words in the IP header. After
* masking of the IPV4 version bits, the number *must* be at least
* 5, even without options.
*/
ip_hdr_words = iph_p->ihl & IPV4_VER_MASK;
if (ip_hdr_words < MIN_IPV4_WORDS)
return;
/* Now, find the packet data payload (depending on IPPROTO).
*/
src_ip = iph_p->saddr;
dest_ip = iph_p->daddr;
if (iph_p->protocol == IPPROTO_TCP)
{
/* Process TCP packet
*/
tcph_p = (struct tcphdr*)((unsigned char*)iph_p + (ip_hdr_words << 2));
src_port = ntohs(tcph_p->source);
dest_port = ntohs(tcph_p->dest);
pkt_data = ((unsigned char*)(tcph_p+1))+((tcph_p->doff)<<2)-sizeof(struct tcphdr);
pkt_data_len = (pkt_end-(unsigned char*)iph_p)-(pkt_data-(unsigned char*)iph_p);
}
else if (iph_p->protocol == IPPROTO_UDP)
{
/* Process UDP packet
*/
udph_p = (struct udphdr*)((unsigned char*)iph_p + (ip_hdr_words << 2));
src_port = ntohs(udph_p->source);
dest_port = ntohs(udph_p->dest);
pkt_data = ((unsigned char*)(udph_p + 1));
pkt_data_len = (pkt_end-(unsigned char*)iph_p)-(pkt_data-(unsigned char*)iph_p);
}
else
return;
/*
* Now we have data. For now we are not checking IP or port values. We
* are relying on the pcap filter. This may change so we do retain the IP
* addresses and ports just in case. We just go ahead and queue the
* data.
*/
/* Truncate the data if it is too long. This most likely means it is not
* a valid SPA packet anyway.
*/
if(pkt_data_len > MAX_SPA_PACKET_LEN)
pkt_data_len = MAX_SPA_PACKET_LEN;
/* Put the data in our 1-entry queue.
*/
memcpy(opts->packet_data, pkt_data, pkt_data_len);
opts->packet_data_len = pkt_data_len;
return;
}
/***EOF***/

36
server/process_packet.h Normal file
View File

@@ -0,0 +1,36 @@
/*
*****************************************************************************
*
* File: process_packet.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for process_packet and other fwknopd code.
*
* 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 PROCESS_PACKET_H
#define PROCESS_PACKET_H
#define IPV4_VER_MASK 0x15
#define MIN_IPV4_WORDS 0x05
/* Prototypes
*/
void process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header, const unsigned char *packet);
#endif /* PROCESS_PACKET_H */

View File

@@ -23,8 +23,7 @@
*
*****************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include "fwknopd_common.h"
#include "utils.h"
/* Generic hex dump function.
@@ -64,5 +63,56 @@ hex_dump(unsigned char *data, int size)
}
}
/* Show the fields of the FKO context.
*/
void
display_ctx(fko_ctx_t ctx)
{
char *rand_val = NULL;
char *username = NULL;
char *version = NULL;
char *spa_message = NULL;
char *nat_access = NULL;
char *server_auth = NULL;
char *enc_data = NULL;
char *spa_digest = NULL;
char *spa_data = NULL;
time_t timestamp = 0;
short msg_type = -1;
short digest_type = -1;
int client_timeout = -1;
/* Should be checking return values, but this is temp code. --DSS
*/
fko_get_rand_value(ctx, &rand_val);
fko_get_username(ctx, &username);
fko_get_timestamp(ctx, &timestamp);
fko_get_version(ctx, &version);
fko_get_spa_message_type(ctx, &msg_type);
fko_get_spa_message(ctx, &spa_message);
fko_get_spa_nat_access(ctx, &nat_access);
fko_get_spa_server_auth(ctx, &server_auth);
fko_get_spa_client_timeout(ctx, &client_timeout);
fko_get_spa_digest_type(ctx, &digest_type);
fko_get_encoded_data(ctx, &enc_data);
fko_get_spa_digest(ctx, &spa_digest);
fko_get_spa_data(ctx, &spa_data);
printf("\nFKO Field Values:\n=================\n\n");
printf(" Random Value: %s\n", rand_val == NULL ? "<NULL>" : rand_val);
printf(" Username: %s\n", username == NULL ? "<NULL>" : username);
printf(" Timestamp: %u\n", (unsigned int) timestamp);
printf(" FKO Version: %s\n", version == NULL ? "<NULL>" : version);
printf(" Message Type: %i\n", msg_type);
printf(" Message String: %s\n", spa_message == NULL ? "<NULL>" : spa_message);
printf(" Nat Access: %s\n", nat_access == NULL ? "<NULL>" : nat_access);
printf(" Server Auth: %s\n", server_auth == NULL ? "<NULL>" : server_auth);
printf(" Client Timeout: %u\n", client_timeout);
printf(" Digest Type: %u\n", digest_type);
printf("\n Encoded Data: %s\n", enc_data == NULL ? "<NULL>" : enc_data);
printf("\nSPA Data Digest: %s\n", spa_digest == NULL ? "<NULL>" : spa_digest);
printf("\nFinal Packed/Encrypted/Encoded Data:\n\n%s\n\n", spa_data);
}
/***EOF***/

View File

@@ -26,11 +26,12 @@
#ifndef UTILS_H
#define UTILS_H
#include "fko.h"
/* Prototypes
*/
void hex_dump(unsigned char *data, int size);
void display_ctx(fko_ctx_t ctx);
#ifdef WIN32
/* Function prototypes we need for Windows