From 4a41ecc9556fedd4bb04206081b4096a2fddaeee Mon Sep 17 00:00:00 2001 From: Michael Rash Date: Wed, 12 Oct 2011 23:36:51 -0400 Subject: [PATCH] removed --- server/fwknopd.c.orig | 664 ------------------------------------- server/fwknopd.c.rej | 39 --- server/incoming_spa.c.orig | 541 ------------------------------ server/replay_cache.c.orig | 326 ------------------ 4 files changed, 1570 deletions(-) delete mode 100644 server/fwknopd.c.orig delete mode 100644 server/fwknopd.c.rej delete mode 100644 server/incoming_spa.c.orig delete mode 100644 server/replay_cache.c.orig diff --git a/server/fwknopd.c.orig b/server/fwknopd.c.orig deleted file mode 100644 index c7d88278..00000000 --- a/server/fwknopd.c.orig +++ /dev/null @@ -1,664 +0,0 @@ -/* - ***************************************************************************** - * - * File: fwknopd.c - * - * Author: Damien S. Stuart - * - * Purpose: An implementation of an fwknop server. - * - * Copyright 2010 Damien Stuart (dstuart@dstuart.org) - * - * License (GNU Public License): - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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.h" -#include "config_init.h" -#include "access.h" -#include "process_packet.h" -#include "pcap_capture.h" -#include "log_msg.h" -#include "utils.h" -#include "fw_util.h" -#include "sig_handler.h" -#include "replay_cache.h" -#include "tcp_server.h" - -/* Prototypes -*/ -static void check_dir_path(const char *path, const char *path_name, unsigned char use_basename); -static int make_dir_path(const char *path); -static void daemonize_process(fko_srv_options_t *opts); -static int write_pid_file(fko_srv_options_t *opts); -static pid_t get_running_pid(fko_srv_options_t *opts); - -int -main(int argc, char **argv) -{ - int res, last_sig, rpdb_count; - char *locale; - pid_t old_pid; - - fko_srv_options_t opts; - - while(1) - { - /* Handle command line - */ - config_init(&opts, argc, argv); - - /* Process any options that do their thing and exit. */ - - /* Kill the currently running fwknopd? - */ - if(opts.kill == 1) - { - old_pid = get_running_pid(&opts); - - if(old_pid > 0) - { - 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 - { - fprintf(stderr, "No running fwknopd detected.\n"); - exit(EXIT_FAILURE); - } - } - - /* Status of the currently running fwknopd? - */ - if(opts.status == 1) - { - old_pid = write_pid_file(&opts); - - if(old_pid > 0) - fprintf(stderr, "Detected fwknopd is running (pid=%i).\n", old_pid); - else - fprintf(stderr, "No running fwknopd detected.\n"); - - exit(EXIT_SUCCESS); - } - - /* Restart the currently running fwknopd? - */ - if(opts.restart == 1 || opts.status == 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"); - exit(EXIT_FAILURE); - } - } - - /* Initialize logging. - */ - init_logging(&opts); - -#if HAVE_LOCALE_H - /* Set the locale if specified. - */ - if(opts.config[CONF_LOCALE] != NULL - && strncasecmp(opts.config[CONF_LOCALE], "NONE", 4) != 0) - { - locale = setlocale(LC_ALL, opts.config[CONF_LOCALE]); - - if(locale == NULL) - { - log_msg(LOG_ERR, - "WARNING: Unable to set locale to '%s'.", - opts.config[CONF_LOCALE] - ); - } - else - { - if(opts.verbose) - log_msg(LOG_INFO, - "Locale set to '%s'.", opts.config[CONF_LOCALE] - ); - } - } -#endif - - /* Make sure we have a valid run dir and path leading to digest file - * in case it configured to be somewhere other than the run dir. - */ - check_dir_path((const char *)opts.config[CONF_FWKNOP_RUN_DIR], "Run", 0); - check_dir_path((const char *)opts.config[CONF_DIGEST_FILE], "Run", 1); - - /* Process the access.conf file. - */ - parse_access_file(&opts); - - /* Show config (including access.conf vars) and exit dump config was - * wanted. - */ - if(opts.dump_config == 1) - { - dump_config(&opts); - dump_access_list(&opts); - exit(EXIT_SUCCESS); - } - - /* Initialize the firewall rules handler based on the fwknopd.conf - * file, but (for iptables firewalls) don't flush any rules or create - * any chains yet. This allows us to dump the current firewall rules - * via fw_rules_dump() in --fw-list mode before changing around any rules - * of an existing fwknopd process. - */ - fw_config_init(&opts); - - if(opts.fw_list == 1) - { - fw_dump_rules(&opts); - exit(EXIT_SUCCESS); - } - - /* If we are a new process (just being started), proceed with normal - * start-up. Otherwise, we are here as a result of a signal sent to an - * existing process and we want to restart. - */ - 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 file 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 - { - log_msg(LOG_INFO, "Re-starting %s", MY_NAME); - } - - if(opts.verbose > 1 && opts.foreground) - { - dump_config(&opts); - dump_access_list(&opts); - } - - /* Initialize the digest cache for replay attack detection - * if so configured. - */ - if(strncasecmp(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0) - { - rpdb_count = replay_db_init(&opts); - - if(rpdb_count < 0) - { - log_msg(LOG_WARNING, - "Error opening digest cache file. Incoming digests will not be remembered." - ); - strcpy(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "N"); - } - - if(opts.verbose) - log_msg(LOG_ERR, - "Using Digest Cache: '%s' (entry count = %i)", - opts.config[CONF_DIGEST_FILE], rpdb_count - ); - } - - /* Prepare the firewall - i.e. flush any old rules and (for iptables) - * create fwknop chains. - */ - fw_initialize(&opts); - - /* If the TCP server option was set, fire it up here. - */ - if(strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0) - { - if(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 valid. TCP server not started!" - ); - } - else - { - run_tcp_server(&opts); - } - } - - /* Intiate pcap capture mode... - */ - pcap_capture(&opts); - - if(got_signal) { - last_sig = got_signal; - got_signal = 0; - - if(got_sighup) - { - log_msg(LOG_WARNING, "Got SIGHUP. Re-reading configs."); - free_configs(&opts); - kill(opts.tcp_server_pid, SIGTERM); - usleep(1000000); - got_sighup = 0; - } - else if(got_sigint) - { - log_msg(LOG_WARNING, "Got SIGINT. Exiting..."); - got_sigint = 0; - break; - } - else if(got_sigterm) - { - log_msg(LOG_WARNING, "Got SIGTERM. Exiting..."); - got_sigterm = 0; - break; - } - else - { - log_msg(LOG_WARNING, - "Got signal %i. No defined action but to exit.", last_sig); - break; - } - } - else if (opts.packet_ctr_limit > 0 - && opts.packet_ctr >= opts.packet_ctr_limit) - { - log_msg(LOG_INFO, - "Packet count limit (%d) reached. Exiting...", - opts.packet_ctr_limit); - break; - } - else /* got_signal was not set (should be if we are here) */ - { - log_msg(LOG_WARNING, - "Capture ended without signal. Exiting..."); - break; - } - } - - log_msg(LOG_INFO, "Shutting Down fwknopd."); - - /* Kill the TCP server (if we have one running). - */ - if(opts.tcp_server_pid > 0) - { - log_msg(LOG_INFO, "Killing the TCP server (pid=%i)", - opts.tcp_server_pid); - - kill(opts.tcp_server_pid, SIGTERM); - - /* --DSS XXX: This seems to be necessary if the tcp server - * was restarted byt this program. We need to - * investigate an fix this. For now, this works - * (it is kludgy, but does no harm afaik). - */ - kill(opts.tcp_server_pid, SIGKILL); - } - - /* Other cleanup. - */ - fw_cleanup(); - free_logging(); - free_configs(&opts); - - return(0); -} - -/* Ensure the specified directory exists. If not, create it or die. -*/ -static void -check_dir_path(const char *filepath, const char *fp_desc, unsigned char use_basename) -{ - struct stat st; - int res; - char tmp_path[MAX_PATH_LEN]; - char *ndx; - - /* - * FIXME: We shouldn't use a hard-coded dir-separator here. - */ - /* But first make sure we are using an absolute path. - */ - if(*filepath != PATH_SEP) - { - log_msg(LOG_ERR, - "Configured %s directory (%s) is not an absolute path.", fp_desc, filepath - ); - exit(EXIT_FAILURE); - } - - /* If this is a file path that we want to use only the basename, strip - * the trailing filename here. - */ - if(use_basename && ((ndx = strrchr(filepath, PATH_SEP)) != NULL)) - strlcpy(tmp_path, filepath, (ndx-filepath)+1); - else - strcpy(tmp_path, filepath); - - /* At this point, we should make the path is more than just the - * PATH_SEP. If it is not, silently return. - */ - if(strlen(tmp_path) < 2) - return; - - /* Make sure we have a valid directory. - */ - res = stat(tmp_path, &st); - if(res != 0) - { - if(errno == ENOENT) - { - log_msg(LOG_WARNING, - "%s directory: %s does not exist. Attempting to create it.", - fp_desc, tmp_path - ); - - /* Directory does not exist, so attempt to create it. - */ - res = make_dir_path(tmp_path); - if(res != 0) - { - log_msg(LOG_ERR, - "Unable to create %s directory: %s (error: %i)", - fp_desc, tmp_path, errno - ); - exit(EXIT_FAILURE); - } - - log_msg(LOG_ERR, - "Successfully created %s directory: %s", fp_desc, tmp_path - ); - } - else - { - log_msg(LOG_ERR, - "Stat of %s returned error %i", tmp_path, errno - ); - exit(EXIT_FAILURE); - } - } - else - { - /* It is a file, but is it a directory? - */ - if(! S_ISDIR(st.st_mode)) - { - log_msg(LOG_ERR, - "Specified %s directory: %s is NOT a directory\n\n", fp_desc, tmp_path - ); - exit(EXIT_FAILURE); - } - } -} - -static int -make_dir_path(const char *run_dir) -{ - struct stat st; - int res, len; - char tmp_path[MAX_PATH_LEN]; - char *ndx; - - strlcpy(tmp_path, run_dir, MAX_PATH_LEN); - - len = strlen(tmp_path); - - /* Strip any trailing dir sep char. - */ - if(tmp_path[len-1] == PATH_SEP) - tmp_path[len-1] = '\0'; - - for(ndx = tmp_path+1; *ndx; ndx++) - { - if(*ndx == '/') - { - *ndx = '\0'; - - /* Stat this part of the path to see if it is a valid directory. - * If it does not exist, attempt to create it. If it does, and - * it is a directory, go on. Otherwise, any other error cause it - * to bail. - */ - if(stat(tmp_path, &st) != 0) - { - if(errno == ENOENT) - res = mkdir(tmp_path, S_IRWXU); - - if(res != 0) - return res; - } - - if(! S_ISDIR(st.st_mode)) - { - log_msg(LOG_ERR, - "Component: %s of %s is NOT a directory\n\n", tmp_path, run_dir - ); - return(ENOTDIR); - } - - *ndx = '/'; - } - } - - res = mkdir(tmp_path, S_IRWXU); - - return(res); -} - -/* Become a daemon: fork(), start a new session, chdir "/", - * and close unneeded standard filehandles. -*/ -static void -daemonize_process(fko_srv_options_t *opts) -{ - pid_t pid, old_pid; - - /* Reset the our umask - */ - umask(0); - - if ((pid = fork()) < 0) - { - perror("Unable to fork: "); - exit(EXIT_FAILURE); - } - else if (pid != 0) /* parent */ - { - exit(EXIT_SUCCESS); - } - - /* Child process from here on out */ - - /* Start a new session - */ - setsid(); - - /* Create the PID file (or be blocked by an existing one). - */ - 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"); - } - - /* Chdir to the root of the filesystem - */ - if ((chdir("/")) < 0) { - perror("Could not chdir() to /: "); - exit(EXIT_FAILURE); - } - - /* Close un-needed file handles - */ - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - return; -} - -static int -write_pid_file(fko_srv_options_t *opts) -{ - pid_t old_pid, my_pid; - int op_fd, lck_res, num_bytes; - char buf[6] = {0}; - - /* Reset errno (just in case) - */ - errno = 0; - - /* Open the PID file - */ - op_fd = open( - opts->config[CONF_FWKNOP_PID_FILE], O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR - ); - - if(op_fd == -1) - { - perror("Error trying to open PID file: "); - return -1; - } - - fcntl(op_fd, F_SETFD, FD_CLOEXEC); - - /* Attempt to lock the PID file. If we get an EWOULDBLOCK - * error, another instance already has the lock. So we grab - * the pid from the existing lock file, complain and bail. - */ - lck_res = lockf(op_fd, F_TLOCK, 0); - if(lck_res == -1) - { - if(errno != EAGAIN) - { - perror("Unexpected error from lockf: "); - return -1; - } - - close(op_fd); - - /* Look for an existing lock holder. If we get a pid return it. - */ - old_pid = get_running_pid(opts); - if(old_pid) - return old_pid; - - /* Otherwise, consider it an error. - */ - perror("Unable read existing PID file: "); - return -1; - } - - /* Write our PID to the file - */ - my_pid = getpid(); - snprintf(buf, 6, "%i\n", my_pid); - - if(opts->verbose > 1) - log_msg(LOG_INFO, "[+] Writing my PID (%i) to the lock file: %s\n", - my_pid, opts->config[CONF_FWKNOP_PID_FILE]); - - num_bytes = write(op_fd, buf, strlen(buf)); - - if(errno || num_bytes != strlen(buf)) - perror("Lock may not be valid. PID file write error: "); - - /* Sync/flush regardless... - */ - fsync(op_fd); - - /* Put the lock file discriptor in out options struct so any - * child processes we my spawn can close and release it. - */ - opts->lock_fd = op_fd; - - return 0; -} - -static pid_t -get_running_pid(fko_srv_options_t *opts) -{ - int op_fd; - char buf[6] = {0}; - pid_t rpid = 0; - - op_fd = open(opts->config[CONF_FWKNOP_PID_FILE], O_RDONLY); - - if(op_fd > 0) - { - if (read(op_fd, buf, 6) > 0) - rpid = (pid_t)atoi(buf); - - close(op_fd); - } - - return(rpid); -} - -/***EOF***/ diff --git a/server/fwknopd.c.rej b/server/fwknopd.c.rej deleted file mode 100644 index 1e156e7e..00000000 --- a/server/fwknopd.c.rej +++ /dev/null @@ -1,39 +0,0 @@ ---- server/fwknopd.c -+++ server/fwknopd.c -@@ -51,7 +51,7 @@ - int - main(int argc, char **argv) - { -- int res, last_sig, rp_cache_count; -+ int res, last_sig, rpdb_count; - char *locale; - pid_t old_pid; - -@@ -239,15 +239,14 @@ - dump_access_list(&opts); - } - -- /* Initialize the digest cache for replay attack detection (either -- * with dbm support or with the default simple cache file strategy -+ /* Initialize the digest cache (replay attack detection dbm) - * if so configured. - */ - if(strncasecmp(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0) - { -- rp_cache_count = replay_cache_init(&opts); -+ rpdb_count = replay_db_init(&opts); - -- if(rp_cache_count < 0) -+ if(rpdb_count < 0) - { - log_msg(LOG_WARNING, - "Error opening digest cache file. Incoming digests will not be remembered." -@@ -258,7 +257,7 @@ - if(opts.verbose) - log_msg(LOG_ERR, - "Using Digest Cache: '%s' (entry count = %i)", -- opts.config[CONF_DIGEST_FILE], rp_cache_count -+ opts.config[CONF_DIGEST_FILE], rpdb_count - ); - } - diff --git a/server/incoming_spa.c.orig b/server/incoming_spa.c.orig deleted file mode 100644 index 467fb18a..00000000 --- a/server/incoming_spa.c.orig +++ /dev/null @@ -1,541 +0,0 @@ -/* - ***************************************************************************** - * - * File: incoming_spa.c - * - * Author: Damien S. Stuart - * - * Purpose: Process an incoming SPA data packet for fwknopd. - * - * Copyright 2010 Damien Stuart (dstuart@dstuart.org) - * - * License (GNU Public License): - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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 "netinet_common.h" - -#if HAVE_SYS_WAIT_H - #include -#endif - -#include "incoming_spa.h" -#include "access.h" -#include "extcmd.h" -#include "log_msg.h" -#include "utils.h" -#include "fw_util.h" -#include "fwknopd_errors.h" -#include "replay_cache.h" - -/* Validate and in some cases preprocess/reformat the SPA data. Return an - * error code value if there is any indication the data is not valid spa data. -*/ -static int -preprocess_spa_data(fko_srv_options_t *opts, char *src_ip) -{ - spa_pkt_info_t *spa_pkt = &(opts->spa_pkt); - - char *ndx = (char *)&(spa_pkt->packet_data); - int pkt_data_len = spa_pkt->packet_data_len; - int i; - - /* At this point, we can reset the packet data length to 0. This our - * indicator to the rest of the program that we do not have a current - * spa packet to process (after this one that is). - */ - spa_pkt->packet_data_len = 0; - - /* Expect the data to be at least the minimum required size. - */ - if(pkt_data_len < MIN_SPA_DATA_SIZE) - return(SPA_MSG_LEN_TOO_SMALL); - - /* Detect and parse out SPA data from an HTTP reqest. If the SPA data - * starts with "GET /" and the user agent starts with "Fwknop", then - * assume it is a SPA over HTTP request. - */ - if(strncasecmp(ndx, "GET /", 5) == 0 - && strstr(ndx, "User-Agent: Fwknop") != NULL) - { - /* This looks like an HTTP request, so let's see if we are - * configured to accept such request and if so, find the SPA - * data. - */ - if(strncasecmp(opts->config[CONF_ENABLE_SPA_OVER_HTTP], "N", 1) == 0) - { - log_msg(LOG_WARNING, - "HTTP request from %s detected, but not enabled.", src_ip - ); - return(SPA_MSG_HTTP_NOT_ENABLED); - } - - /* Now extract, adjust (convert characters translated by the fwknop - * client), and reset the SPA message itself. - */ - strlcpy((char *)spa_pkt->packet_data, ndx+5, pkt_data_len); - - for(i=0; ipacket_data); - - /* Get encryption type and try its decoding routine first (if the key - * for that type is set) - */ - enc_type = fko_encryption_type((char *)spa_pkt->packet_data); - - if(enc_type == FKO_ENCRYPTION_RIJNDAEL) - { - if(acc->key != NULL) - res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, acc->key); - else - { - log_msg(LOG_ERR, - "No KEY for RIJNDAEL encrypted messages"); - return(SPA_MSG_FKO_CTX_ERROR); - } - } - else if(enc_type == FKO_ENCRYPTION_GPG) - { - /* For GPG we create the new context without decrypting on the fly - * so we can set some GPG parameters first. - */ - if(acc->gpg_decrypt_pw != NULL) - { - res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, NULL); - if(res != FKO_SUCCESS) - { - log_msg(LOG_WARNING, - "Error creating fko context (before decryption): %s", - fko_errstr(res) - ); - return(SPA_MSG_FKO_CTX_ERROR); - } - - /* Set whatever GPG parameters we have. - */ - if(acc->gpg_home_dir != NULL) - res = fko_set_gpg_home_dir(ctx, acc->gpg_home_dir); - if(res != FKO_SUCCESS) - { - log_msg(LOG_WARNING, - "Error setting GPG keyring path to %s: %s", - acc->gpg_home_dir, - fko_errstr(res) - ); - return(SPA_MSG_FKO_CTX_ERROR); - } - - if(acc->gpg_decrypt_id != NULL) - fko_set_gpg_recipient(ctx, acc->gpg_decrypt_id); - - /* If GPG_REQUIRE_SIG is set for this acc stanza, then set - * the FKO context accordingly and check the other GPG Sig- - * related parameters. This also applies when REMOTE_ID is - * set. - */ - if(acc->gpg_require_sig) - { - fko_set_gpg_signature_verify(ctx, 1); - - /* Set whether or not to ignore signature verification errors. - */ - fko_set_gpg_ignore_verify_error(ctx, acc->gpg_ignore_sig_error); - } - else - { - fko_set_gpg_signature_verify(ctx, 0); - fko_set_gpg_ignore_verify_error(ctx, 1); - } - - /* Now decrypt the data. - */ - res = fko_decrypt_spa_data(ctx, acc->gpg_decrypt_pw); - } - else - { - log_msg(LOG_ERR, - "No GPG_DECRYPT_PW for GPG encrypted messages"); - return(SPA_MSG_FKO_CTX_ERROR); - } - } - else - { - log_msg(LOG_ERR, "Unable to determing encryption type. Got type=%i.", - enc_type); - return(SPA_MSG_FKO_CTX_ERROR); - } - - /* Do we have a valid FKO context? - */ - if(res != FKO_SUCCESS) - { - log_msg(LOG_WARNING, "Error creating fko context: %s", - fko_errstr(res)); - - if(IS_GPG_ERROR(res)) - log_msg(LOG_WARNING, " - GPG ERROR: %s", - fko_gpg_errstr(ctx)); - - goto clean_and_bail; - } - - /* At this point, we assume the SPA data is valid. Now we need to see - * if it meets our access criteria. - */ - if(opts->verbose > 2) - log_msg(LOG_INFO, "SPA Decode (res=%i):\n%s", res, dump_ctx(ctx)); - - /* First, if this is a GPG message, and GPG_REMOTE_ID list is not empty, - * then we need to make sure this incoming message is signer ID matches - * an entry in the list. - */ - if(enc_type == FKO_ENCRYPTION_GPG && acc->gpg_require_sig) - { - res = fko_get_gpg_signature_id(ctx, &gpg_id); - if(res != FKO_SUCCESS) - { - log_msg(LOG_WARNING, "Error pulling the GPG signature ID from the context: %s", - fko_gpg_errstr(ctx)); - goto clean_and_bail; - } - - if(opts->verbose) - log_msg(LOG_INFO, "Incoming SPA data signed by '%s'.", gpg_id); - - if(acc->gpg_remote_id != NULL && !acc_check_gpg_remote_id(acc, gpg_id)) - { - log_msg(LOG_WARNING, - "Incoming SPA packet signed by ID: %s, but that ID is not the GPG_REMOTE_ID list.", - gpg_id); - goto clean_and_bail; - } - } - - /* Check for replays if so configured. - */ - if(strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0) - { - res = replay_check(opts, ctx); - if(res != 0) /* non-zero means we have seen this packet before. */ - goto clean_and_bail; - } - - /* Populate our spa data struct for future reference. - */ - res = get_spa_data_fields(ctx, &spadat); - - /* Figure out what our timeout will be. If it is specified in the SPA - * data, then use that. If not, try the FW_ACCESS_TIMEOUT from the - * access.conf file (if there is one). Otherwise use the default. - */ - if(spadat.client_timeout > 0) - spadat.fw_access_timeout = spadat.client_timeout; - else if(acc->fw_access_timeout > 0) - spadat.fw_access_timeout = acc->fw_access_timeout; - else - spadat.fw_access_timeout = DEF_FW_ACCESS_TIMEOUT; - - if(res != FKO_SUCCESS) - { - log_msg(LOG_ERR, "Unexpected error pulling SPA data from the context: %s", - fko_errstr(res)); - res = SPA_MSG_ERROR; - goto clean_and_bail; - } - - /* Check packet age if so configured. - */ - if(strncasecmp(opts->config[CONF_ENABLE_SPA_PACKET_AGING], "Y", 1) == 0) - { - time(&now_ts); - - ts_diff = now_ts - spadat.timestamp; - - if(ts_diff > atoi(opts->config[CONF_MAX_SPA_PACKET_AGE])) - { - log_msg(LOG_WARNING, "SPA data is too old (%i seconds).", - ts_diff); - res = SPA_MSG_TOO_OLD; - goto clean_and_bail; - } - } - - /* At this point, we have enough to check the embedded (or packet source) - * IP address against the defined access rights. We start by splitting - * the spa msg source IP from the remainder of the message. - */ - spa_ip_demark = strchr(spadat.spa_message, ','); - if(spa_ip_demark == NULL) - { - log_msg(LOG_WARNING, "Error parsing SPA message string: %s", - fko_errstr(res)); - res = SPA_MSG_ERROR; - goto clean_and_bail; - } - - strlcpy(spadat.spa_message_src_ip, spadat.spa_message, (spa_ip_demark-spadat.spa_message)+1); - strlcpy(spadat.spa_message_remain, spa_ip_demark+1, 1024); - - /* If use source IP was requested (embedded IP of 0.0.0.0), make sure it - * is allowed. - */ - if(strcmp(spadat.spa_message_src_ip, "0.0.0.0") == 0) - { - if(acc->require_source_address) - { - log_msg(LOG_WARNING, - "Got 0.0.0.0 when valid source IP was required." - ); - res = SPA_MSG_ACCESS_DENIED; - goto clean_and_bail; - } - - spadat.use_src_ip = spadat.pkt_source_ip; - } - else - spadat.use_src_ip = spadat.spa_message_src_ip; - - /* If REQUIRE_USERNAME is set, make sure the username in this SPA data - * matches. - */ - if(acc->require_username != NULL) - { - if(strcmp(spadat.username, acc->require_username) != 0) - { - log_msg(LOG_WARNING, - "Username in SPA data (%s) does not match required username: %s", - spadat.username, acc->require_username - ); - res = SPA_MSG_ACCESS_DENIED; - goto clean_and_bail; - } - } - - /* Take action based on SPA message type. */ - - /* Command messages. - */ - if(spadat.message_type == FKO_COMMAND_MSG) - { - if(!acc->enable_cmd_exec) - { - log_msg(LOG_WARNING, - "SPA Command message are not allowed in the current configuration." - ); - res = SPA_MSG_ACCESS_DENIED; - } - else - { - log_msg(LOG_INFO, - "Processing SPA Command message: command='%s'.", - spadat.spa_message_remain - ); - - /* Do we need to become another user? If so, we call - * run_extcmd_as and pass the cmd_exec_uid. - */ - if(acc->cmd_exec_user != NULL && strncasecmp(acc->cmd_exec_user, "root", 4) != 0) - { - if(opts->verbose) - log_msg(LOG_INFO, "Setting effective user to %s (UID=%i) before running command.", - acc->cmd_exec_user, acc->cmd_exec_uid); - - - res = run_extcmd_as(acc->cmd_exec_uid, - spadat.spa_message_remain, NULL, 0, 0); - } - else /* Just run it as we are (root that is). */ - res = run_extcmd(spadat.spa_message_remain, NULL, 0, 5); - - /* --DSS XXX: I have found that the status (and res for that - * matter) have been unreliable indicators of the - * actual exit status of some commands. Not sure - * why yet. For now, we will take what we get. - */ - status = WEXITSTATUS(res); - - if(opts->verbose > 2) - log_msg(LOG_WARNING, - "CMD_EXEC: command returned %i", status); - - if(status != 0) - res = SPA_MSG_COMMAND_ERROR; - } - - goto clean_and_bail; - } - - /* From this point forward, we have some kind of access message. So - * we first see if access is allowed by checking access against - * restrict_ports and open_ports. - * - * --DSS TODO: We should add BLACKLIST support here as well. - */ - if(! acc_check_port_access(acc, spadat.spa_message_remain)) - { - log_msg(LOG_WARNING, - "One or more requested protocol/ports was denied per access.conf." - ); - - res = SPA_MSG_ACCESS_DENIED; - - goto clean_and_bail; - } - - /* At this point, we can process the SPA request. - */ - res = process_spa_request(opts, &spadat); - -clean_and_bail: - if(ctx != NULL) - fko_destroy(ctx); - - return(res); -} - -/***EOF***/ diff --git a/server/replay_cache.c.orig b/server/replay_cache.c.orig deleted file mode 100644 index 085823d6..00000000 --- a/server/replay_cache.c.orig +++ /dev/null @@ -1,326 +0,0 @@ -/* - ***************************************************************************** - * - * File: replay_cache.c - * - * Author: Damien S. Stuart - * - * Purpose: Provides the functions to check for possible replay attacks - * by using a cache of previously seen digests. This cache is a - * simple file by default, but can be made to use a dbm solution - * (ndbm or gdbm in ndbm compatibility mode) file to store the digest - * of a previously received SPA packets. - * - * Copyright 2010 Damien Stuart (dstuart@dstuart.org) - * - * License (GNU Public License): - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - ***************************************************************************** -*/ -#include "replay_cache.h" -#include "log_msg.h" -#include "fwknopd_errors.h" - -#include - -#if HAVE_LIBGDBM - #include - - #define MY_DBM_FETCH(d, k) gdbm_fetch(d, k) - #define MY_DBM_STORE(d, k, v, m) gdbm_store(d, k, v, m) - #define MY_DBM_STRERROR(x) gdbm_strerror(x) - #define MY_DBM_CLOSE(d) gdbm_close(d) - - #define MY_DBM_REPLACE GDBM_REPLACE - #define MY_DBM_INSERT GDBM_INSERT - -#elif HAVE_LIBNDBM - #include - - #define MY_DBM_FETCH(d, k) dbm_fetch(d, k) - #define MY_DBM_STORE(d, k, v, m) dbm_store(d, k, v, m) - #define MY_DBM_STRERROR(x) strerror(x) - #define MY_DBM_CLOSE(d) dbm_close(d) - - #define MY_DBM_REPLACE DBM_REPLACE - #define MY_DBM_INSERT DBM_INSERT - -#else - #error "No GDBM or NDBM header file found. WTF?" -#endif - -#if HAVE_SYS_SOCKET_H - #include -#endif -#include - -#include - -#define MAX_DIGEST_SIZE 64 - -/* Rotate the digest file by simply renaming it. -*/ -static void -rotate_digest_cache_file(fko_srv_options_t *opts) -{ -#ifdef NO_DIGEST_CACHE - log_msg(LOG_WARNING, "Digest cache not supported. Nothing to rotate."); -#else - int res; - char *new_file = NULL; - - log_msg(LOG_INFO, "Rotating digest cache file."); - - new_file = malloc(strlen(opts->config[CONF_DIGEST_FILE])+5); - - if(new_file == NULL) - { - log_msg(LOG_ERR, "rotate_digest_cache_file: Memory allocation error."); - exit(EXIT_FAILURE); - } - - /* The new filename is just the original with a trailing '-old'. - */ - strcpy(new_file, opts->config[CONF_DIGEST_FILE]); - strcat(new_file, "-old"); - - res = rename(opts->config[CONF_DIGEST_FILE], new_file); - - if(res < 0) - log_msg(LOG_ERR, "Unable to rename digest file: %s to %s: %s", - opts->config[CONF_DIGEST_FILE], new_file, strerror(errno) - ); -#endif /* NO_DIGEST_CACHE */ -} - -/* Check for the existence of the replay dbm file, and create it if it does - * not exist. Returns the number of db entries or -1 on error. -*/ -int -replay_db_init(fko_srv_options_t *opts) -{ -#ifdef NO_DIGEST_CACHE - return 0; -#else - -#ifdef HAVE_LIBGDBM - GDBM_FILE rpdb; -#elif HAVE_LIBNDBM - DBM *rpdb; -#endif - - datum db_key, db_ent, db_next_key; - int db_count = 0; - - /* If rotation was specified, do it. - */ - if(opts->rotate_digest_cache) - rotate_digest_cache_file(opts); - -#ifdef HAVE_LIBGDBM - rpdb = gdbm_open( - opts->config[CONF_DIGEST_FILE], 512, GDBM_WRCREAT, S_IRUSR|S_IWUSR, 0 - ); -#elif HAVE_LIBNDBM - rpdb = dbm_open( - opts->config[CONF_DIGEST_FILE], O_RDWR|O_CREAT, S_IRUSR|S_IWUSR - ); -#endif - - if(!rpdb) - { - log_msg(LOG_ERR, - "Unable to open digest cache file: '%s': %s", - opts->config[CONF_DIGEST_FILE], - MY_DBM_STRERROR(errno) - ); - - return(-1); - } - -#ifdef HAVE_LIBGDBM - db_key = gdbm_firstkey(rpdb); - - while (db_key.dptr != NULL) - { - db_count++; - db_next_key = gdbm_nextkey(rpdb, db_key); - free(db_key.dptr); - db_key = db_next_key; - } -#elif HAVE_LIBNDBM - for (db_key = dbm_firstkey(rpdb); db_ent.dptr != NULL; db_key = dbm_nextkey(rpdb)) - db_count++; -#endif - - MY_DBM_CLOSE(rpdb); - - return(db_count); -#endif /* NO_DIGEST_CACHE */ -} - -/* Take an fko context, pull the digest and use it as the key to check the - * replay db (digest cache). Returns 1 if there was a match (a replay), - * 0 for no match, and -1 on error. -*/ -int -replay_check(fko_srv_options_t *opts, fko_ctx_t ctx) -{ -#ifdef NO_DIGEST_CACHE - return 0; -#else - -#ifdef HAVE_LIBGDBM - GDBM_FILE rpdb; -#elif HAVE_LIBNDBM - DBM *rpdb; -#endif - datum db_key, db_ent; - - char created[18], first[18], last[18]; - - char curr_ip[INET_ADDRSTRLEN+1] = {0}; - char last_ip[INET_ADDRSTRLEN+1] = {0}; - - char *digest; - int digest_len, res; - - digest_cache_info_t dc_info, *dci_p; - - res = fko_get_spa_digest(ctx, &digest); - if(res != FKO_SUCCESS) - { - log_msg(LOG_WARNING, "Error getting digest from SPA data: %s", - fko_errstr(res)); - - return(SPA_MSG_DIGEST_ERROR); - } - - digest_len = strlen(digest); - - db_key.dptr = digest; - db_key.dsize = digest_len; - - /* Check the db for the key - */ -#ifdef HAVE_LIBGDBM - rpdb = gdbm_open( - opts->config[CONF_DIGEST_FILE], 512, GDBM_WRCREAT, S_IRUSR|S_IWUSR, 0 - ); -#elif HAVE_LIBNDBM - rpdb = dbm_open(opts->config[CONF_DIGEST_FILE], O_RDWR, 0); -#endif - - if(!rpdb) - { - log_msg(LOG_WARNING, "Error opening digest_cache: '%s': %s", - opts->config[CONF_DIGEST_FILE], - MY_DBM_STRERROR(errno) - ); - - return(SPA_MSG_DIGEST_CACHE_ERROR); - } - - db_ent = MY_DBM_FETCH(rpdb, db_key); - - /* If the datum is not null, we have a match. Otherwise, we add - * this entry to the cache. - */ - if(db_ent.dptr != NULL) - { - dci_p = (digest_cache_info_t *)db_ent.dptr; - - /* Convert the IPs to a human readable form - */ - inet_ntop(AF_INET, &(opts->spa_pkt.packet_src_ip), - curr_ip, INET_ADDRSTRLEN); - inet_ntop(AF_INET, &(dci_p->src_ip), last_ip, INET_ADDRSTRLEN); - - /* Mark the last_replay time. - */ - dci_p->last_replay = time(NULL); - - /* Increment the replay count and check to see if it is the first one. - */ - if(++(dci_p->replay_count) == 1) - { - /* This is the first replay so make it the same as last_replay - */ - dci_p->first_replay = dci_p->last_replay; - } - - strftime(created, 18, "%D %H:%M:%S", localtime(&(dci_p->created))); - strftime(first, 18, "%D %H:%M:%S", localtime(&(dci_p->first_replay))); - strftime(last, 18, "%D %H:%M:%S", localtime(&(dci_p->last_replay))); - - log_msg(LOG_WARNING, - "Replay detected from source IP: %s\n" - " Original source IP: %s\n" - " Entry created: %s\n" - " First replay: %s\n" - " Last replay: %s\n" - " Replay count: %i\n", - curr_ip, last_ip, - created, - first, - last, - dci_p->replay_count - ); - - /* Save it back to the digest cache - */ - if(MY_DBM_STORE(rpdb, db_key, db_ent, MY_DBM_REPLACE) != 0) - log_msg(LOG_WARNING, "Error updating entry in digest_cache: '%s': %s", - opts->config[CONF_DIGEST_FILE], - MY_DBM_STRERROR(errno) - ); - -#ifdef HAVE_LIBGDBM - free(db_ent.dptr); -#endif - - res = SPA_MSG_REPLAY; - } else { - /* This is a new SPA packet that needs to be added to the cache. - */ - dc_info.src_ip = opts->spa_pkt.packet_src_ip; - dc_info.created = time(NULL); - dc_info.first_replay = dc_info.last_replay = dc_info.replay_count = 0; - - db_ent.dsize = sizeof(digest_cache_info_t); - db_ent.dptr = (char*)&(dc_info); - - if(MY_DBM_STORE(rpdb, db_key, db_ent, MY_DBM_INSERT) != 0) - { - log_msg(LOG_WARNING, "Error adding entry digest_cache: %s", - MY_DBM_STRERROR(errno) - ); - - res = SPA_MSG_DIGEST_CACHE_ERROR; - } - - res = SPA_MSG_SUCCESS; - } - - MY_DBM_CLOSE(rpdb); - - return(res); -#endif /* NO_DIGEST_CACHE */ -} - -/***EOF***/