diff --git a/server/Makefile.am b/server/Makefile.am index c1e94a19..2286c697 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -3,7 +3,8 @@ sbin_PROGRAMS = fwknopd 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 + process_packet.h log_msg.c log_msg.h utils.c utils.h \ + sig_handler.c sig_handler.h fwknopd_LDADD = $(top_builddir)/lib/libfko.la diff --git a/server/config_init.c b/server/config_init.c index 2973f52e..758ed5c3 100644 --- a/server/config_init.c +++ b/server/config_init.c @@ -88,6 +88,18 @@ config_entry_index(fko_srv_options_t *opts, char *var) return(-1); } +/* Free the config memory +*/ +void +free_configs(fko_srv_options_t *opts) +{ + int i; + + for(i=0; iconfig[i] != NULL) + free(opts->config[i]); +} + /* Parse the config file... */ static void @@ -244,13 +256,16 @@ config_init(fko_srv_options_t *opts, int argc, char **argv) memset(opts, 0x00, sizeof(fko_srv_options_t)); /* First, set any default or otherwise static settings here. Some may - * end up being overwritten vail config file or command-line. + * end up being overwritten via config file or command-line. */ /* Default Hostname (or unknown if gethostname cannot tell us). */ if(gethostname(opts->hostname, MAX_HOSTNAME_LEN-1) < 0) strcpy(opts->hostname, "UNKNOWN"); + /* In case this is a re-config. + */ + optind = 0; /* First, scan the command-line args for an alternate configuration * file. If we find it, use it, otherwise use the default. @@ -364,9 +379,6 @@ config_init(fko_srv_options_t *opts, int argc, char **argv) //flush_firewall_rules(); exit(EXIT_SUCCESS); break; - case FIREWALL_LOG: - set_config_entry(opts, CONF_FIREWALL_LOG, optarg); - break; case GPG_HOME_DIR: set_config_entry(opts, CONF_GPG_HOME_DIR, optarg); break; diff --git a/server/config_init.h b/server/config_init.h index 2a25e824..5771f7e4 100644 --- a/server/config_init.h +++ b/server/config_init.h @@ -90,8 +90,9 @@ static struct option cmd_opts[] = /* Function Prototypes */ -void config_init(fko_srv_options_t *options, int argc, char **argv); -void dump_config(fko_srv_options_t *options); +void config_init(fko_srv_options_t *opts, int argc, char **argv); +void dump_config(fko_srv_options_t *opts); +void clear_configs(fko_srv_options_t *opts); void usage(void); #endif /* CONFIG_INIT_H */ diff --git a/server/fwknopd.c b/server/fwknopd.c index fa487fb9..70c88c0a 100644 --- a/server/fwknopd.c +++ b/server/fwknopd.c @@ -32,6 +32,7 @@ #include "pcap_capture.h" #include "log_msg.h" #include "utils.h" +#include "sig_handler.h" /* Prototypes */ @@ -43,119 +44,187 @@ int main(int argc, char **argv) { fko_ctx_t ctx; - int res; + int res, last_sig; char *spa_data, *version; char access_buf[MAX_LINE_LEN]; pid_t old_pid; fko_srv_options_t opts; - /* Handle command line - */ - config_init(&opts, argc, argv); - - /* Process any options that do their thing and exit. */ - - /* Show config and exit dump config was wanted. - */ - if(opts.dump_config == 1) + while(1) { - dump_config(&opts); - exit(EXIT_SUCCESS); - } + /* Handle command line + */ + config_init(&opts, argc, argv); - /* Kill the currently running fwknopd? - */ - if(opts.kill == 1) - { - old_pid = get_running_pid(&opts); + /* Process any options that do their thing and exit. */ - if(old_pid > 0) + /* Show config and exit dump config was wanted. + */ + if(opts.dump_config == 1) { - res = kill(old_pid, SIGTERM); - if(res == 0) + dump_config(&opts); + exit(EXIT_SUCCESS); + } + + /* Kill the currently running fwknopd? + */ + if(opts.kill == 1) + { + old_pid = get_running_pid(&opts); + + if(old_pid > 0) { - fprintf(stderr, "Killed fwknopd (pid=%i)\n", old_pid); - exit(EXIT_SUCCESS); + res = kill(old_pid, SIGTERM); + if(res == 0) + { + fprintf(stderr, "Killed fwknopd (pid=%i)\n", old_pid); + exit(EXIT_SUCCESS); + } + else + { + perror("Unable to kill fwknop: "); + exit(EXIT_FAILURE); + } } else { - perror("Unable to kill fwknop: "); + fprintf(stderr, "No running fwknopd detected.\n", old_pid); exit(EXIT_FAILURE); } } + + /* Restart the currently running fwknopd? + */ + if(opts.restart == 1) + { + old_pid = get_running_pid(&opts); + + if(old_pid > 0) + { + res = kill(old_pid, SIGHUP); + if(res == 0) + { + fprintf(stderr, "Sent restart signal to fwknopd (pid=%i)\n", old_pid); + exit(EXIT_SUCCESS); + } + else + { + perror("Unable to send signal to fwknop: "); + exit(EXIT_FAILURE); + } + } + else + { + fprintf(stderr, "No running fwknopd detected.\n", old_pid); + exit(EXIT_FAILURE); + } + } + + /* Status of the currently running fwknopd? + */ + if(opts.status == 1) + { + fprintf(stderr, "Status option not implemented yet.\n"); + exit(EXIT_SUCCESS); + } + + /* Initialize logging. + */ + init_logging(&opts); + + if(get_running_pid(&opts) != getpid()) + { + /* If foreground mode is not set, the fork off and become a daemon. + * Otherwise, attempt to get the pid fiel lock and go on. + */ + if(opts.foreground == 0) + { + daemonize_process(&opts); + } + else + { + old_pid = write_pid_file(&opts); + if(old_pid > 0) + { + fprintf(stderr, + "* An instance of fwknopd is already running: (PID=%i).\n", old_pid + ); + + exit(EXIT_FAILURE); + } + else if(old_pid < 0) + { + fprintf(stderr, "* PID file error. The lock may not be effective.\n"); + } + } + + log_msg(LOG_INFO, "Starting %s", MY_NAME); + } else { - fprintf(stderr, "No running fwknopd detected.\n", old_pid); - exit(EXIT_FAILURE); + log_msg(LOG_INFO, "Re-starting %s", MY_NAME); } - } - /* Restart the currently running fwknopd? - */ - if(opts.restart == 1) - { - //sendsig_fwknopd(&opts, SIGHUP); - fprintf(stderr, "Restart option not implemented yet.\n"); - exit(EXIT_SUCCESS); - } + dump_config(&opts); - /* Status of the currently running fwknopd? - */ - if(opts.status == 1) - { - //fwknopd_status(&opts, SIGHUP); - fprintf(stderr, "Status option not implemented yet.\n"); - exit(EXIT_SUCCESS); - } - - /* If foreground mode is not set, the fork off and become a daemon. - * Otherwise, attempt to get the pid fiel lock and go on. - */ - if(opts.foreground == 0) - { - daemonize_process(&opts); - } - else - { - old_pid = write_pid_file(&opts); - if(old_pid > 0) + if((strncasecmp(opts.config[CONF_AUTH_MODE], "pcap", 4)) != 0) { - fprintf(stderr, - "* An instance of fwknopd is already running: (PID=%i).\n", old_pid + log_msg(LOG_ERR|LOG_STDERR, + "Capture/auth mode other than 'PCAP' is not supported." ); - exit(EXIT_FAILURE); } - else if(old_pid < 0) - { - fprintf(stderr, "* PID file error. The lock may not be effective.\n"); - } - } - - /* Initialize logging. - */ - init_logging(&opts); - - 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); + log_msg(LOG_ERR|LOG_STDERR, + "libpcap is not avaiable, I'm hosed (for now)."); + exit(EXIT_FAILURE); #endif - /* Intiate pcap capture mode... + /* Intiate pcap capture mode... + */ + pcap_capture(&opts); + + if(last_sig = got_signal) { + got_signal = 0; + if(got_sighup) + { + log_msg(LOG_WARNING|LOG_STDERR, "Got SIGHUP. Re-reading configs."); + free_configs(&opts); + got_sighup = 0; + } + else if(got_sigint) + { + log_msg(LOG_WARNING|LOG_STDERR, "Got SIGINT. Exiting..."); + got_sigint = 0; + break; + } + else if(got_sigterm) + { + log_msg(LOG_WARNING|LOG_STDERR, "Got SIGTERM. Exiting..."); + got_sigterm = 0; + break; + } + else + { + log_msg(LOG_WARNING|LOG_STDERR, + "Got signal %i. No defined action but to exit.", last_sig); + break; + } + } + else /* got_signal was not set (should be if we are here) */ + { + log_msg(LOG_WARNING|LOG_STDERR, + "Capture ended without signal. Exiting..."); + break; + } + } + + /* Other cleanup. */ - pcap_capture(&opts); + free_logging(); + free_configs(&opts); return(0); } diff --git a/server/fwknopd.conf b/server/fwknopd.conf index 97f1fc0a..8b3f2af4 100644 --- a/server/fwknopd.conf +++ b/server/fwknopd.conf @@ -78,19 +78,6 @@ MAX_SPA_PACKET_AGE 120; # ENABLE_DIGEST_PERSISTENCE Y; -# Default to using all of SHA1/256/384/512, and MD5 for SPA replay attack -# detection. This is overkill, but performance is not usually a concern. -# Further, the variable can also be set to "SHA1" or "MD5". -# -DIGEST_TYPE ALL; - -# This variable controls whether fwknopd includes the source IP of each SPA -# packet in the DIGEST store. If a replayed SPA message is detected, then -# having this information can provide information about which networks have -# people sniffing your SPA packets. -# -ENABLE_DIGEST_INCLUDE_SRC Y; - # Allow SPA clients to request access to services through an iptables # firewall instead of just to it (i.e. access through the FWKNOP_FORWARD # chain instead of the INPUT chain). This also requires the @@ -142,48 +129,33 @@ ENABLE_IPT_OUTPUT N; # REQUIRE_SOURCE_ADDRESS N; -# Config variable to force fwknopd to always treat the sniffing interface as -# the "cooked" interface type on Linux. -# -ENABLE_COOKED_INTF N; - -# This pair of variables controls whether fwknopd voluntarily exits and over -# what time interval. When fwknopd exits, knopwatchd will restart it. -# Because fwknop controls the accessibility of services, this feature can be -# used to make sure that the fwknop rules are flushed (see the -# FLUSH_IPT_AT_INIT variable), and the effects of any potential logic (or -# other) bugs are minimized since fwknopd will start "fresh" when knopwatchd -# kicks it off. NOTE: This feature is almost never required since fwknopd is -# generally quite stable, and is mostly offered for the the extra paranoid. -# -ENABLE_VOLUNTARY_EXITS N; -EXIT_INTERVAL 1440; ### minutes (1 day) - # Specify the the maximum number of bytes to sniff per frame - 1500 # is a good default # MAX_SNIFF_BYTES 1500; -# Flush all existing rules in the fwknop chains at fwknop start time. +# Flush all existing rules in the fwknop chains at fwknop start time and/or +# exit time. They default to Y. # -FLUSH_IPT_AT_INIT Y; +#FLUSH_IPT_AT_INIT Y; +#FLUSH_IPT_AT_EXIT Y; # If running on ipfw firewalls, this variable defines the rule number that # fwknopd uses to insert an ipfw pass rule. # -IPFW_RULE_NUM 1; +#IPFW_RULE_NUM 1; # If running on ipfw firewalls, this variable defines the rule set that will # be used to store expired rules that still have a dynamic rule associated # to them. That set will be disabled by fwknop and should not be enabled # while fwknop is running. Not used when ipfw isn't using dynamic rules. # -IPFW_SET_NUM 1; +#IPFW_SET_NUM 1; # For ipfw firewalls set the interval (in seconds) over which rules that # have no remaining dynamic rules associated with them will be removed. # -IPFW_DYNAMIC_INTERVAL 60; ### seconds +#IPFW_DYNAMIC_INTERVAL 60; ### seconds # Define the timeout for running a command # @@ -191,7 +163,7 @@ PCAP_CMD_TIMEOUT 10; # If GPG keys are used instead of a Rijndael symmetric key, this is # the default GPG keys directory. Note that each access block in -# /etc/fwknop/access.conf can specify its own GPG directory to override +# fwknop access.conf can specify its own GPG directory to override # this default. # GPG_HOME_DIR /root/.gnupg; @@ -200,50 +172,45 @@ GPG_HOME_DIR /root/.gnupg; # be created by a sniffer process (or something like the ulogd pcap # writer). # -PCAP_PKT_FILE /var/log/sniff.pcap; +#PCAP_PKT_FILE /var/log/sniff.pcap; # Define a comma-separated set of IP addresses and/or networks that should # be globally blacklisted. That is, any SPA packet that is from a source # IP (or has an internal --allow-ip) within a blacklisted network will be # ignored. # -BLACKLIST NONE; +#BLACKLIST NONE; # TTL values are decremented depending on the number of hops the packet # has taken before it hits the firewall. We will assume packets will not # jump through more than 20 hops on average. # -MAX_HOPS 20; +#MAX_HOPS 20; # Allow fwknopd to acquire SPA data from HTTP requests (generated with the # fwknop client in --HTTP mode). Note that the PCAP_FILTER variable would # need to be updated when this is enabled to sniff traffic over TCP/80 # connections # -ENABLE_SPA_OVER_HTTP N; +#ENABLE_SPA_OVER_HTTP N; # Note that fwknopd still only gets its data via pcap, so the filter # defined by PCAP_FILTER needs to be updated to include this TCP port. # -ENABLE_TCP_SERVER N; +#ENABLE_TCP_SERVER N; # Set the default port number that the fwknop_serv "dummy" TCP server # listens on. This server is only spawned when ENABLE_TCP_SERVER is set # to "Y". # -TCPSERV_PORT 62201; +#TCPSERV_PORT 62201; # Set the locale (via the LC_ALL variable). This can be set to NONE to # have fwknopd honor the default system locale. # LOCALE C; -# Set the type of syslog daemon that is used. The SYSLOG_DAEMON variable -# accepts three possible values: syslogd, syslog-ng, or metalog. -# -SYSLOG_DAEMON syslogd; - -# syslog identity and facility (the defaults are usually ok) +# Override syslog identity and facility (the defaults are usually ok). # The SYSLOG_FACILITY variable can be set to one of LOG_LOCAL{0-7} # or LOG_DAEMON (the default). # @@ -257,29 +224,9 @@ SYSLOG_DAEMON syslogd; # and "noemail" can be combined with a comma to disable all logging # and alerting. # -ALERTING_METHODS ALL; +#ALERTING_METHODS ALL; -# This variable defines the number of seconds that the IPTables::ChainMgr -# module should wait for running iptables commands. Normally iptables -# runs extremely fast from the command line (at least for the commands -# that fwknopd executes), so the default of 30 seconds is plenty. -# -IPT_CMD_ALARM 30; - -# Set the strategy that the IPTables::ChainMgr module will use for executing -# iptables commands. The default of "waitpid" means that IPTables::ChainMgr -# will use fork(), exec(), and waitpid(), whereas "system" means that -# "system()" will used, and finally "popen" means that iptables will be -# executed via popen(). -# -IPT_EXEC_STYLE waitpid; - -# Define the number of seconds that the IPTables::ChainMgr policy uses to -# sleep between successive iptables commands. Zero is the default. -# -IPT_EXEC_SLEEP 0; - -# Define the number of times that fwknopd or knoptm will run certain +# Define the number of times that fwknopd will run certain # critical iptables commands (such as adding a new access rule) if any # problems are encountered. # @@ -312,18 +259,18 @@ IPT_EXEC_TRIES 1; # EXTERNAL_CMD_OPEN /path/someprog $SOURCE $OPEN_PORTS # EXTERNAL_CMD_OPEN /path/otherprog $SRC # -ENABLE_EXTERNAL_CMDS N; -EXTERNAL_CMD_OPEN __NONE__; -EXTERNAL_CMD_CLOSE __NONE__; -EXTERNAL_CMD_ALARM 30; +#ENABLE_EXTERNAL_CMDS N; +#EXTERNAL_CMD_OPEN __NONE__; +#EXTERNAL_CMD_CLOSE __NONE__; +#EXTERNAL_CMD_ALARM 30; # if EXTERNAL_CMD_OPEN is used above, then the following two variables can # be used to enforce a prefix on variable substitutions - useful if there # are any naming conflicts with the external script and command line # arguments that are named the same as the variables to be substituted. # -ENABLE_EXT_CMD_PREFIX N; -EXT_CMD_PREFIX FWKNOP_; +#ENABLE_EXT_CMD_PREFIX N; +#EXT_CMD_PREFIX FWKNOP_; # fwknop uses the IPTables::ChainMgr module to add allow rules to a # custom iptables chain "FWKNOP_INPUT". This chain is called from @@ -350,56 +297,48 @@ EXT_CMD_PREFIX FWKNOP_; # "Rule_position": Defines the position where rule are added within the # To_chain. # -IPT_INPUT_ACCESS ACCEPT, src, filter, INPUT, 1, FWKNOP_INPUT, 1; +#IPT_INPUT_ACCESS ACCEPT, src, filter, INPUT, 1, FWKNOP_INPUT, 1; # The IPT_OUTPUT_ACCESS variable is only used if ENABLE_IPT_OUTPUT is enabled # -IPT_OUTPUT_ACCESS ACCEPT, dst, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1; +#IPT_OUTPUT_ACCESS ACCEPT, dst, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1; # The IPT_FORWARD_ACCESS variable is only used if ENABLE_IPT_FORWARDING is # enabled. # -IPT_FORWARD_ACCESS ACCEPT, src, filter, FORWARD, 1, FWKNOP_FORWARD, 1; -IPT_DNAT_ACCESS DNAT, src, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1; +#IPT_FORWARD_ACCESS ACCEPT, src, filter, FORWARD, 1, FWKNOP_FORWARD, 1; +#IPT_DNAT_ACCESS DNAT, src, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1; # The IPT_SNAT_ACCESS variable is not used unless both ENABLE_IPT_SNAT and # ENABLE_IPT_FORWARDING are enabled. Also, the external static IP must be # set with the SNAT_TRANSLATE_IP variable. The default is to use the # IPT_MASQUERADE_ACCESS variable. # -IPT_SNAT_ACCESS SNAT, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; -IPT_MASQUERADE_ACCESS MASQUERADE, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; +#IPT_SNAT_ACCESS SNAT, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; +#IPT_MASQUERADE_ACCESS MASQUERADE, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; # Directories # -FWKNOP_DIR /var/log/fwknop; +#FWKNOP_DIR /var/log/fwknop; FWKNOP_RUN_DIR /var/run/fwknop; -FWKNOP_MOD_DIR /usr/lib/fwknop; -FWKNOP_CONF_DIR /etc/fwknop; -FWKNOP_ERR_DIR $FWKNOP_DIR/errs; +#FWKNOP_MOD_DIR /usr/lib/fwknop; +#FWKNOP_CONF_DIR /etc/fwknop; +#FWKNOP_ERR_DIR $FWKNOP_DIR/errs; # Files # -ACCESS_CONF $FWKNOP_CONF_DIR/access.conf; -DIGEST_FILE $FWKNOP_DIR/digest.cache; +#ACCESS_CONF $FWKNOP_CONF_DIR/access.conf; FWKNOP_PID_FILE $FWKNOP_RUN_DIR/fwknopd.pid; -FWKNOP_CMDLINE_FILE $FWKNOP_RUN_DIR/fwknopd.cmd; -TCPSERV_PID_FILE $FWKNOP_RUN_DIR/fwknop_serv.pid; -PROC_IP_FORWARD_FILE /proc/sys/net/ipv4/ip_forward; +DIGEST_FILE $FWKNOP_RUN_DIR/digest.cache; +#FWKNOP_CMDLINE_FILE $FWKNOP_RUN_DIR/fwknopd.cmd; +#TCPSERV_PID_FILE $FWKNOP_RUN_DIR/fwknop_serv.pid; +#PROC_IP_FORWARD_FILE /proc/sys/net/ipv4/ip_forward; -# iptables command output and error collection files; these are -# used by IPTables::ChainMgr +# System binaries # -IPT_OUTPUT_FILE $FWKNOP_DIR/fwknopd.iptout; -IPT_ERROR_FILE $FWKNOP_DIR/fwknopd.ipterr; - -# system binaries -# -#gpgCmd /usr/bin/gpg; -#mailCmd /bin/mail; -#sendmailCmd /usr/sbin/sendmail; -#shCmd /bin/sh; -#mknodCmd /bin/mknod; -#iptablesCmd /sbin/iptables; -#ipfwCmd /sbin/ipfw; ### BSD and Mac OS X only -#fwknopdCmd /usr/sbin/fwknopd; -#fwknop_servCmd /usr/sbin/fwknop_serv; +EXE_GPG /usr/bin/gpg; +EXE_MAIL /bin/mail; +EXE_SENDMAIL /usr/sbin/sendmail; +EXE_SH /bin/sh; +EXE_MKNOD /bin/mknod; +EXE_IPTABLES /sbin/iptables; +EXE_IPFW /sbin/ipfw; ### BSD and Mac OS X only ###EOF### diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index 5a502f3e..6b17bbbb 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -47,6 +47,7 @@ #define DEF_CONF_DIR SYSCONFDIR"/fwknop" #endif #define DEF_CONFIG_FILE DEF_CONF_DIR"/"MY_NAME".conf" + #define DEF_INTERFACE "eth0" /* fwknopd-specific limits @@ -70,7 +71,6 @@ enum { */ enum { CONF_CONFIG_FILE = 0, - CONF_FIREWALL_LOG, CONF_GPG_KEY, CONF_OVERRIDE_CONFIG, CONF_EMAIL_ADDRESSES, @@ -83,8 +83,7 @@ enum { CONF_ENABLE_SPA_PACKET_AGING, CONF_MAX_SPA_PACKET_AGE, CONF_ENABLE_DIGEST_PERSISTENCE, - CONF_DIGEST_TYPE, - CONF_ENABLE_DIGEST_INCLUDE_SRC, + //CONF_ENABLE_DIGEST_INCLUDE_SRC, CONF_ENABLE_IPT_FORWARDING, CONF_ENABLE_IPT_LOCAL_NAT, CONF_ENABLE_IPT_SNAT, @@ -92,56 +91,58 @@ enum { CONF_ENABLE_PROC_IP_FORWARD, CONF_ENABLE_IPT_OUTPUT, CONF_REQUIRE_SOURCE_ADDRESS, - CONF_ENABLE_COOKED_INTF, + //CONF_ENABLE_COOKED_INTF, CONF_ENABLE_VOLUNTARY_EXITS, CONF_EXIT_INTERVAL, CONF_MAX_SNIFF_BYTES, - CONF_FLUSH_IPT_AT_INIT, - CONF_IPFW_RULE_NUM, - CONF_IPFW_SET_NUM, - CONF_IPFW_DYNAMIC_INTERVAL, + //CONF_FLUSH_IPT_AT_INIT, + //CONF_FLUSH_IPT_AT_EXIT, + //CONF_IPFW_RULE_NUM, + //CONF_IPFW_SET_NUM, + //CONF_IPFW_DYNAMIC_INTERVAL, CONF_PCAP_CMD_TIMEOUT, CONF_GPG_HOME_DIR, - CONF_PCAP_PKT_FILE, - CONF_BLACKLIST, - CONF_MAX_HOPS, - CONF_ENABLE_SPA_OVER_HTTP, - CONF_ENABLE_TCP_SERVER, - CONF_TCPSERV_PORT, + //CONF_PCAP_PKT_FILE, + //CONF_BLACKLIST, + //CONF_MAX_HOPS, + //CONF_ENABLE_SPA_OVER_HTTP, + //CONF_ENABLE_TCP_SERVER, + //CONF_TCPSERV_PORT, CONF_LOCALE, - CONF_SYSLOG_DAEMON, CONF_SYSLOG_IDENTITY, CONF_SYSLOG_FACILITY, - CONF_ALERTING_METHODS, - CONF_IPT_CMD_ALARM, - CONF_IPT_EXEC_STYLE, - CONF_IPT_EXEC_SLEEP, + //CONF_ALERTING_METHODS, CONF_IPT_EXEC_TRIES, - CONF_ENABLE_EXTERNAL_CMDS, - CONF_EXTERNAL_CMD_OPEN, - CONF_EXTERNAL_CMD_CLOSE, - CONF_EXTERNAL_CMD_ALARM, - CONF_ENABLE_EXT_CMD_PREFIX, - CONF_EXT_CMD_PREFIX, - CONF_IPT_INPUT_ACCESS, - CONF_IPT_OUTPUT_ACCESS, - CONF_IPT_FORWARD_ACCESS, - CONF_IPT_DNAT_ACCESS, - CONF_IPT_SNAT_ACCESS, - CONF_IPT_MASQUERADE_ACCESS, - CONF_FWKNOP_DIR, + //CONF_ENABLE_EXTERNAL_CMDS, + //CONF_EXTERNAL_CMD_OPEN, + //CONF_EXTERNAL_CMD_CLOSE, + //CONF_EXTERNAL_CMD_ALARM, + //CONF_ENABLE_EXT_CMD_PREFIX, + //CONF_EXT_CMD_PREFIX, + //CONF_IPT_INPUT_ACCESS, + //CONF_IPT_OUTPUT_ACCESS, + //CONF_IPT_FORWARD_ACCESS, + //CONF_IPT_DNAT_ACCESS, + //CONF_IPT_SNAT_ACCESS, + //CONF_IPT_MASQUERADE_ACCESS, + //CONF_FWKNOP_DIR, CONF_FWKNOP_RUN_DIR, - CONF_FWKNOP_MOD_DIR, - CONF_FWKNOP_CONF_DIR, - CONF_FWKNOP_ERR_DIR, - CONF_ACCESS_CONF, - CONF_DIGEST_FILE, + //CONF_FWKNOP_MOD_DIR, + //CONF_FWKNOP_CONF_DIR, + //CONF_FWKNOP_ERR_DIR, + //CONF_ACCESS_CONF, CONF_FWKNOP_PID_FILE, - CONF_FWKNOP_CMDLINE_FILE, - CONF_TCPSERV_PID_FILE, - CONF_PROC_IP_FORWARD_FILE, - CONF_IPT_OUTPUT_FILE, - CONF_IPT_ERROR_FILE, + CONF_DIGEST_FILE, + //CONF_FWKNOP_CMDLINE_FILE, + //CONF_TCPSERV_PID_FILE, + //CONF_PROC_IP_FORWARD_FILE, + CONF_EXE_GPG, + CONF_EXE_MAIL, + CONF_EXE_SENDMAIL, + CONF_EXE_SH, + CONF_EXE_MKNOD, + CONF_EXE_IPTABLES, + CONF_EXE_IPFW, NUMBER_OF_CONFIG_ENTRIES /* Marks the end and number of entries */ }; @@ -153,7 +154,6 @@ enum { */ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = { "CONFIG_FILE", - "FIREWALL_LOG", "GPG_KEY", "OVERRIDE_CONFIG", "EMAIL_ADDRESSES", @@ -166,8 +166,7 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = { "ENABLE_SPA_PACKET_AGING", "MAX_SPA_PACKET_AGE", "ENABLE_DIGEST_PERSISTENCE", - "DIGEST_TYPE", - "ENABLE_DIGEST_INCLUDE_SRC", + //"ENABLE_DIGEST_INCLUDE_SRC", "ENABLE_IPT_FORWARDING", "ENABLE_IPT_LOCAL_NAT", "ENABLE_IPT_SNAT", @@ -175,58 +174,69 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = { "ENABLE_PROC_IP_FORWARD", "ENABLE_IPT_OUTPUT", "REQUIRE_SOURCE_ADDRESS", - "ENABLE_COOKED_INTF", + //"ENABLE_COOKED_INTF", "ENABLE_VOLUNTARY_EXITS", "EXIT_INTERVAL", "MAX_SNIFF_BYTES", - "FLUSH_IPT_AT_INIT", - "IPFW_RULE_NUM", - "IPFW_SET_NUM", - "IPFW_DYNAMIC_INTERVAL", + //"FLUSH_IPT_AT_INIT", + //"FLUSH_IPT_AT_EXIT", + //"IPFW_RULE_NUM", + //"IPFW_SET_NUM", + //"IPFW_DYNAMIC_INTERVAL", "PCAP_CMD_TIMEOUT", "GPG_HOME_DIR", - "PCAP_PKT_FILE", - "BLACKLIST", - "MAX_HOPS", - "ENABLE_SPA_OVER_HTTP", - "ENABLE_TCP_SERVER", - "TCPSERV_PORT", + //"PCAP_PKT_FILE", + //"BLACKLIST", + //"MAX_HOPS", + //"ENABLE_SPA_OVER_HTTP", + //"ENABLE_TCP_SERVER", + //"TCPSERV_PORT", "LOCALE", - "SYSLOG_DAEMON", "SYSLOG_IDENTITY", "SYSLOG_FACILITY", - "ALERTING_METHODS", - "IPT_CMD_ALARM", - "IPT_EXEC_STYLE", - "IPT_EXEC_SLEEP", + //"ALERTING_METHODS", "IPT_EXEC_TRIES", - "ENABLE_EXTERNAL_CMDS", - "EXTERNAL_CMD_OPEN", - "EXTERNAL_CMD_CLOSE", - "EXTERNAL_CMD_ALARM", - "ENABLE_EXT_CMD_PREFIX", - "EXT_CMD_PREFIX", - "IPT_INPUT_ACCESS", - "IPT_OUTPUT_ACCESS", - "IPT_FORWARD_ACCESS", - "IPT_DNAT_ACCESS", - "IPT_SNAT_ACCESS", - "IPT_MASQUERADE_ACCESS", - "FWKNOP_DIR", + //"ENABLE_EXTERNAL_CMDS", + //"EXTERNAL_CMD_OPEN", + //"EXTERNAL_CMD_CLOSE", + //"EXTERNAL_CMD_ALARM", + //"ENABLE_EXT_CMD_PREFIX", + //"EXT_CMD_PREFIX", + //"IPT_INPUT_ACCESS", + //"IPT_OUTPUT_ACCESS", + //"IPT_FORWARD_ACCESS", + //"IPT_DNAT_ACCESS", + //"IPT_SNAT_ACCESS", + //"IPT_MASQUERADE_ACCESS", + //"FWKNOP_DIR", "FWKNOP_RUN_DIR", - "FWKNOP_MOD_DIR", - "FWKNOP_CONF_DIR", - "FWKNOP_ERR_DIR", - "ACCESS_CONF", - "DIGEST_FILE", + //"FWKNOP_MOD_DIR", + //"FWKNOP_CONF_DIR", + //"FWKNOP_ERR_DIR", + //"ACCESS_CONF", "FWKNOP_PID_FILE", - "FWKNOP_CMDLINE_FILE", - "TCPSERV_PID_FILE", - "PROC_IP_FORWARD_FILE", - "IPT_OUTPUT_FILE", - "IPT_ERROR_FILE" + "DIGEST_FILE", + //"FWKNOP_CMDLINE_FILE", + //"TCPSERV_PID_FILE", + //"PROC_IP_FORWARD_FILE", + "EXE_GPG", + "EXE_MAIL", + "EXE_SENDMAIL", + "EXE_SH", + "EXE_MKNOD", + "EXE_IPTABLES", + "EXE_IPFW" }; +/* SPA Packet info struct. +*/ +typedef struct spa_pkt_info +{ + unsigned int packet_data_len; + unsigned int packet_src_ip; + unsigned char packet_data[MAX_SPA_PACKET_LEN+1]; +} spa_pkt_info_t; + /* fwknopd server configuration parameters and values */ typedef struct fko_srv_options @@ -244,8 +254,7 @@ typedef struct fko_srv_options int data_link_offset; - unsigned int packet_data_len; /* Is > 0 if we have data */ - unsigned char packet_data[MAX_SPA_PACKET_LEN+1]; + spa_pkt_info_t spa_pkt; /* The current SPA packet */ /* This array holds all of the config file entry values as strings * indexed by their tag name. diff --git a/server/incoming_spa.c b/server/incoming_spa.c index 6280ca54..447b8a43 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -34,21 +34,19 @@ incoming_spa(fko_srv_options_t *opts) fko_ctx_t ctx; int res; + spa_pkt_info_t *spa_pkt = &(opts->spa_pkt); + /* Sanity check */ - if(opts->packet_data_len <= 0) + if(spa_pkt->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); +fprintf(stderr, "SPA Packet: '%s'\n", spa_pkt->packet_data); /* Get the decryption key */ - res = fko_new_with_data(&ctx, opts->packet_data, "sdf"); + res = fko_new_with_data(&ctx, spa_pkt->packet_data, "sdf"); if(res == FKO_SUCCESS) { @@ -63,6 +61,9 @@ fprintf(stderr, "Decode res = %i\n", res); 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); } diff --git a/server/log_msg.c b/server/log_msg.c index c04955a8..0db339e0 100644 --- a/server/log_msg.c +++ b/server/log_msg.c @@ -41,17 +41,24 @@ static int static_log_flag = 0; */ static char *log_name = NULL; +/* Free resources allocated for logging. +*/ +void +free_logging(void) +{ + if(log_name != NULL) + free(log_name); +} + /* Initialize logging sets the name used for syslog. */ void init_logging(fko_srv_options_t *opts) { char *my_name = NULL; - static unsigned char linit = 0; - /* Do nothing but silently return if we have already been called. + /* In case this is a re-init. */ - if(linit++) - return; + free_logging(); /* Allocate memory for the log_name and set the my_name to point * to the appropriate name. If the name is set in the config file, diff --git a/server/log_msg.h b/server/log_msg.h index 8977b2b1..0e4838f9 100644 --- a/server/log_msg.h +++ b/server/log_msg.h @@ -5,7 +5,7 @@ * * Author: Damien Stuart (dstuart@dstuart.org) * - * Purpose: Header file for pcap_capture.c. + * Purpose: Header file for log_msg.c. * * Copyright (C) 2009 Damien Stuart (dstuart@dstuart.org) * @@ -39,6 +39,7 @@ #define LOG_STDERR_MASK 0x0FFF void init_logging(fko_srv_options_t *opts); +void free_logging(void); void set_log_facility(int fac); void log_msg(int, char*, ...); diff --git a/server/pcap_capture.c b/server/pcap_capture.c index d208ee2e..7e81fe7c 100644 --- a/server/pcap_capture.c +++ b/server/pcap_capture.c @@ -29,6 +29,8 @@ #include "pcap_capture.h" #include "process_packet.h" #include "incoming_spa.h" +#include "config_init.h" +#include "sig_handler.h" /* The pcap capture routine. */ @@ -39,13 +41,14 @@ pcap_capture(fko_srv_options_t *opts) pcap_t *pcap; char errstr[PCAP_ERRBUF_SIZE] = {0}; + struct bpf_program fp; int res, pcap_errcnt = 0; int promisc = 1; - /* Set non-promiscuous mode only of the ENABLE_PCAP_POROMISC is + /* Set non-promiscuous mode only of the ENABLE_PCAP_PROMISC is * explicitly set to 'N'. */ if(opts->config[CONF_ENABLE_PCAP_PROMISC] != NULL @@ -126,16 +129,27 @@ pcap_capture(fko_srv_options_t *opts) exit(EXIT_FAILURE); } + /* Initialize our signal handlers. You can check the return value for + * the number of signals that were *not* set. Those that we not set + * will be listed in the log/stderr output. + */ + set_sig_handlers(); + /* Jump into our home-grown packet cature loop. */ while(1) { + /* Any signal except USR1 and USR2 mean break the loop. + */ + if(got_signal && (got_sigusr1 + got_sigusr2) == 0) + pcap_breakloop(pcap); + 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) + if(res > 0 && opts->spa_pkt.packet_data_len > 0) { incoming_spa(opts); @@ -162,7 +176,7 @@ pcap_capture(fko_srv_options_t *opts) } else if(res == -2) { - /* pcap_break_loop was called, so we bail. */ + /* pcap_breakloop was called, so we bail. */ break; } else @@ -176,6 +190,9 @@ pcap_capture(fko_srv_options_t *opts) usleep(10000); } #endif /* HAVE_LIBPCAP */ + + pcap_close(pcap); + return(0); } diff --git a/server/process_packet.c b/server/process_packet.c index 3a972a7f..77e05a9f 100644 --- a/server/process_packet.c +++ b/server/process_packet.c @@ -61,7 +61,7 @@ process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header, 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; @@ -164,7 +164,7 @@ process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header, return; /* - * Now we have data. For now we are not checking IP or port values. We + * 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. @@ -178,8 +178,9 @@ process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header, /* Put the data in our 1-entry queue. */ - memcpy(opts->packet_data, pkt_data, pkt_data_len); - opts->packet_data_len = pkt_data_len; + strlcpy(opts->spa_pkt.packet_data, pkt_data, pkt_data_len+1); + opts->spa_pkt.packet_data_len = pkt_data_len; + opts->spa_pkt.packet_src_ip = src_ip; return; } diff --git a/server/sig_handler.c b/server/sig_handler.c new file mode 100644 index 00000000..2db99281 --- /dev/null +++ b/server/sig_handler.c @@ -0,0 +1,115 @@ +/* + ***************************************************************************** + * + * File: sig_handler.c + * + * Author: Damien S. Stuart + * + * Purpose: Signal handling dta and 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 "log_msg.h" +#include "sig_handler.h" + +sig_atomic_t got_signal = 0; /* General signal flag (break capture) */ + +sig_atomic_t got_sighup = 0; /* SIGHUP flag */ +sig_atomic_t got_sigint = 0; /* SIGINT flag */ +sig_atomic_t got_sigterm = 0; /* SIGTERM flag */ +sig_atomic_t got_sigusr1 = 0; /* SIGUSR1 flag */ +sig_atomic_t got_sigusr2 = 0; /* SIGUSR2 flag */ + +/* SIGHUP Handler +*/ +void +sig_handler(int sig) +{ + got_signal = sig; + + switch(sig) { + case SIGHUP: + got_sighup = 1; + return; + case SIGINT: + got_sigint = 1; + return; + case SIGTERM: + got_sigterm = 1; + return; + case SIGUSR1: + got_sigusr1 = 1; + return; + case SIGUSR2: + got_sigusr2 = 1; + return; + } +} + +/* Setup signal handlers +*/ +int +set_sig_handlers(void) +{ + int err = 0; + + /* Clear the signal flags. + */ + got_signal = 0; + got_sighup = 0; + got_sigint = 0; + got_sigterm = 0; + got_sigusr1 = 0; + got_sigusr2 = 0; + + /* Setup the handlers */ + + if(signal(SIGHUP, sig_handler) == SIG_ERR) + { + log_msg(LOG_ERR|LOG_STDERR, "* Error setting SIGHUP handler"); + err++; + } + + if(signal(SIGINT, sig_handler) == SIG_ERR) + { + log_msg(LOG_ERR|LOG_STDERR, "* Error setting SIGINT handler"); + err++; + } + + if(signal(SIGTERM, sig_handler) == SIG_ERR) + { + log_msg(LOG_ERR|LOG_STDERR, "* Error setting SIGTERM handler"); + err++; + } + + if(signal(SIGUSR1, sig_handler) == SIG_ERR) + { + log_msg(LOG_ERR|LOG_STDERR, "* Error setting SIGUSR1 handler"); + err++; + } + + if(signal(SIGUSR2, sig_handler) == SIG_ERR) + { + log_msg(LOG_ERR|LOG_STDERR, "* Error setting SIGUSR2 handler"); + err++; + } + + return(err); +} + +/***EOF***/ diff --git a/server/sig_handler.h b/server/sig_handler.h new file mode 100644 index 00000000..edec2c3d --- /dev/null +++ b/server/sig_handler.h @@ -0,0 +1,43 @@ +/* + ***************************************************************************** + * + * File: sig_handler.h + * + * Author: Damien Stuart (dstuart@dstuart.org) + * + * Purpose: Header file for sig_handler functions and data. + * + * 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 SIG_HANDLER_H +#define SIG_HANDLER_H + +#include + +extern sig_atomic_t got_signal; + +extern sig_atomic_t got_sighup; +extern sig_atomic_t got_sigint; +extern sig_atomic_t got_sigterm; +extern sig_atomic_t got_sigusr1; +extern sig_atomic_t got_sigusr2; + +void sig_handler(int sig); + +#endif /* SIG_HANDLER_H */ + +/***EOF***/