From 315f3e677843ba9e1efc8d03104f759859aa0d62 Mon Sep 17 00:00:00 2001 From: Damien Stuart Date: Sun, 20 Jun 2010 23:15:52 +0000 Subject: [PATCH] Tweak to client usage message output. Added TCP server funcionality to the server (call it a first cut). git-svn-id: file:///home/mbr/svn/fwknop/trunk@220 510a4753-2344-4c79-9c09-4d669213fbeb --- client/config_init.c | 8 +-- server/Makefile.am | 25 ++++---- server/config_init.c | 4 -- server/fwknopd.c | 23 +++++++ server/fwknopd.conf | 4 +- server/fwknopd_common.h | 15 +++-- server/incoming_spa.c | 5 +- server/pcap_capture.c | 4 +- server/tcp_server.c | 133 ++++++++++++++++++++++++++++++++++++++++ server/tcp_server.h | 35 +++++++++++ 10 files changed, 223 insertions(+), 33 deletions(-) create mode 100644 server/tcp_server.c create mode 100644 server/tcp_server.h diff --git a/client/config_init.c b/client/config_init.c index 8fdd57e2..832fdb18 100644 --- a/client/config_init.c +++ b/client/config_init.c @@ -484,10 +484,10 @@ usage(void) " protected by the fwknop server.\n" " -p, --server-port Set the destination port for outgoing SPA\n" " packet.\n" - " -P, --server-proto Set the protocol (udp, tcp, tcpraw, icmp) for\n" - " the outgoing SPA packet. Note: The 'tcpraw'\n" - " and 'icmp' modes use raw sockets and thus\n" - " require root access to run.\n" + " -P, --server-proto Set the protocol (udp, tcp, http, tcpraw,\n" + " icmp) for the outgoing SPA packet.\n" + " Note: The 'tcpraw' and 'icmp' modes use raw\n" + " sockets and thus require root access to use.\n" " -s, --source-ip Tell the fwknopd server to accept whatever\n" " source IP the SPA packet has as the IP that\n" " needs access (not recommended, and the\n" diff --git a/server/Makefile.am b/server/Makefile.am index ba17181b..cbfbb27c 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -1,19 +1,20 @@ -sbin_PROGRAMS = fwknopd +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 \ - sig_handler.c sig_handler.h replay_dbm.c replay_dbm.h \ - access.c access.h fw_util.c fw_util.h extcmd.c extcmd.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 \ + sig_handler.c sig_handler.h replay_dbm.c replay_dbm.h \ + access.c access.h fw_util.c fw_util.h extcmd.c extcmd.h \ + tcp_server.c tcp_server.h -fwknopd_LDADD = $(top_builddir)/lib/libfko.la +fwknopd_LDADD = $(top_builddir)/lib/libfko.la -fwknopd_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common -DSYSCONFDIR=\"$(sysconfdir)\" -DSYSRUNDIR=\"$(localstatedir)\" +fwknopd_CPPFLAGS = -I $(top_srcdir)/lib -I $(top_srcdir)/common -DSYSCONFDIR=\"$(sysconfdir)\" -DSYSRUNDIR=\"$(localstatedir)\" -fwknopddir = @sysconfdir@/fwknop +fwknopddir = @sysconfdir@/fwknop -dist_man_MANS = fwknopd.8 +dist_man_MANS = fwknopd.8 -dist_fwknopd_DATA = fwknopd.conf access.conf +dist_fwknopd_DATA = fwknopd.conf access.conf diff --git a/server/config_init.c b/server/config_init.c index c343e559..15b20791 100644 --- a/server/config_init.c +++ b/server/config_init.c @@ -312,10 +312,6 @@ set_preconfig_entries(fko_srv_options_t *opts) */ set_config_entry(opts, CONF_HOSTNAME, opts->hostname); - /* SPA_OVER_HTTP_PORT default to 80 - */ - set_config_entry(opts, CONF_SPA_OVER_HTTP_PORT, "80"); - /* Setup the local executables based on build-time info. #ifdef GPG_EXE set_config_entry(opts, CONF_EXE_GPG, GPG_EXE); diff --git a/server/fwknopd.c b/server/fwknopd.c index bb932218..7abc212c 100644 --- a/server/fwknopd.c +++ b/server/fwknopd.c @@ -242,6 +242,29 @@ main(int argc, char **argv) */ fw_initialize(&opts); + /* If the TCP server option was specified, fire it up here. + */ + if(opts.config[CONF_ENABLE_TCP_SERVER] != NULL + && strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0) + { + if(opts.config[CONF_TCPSERV_PORT] == NULL + || atoi(opts.config[CONF_TCPSERV_PORT]) <= 0 + || atoi(opts.config[CONF_TCPSERV_PORT]) > 65535) + { + log_msg(LOG_WARNING, + "WARNING: ENABLE_TCP_SERVER is set, but TCPSERV_PORT is not set or not valid." + ); + } + else + { + res = run_tcp_server(&opts); + if(res < 0) + log_msg(LOG_WARNING, "Fork error from run_tcp_serv."); + else + opts.tcp_server_pid = res; + } + } + /* Intiate pcap capture mode... */ pcap_capture(&opts); diff --git a/server/fwknopd.conf b/server/fwknopd.conf index 5864ef0a..3ec91c40 100644 --- a/server/fwknopd.conf +++ b/server/fwknopd.conf @@ -190,13 +190,13 @@ PCAP_CMD_TIMEOUT 10; # 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. diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index 00f516c1..0c87bce7 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -151,9 +151,8 @@ enum { //CONF_PCAP_PKT_FILE, //CONF_BLACKLIST, CONF_ENABLE_SPA_OVER_HTTP, - CONF_SPA_OVER_HTTP_PORT, - //CONF_ENABLE_TCP_SERVER, - //CONF_TCPSERV_PORT, + CONF_ENABLE_TCP_SERVER, + CONF_TCPSERV_PORT, CONF_LOCALE, CONF_SYSLOG_IDENTITY, CONF_SYSLOG_FACILITY, @@ -233,9 +232,8 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = { //"PCAP_PKT_FILE", //"BLACKLIST", "ENABLE_SPA_OVER_HTTP", - "SPA_OVER_HTTP_PORT", - //"ENABLE_TCP_SERVER", - //"TCPSERV_PORT", + "ENABLE_TCP_SERVER", + "TCPSERV_PORT", "LOCALE", "SYSLOG_IDENTITY", "SYSLOG_FACILITY", @@ -404,8 +402,8 @@ typedef struct spa_data char *version; short message_type; char *spa_message; - char spa_message_src_ip[16]; - char pkt_source_ip[16]; + char spa_message_src_ip[MAX_IP_STR_LEN]; + char pkt_source_ip[MAX_IP_STR_LEN]; char spa_message_remain[1024]; /* --DSS FIXME: arbitrary bounds */ char *nat_access; char *server_auth; @@ -431,6 +429,7 @@ typedef struct fko_srv_options unsigned char verbose; /* Verbose mode flag */ int data_link_offset; + int tcp_server_pid; spa_pkt_info_t spa_pkt; /* The current SPA packet */ diff --git a/server/incoming_spa.c b/server/incoming_spa.c index a852e649..373856c6 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -71,7 +71,8 @@ preprocess_spa_data(fko_srv_options_t *opts, char *src_ip) return(SPA_MSG_HTTP_NOT_ENABLED); } - /* Now extract, adjust, and set just the SPA message itself. + /* Now extract, adjust (convert characters translated by the fwknop + * client), and reset the SPA message itself. */ strlcpy(spa_pkt->packet_data, ndx+5, pkt_data_len); @@ -107,6 +108,8 @@ preprocess_spa_data(fko_srv_options_t *opts, char *src_ip) } } + /* --DSS: Are there other checks we can do here ??? */ + /* If we made it here, we have no reason to assume this is not SPA data * (at least until we come up with more checks). */ diff --git a/server/pcap_capture.c b/server/pcap_capture.c index 811db961..d23cc4b6 100644 --- a/server/pcap_capture.c +++ b/server/pcap_capture.c @@ -193,8 +193,8 @@ pcap_capture(fko_srv_options_t *opts) pending_break = 1; } } - /* If there was an error, complain and go on (to an extent - * before giving up). + /* If there was an error, complain and go on (to an extent before + * giving up). */ else if(res == -1) { diff --git a/server/tcp_server.c b/server/tcp_server.c new file mode 100644 index 00000000..219ed87b --- /dev/null +++ b/server/tcp_server.c @@ -0,0 +1,133 @@ +/* $Id$ + ***************************************************************************** + * + * File: tcp_server.c + * + * Author: Damien Stuart (dstuart@dstuart.org) + * + * Purpose: Spawns off a dummy tcp server for fwknopd. Its purpose is + * to accept a tcp connection, then drop it after the first packet. + * + * Copyright (C) 2010 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 "tcp_server.h" +#include "log_msg.h" +#include + +#if HAVE_SYS_SOCKET_H + #include +#endif +#include +#include + +static int c_sock; + +/* Fork off and run a "dummy" TCP server. The return value is the PID of + * the child process or -1 if there is a fork error. +*/ +int +run_tcp_server(fko_srv_options_t *opts) +{ + pid_t pid; + int s_sock, clen; + struct sockaddr_in saddr, caddr; + char sipbuf[MAX_IP_STR_LEN]; + + unsigned short port = atoi(opts->config[CONF_TCPSERV_PORT]); + + log_msg(LOG_INFO, "Kicking off TCP server for port %i", port); + + /* Fork off a child process to run the command and provide its outputs. + */ + pid = fork(); + + /* Non-zero pid means we are the parent or there was a fork error. + * in either case we simply return that value to the caller. + */ + if (pid != 0) + return(pid); + + /* We are the child, so let's make a TCP server */ + + if ((s_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + { + log_msg(LOG_ERR|LOG_STDERR, "run_tcp_server: socket() failed: %s", + strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Construct local address structure */ + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; /* Internet address family */ + saddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ + saddr.sin_port = htons(port); /* Local port */ + + /* Bind to the local address */ + if (bind(s_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) + { + log_msg(LOG_ERR|LOG_STDERR, "run_tcp_server: bind() failed: %s", + strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Mark the socket so it will listen for incoming connections + * (but only one at a time) + */ + if (listen(s_sock, 1) < 0) + { + log_msg(LOG_ERR|LOG_STDERR, "run_tcp_server: listen() failed: %s", + strerror(errno)); + exit(EXIT_FAILURE); + } + + clen = sizeof(caddr); + + /* Now loop and accept and drop connections after the first packet or a + * short timeout. + */ + while(1) + { + /* Wait for a client to connect + */ + if((c_sock = accept(s_sock, (struct sockaddr *) &caddr, &clen)) < 0) + { + log_msg(LOG_ERR|LOG_STDERR, "run_tcp_server: accept() failed: %s", + strerror(errno)); + exit(EXIT_FAILURE); /* Should this be fatal? */ + } + + if(opts->verbose > 1) + { + memset(sipbuf, 0x0, MAX_IP_STR_LEN); + inet_ntop(AF_INET, &(caddr.sin_addr.s_addr), sipbuf, MAX_IP_STR_LEN); + log_msg(LOG_INFO, "tcp_server: Got TCP connection from %s.", sipbuf); + } + + /* Though hacky and clunky, we just sleep for a second then + * close the socket. No need to read or write anything. This + * just gives the client a sufficient window to send their + * request on this socket. In any case the socket is closed + * after that time. + */ + usleep(1000000); + + close(c_sock); + } +} + +/***EOF***/ diff --git a/server/tcp_server.h b/server/tcp_server.h new file mode 100644 index 00000000..28636ee4 --- /dev/null +++ b/server/tcp_server.h @@ -0,0 +1,35 @@ +/* $Id$ + ***************************************************************************** + * + * File: tcp_server.h + * + * Author: Damien Stuart (dstuart@dstuart.org) + * + * Purpose: Header file for tcp_server.c. + * + * Copyright (C) 2010 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 TCP_SERVER_H +#define TCP_SERVER_H + +/* Function prototypes +*/ +int run_tcp_server(fko_srv_options_t *opts); + +#endif /* TCP_SERVER_H */ + +/***EOF***/