Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
  • Loading branch information...
commit 61c243f827d3b6b68e0111eb931641416cf395d9 1 parent 8a06e36
Damien Stuart authored
View
10 Makefile.am
@@ -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
15 client/Makefile.am
@@ -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
8 doc/Makefile.am
@@ -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
6 doc/libfko.texi
@@ -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
18 server/Makefile.am
@@ -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
90 server/config_init.c
@@ -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
194 server/fwknopd.c
@@ -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(&opts);
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Kill the currently running fwknopd?
+ */
+ if(opts.kill == 1)
+ {
+ //sendsig_fwknopd(&opts, SIGTERM);
+ fprintf(stderr, "Kill option no implemented yet.\n");
+ exit(EXIT_SUCCESS);
+ }
+
+ /* 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)
{
- dump_config(&options);
+ //fwknopd_status(&opts, SIGHUP);
+ fprintf(stderr, "Status option no implemented yet.\n");
exit(EXIT_SUCCESS);
}
- /* TODO: add fwknop server code below :)
+ /* If foreground mode is not set, the fork off and become a daemon.
*/
- printf("\nThis is fwknopd. It would do something if it was coded"
- " to do something:\n\n");
+ 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);
+ }
-#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");
+#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;
-
- 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
+ FILE *pidfile_ptr;
+
+ 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);
+ }
+
+ /* 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);
-
- 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);
+ 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);
+ }
+
+ fclose(pidfile_ptr);
+
+ chmod(pid_file, 0600);
+
+ return;
}
/***EOF***/
View
12 server/fwknopd_common.h
@@ -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.
View
70 server/incoming_spa.c
@@ -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***/
View
34 server/incoming_spa.h
@@ -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 */
View
67 server/log_msg.c
@@ -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***/
View
45 server/log_msg.h
@@ -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***/
View
168 server/pcap_capture.c
@@ -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***/
View
33 server/pcap_capture.h
@@ -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 */
View
182 server/process_packet.c
@@ -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***/
View
36 server/process_packet.h
@@ -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
54 server/utils.c
@@ -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
3  server/utils.h
@@ -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
Please sign in to comment.
Something went wrong with that request. Please try again.