diff --git a/doc/fwknopd.man.asciidoc b/doc/fwknopd.man.asciidoc index 612e3579..0082ea08 100644 --- a/doc/fwknopd.man.asciidoc +++ b/doc/fwknopd.man.asciidoc @@ -62,6 +62,10 @@ COMMAND-LINE OPTIONS in the foreground, message that would go to the log would instead be sent to stderr. This mode is usually used when testing and/or debugging. +*--fw-list*:: + List all firewall rules that any running *fwknopd* daemon has created + and then exit. + *-K, --Kill*:: Kill the current *fwknopd* process. This provides a quick and easy way to stop *fwknopd* without having to look in the process table. diff --git a/server/config_init.c b/server/config_init.c index 682af1cb..3892e44b 100644 --- a/server/config_init.c +++ b/server/config_init.c @@ -451,6 +451,9 @@ config_init(fko_srv_options_t *opts, int argc, char **argv) case 'f': opts->foreground = 1; break; + case FW_LIST: + opts->fw_list = 1; + break; case GPG_HOME_DIR: if (is_valid_dir(optarg)) { diff --git a/server/config_init.h b/server/config_init.h index ed5c6b9e..ba53edde 100644 --- a/server/config_init.h +++ b/server/config_init.h @@ -53,7 +53,8 @@ /* Long options values (for those that may not have a short option). */ enum { - GPG_HOME_DIR = 0x200, + FW_LIST = 0x200, + GPG_HOME_DIR, GPG_KEY, ROTATE_DIGEST_CACHE, NOOP /* Just to be a marker for the end */ @@ -75,6 +76,7 @@ static struct option cmd_opts[] = {"help", 0, NULL, 'h'}, {"interface", 1, NULL, 'i'}, {"kill", 0, NULL, 'K'}, + {"fw-list", 0, NULL, FW_LIST }, {"gpg-home-dir", 1, NULL, GPG_HOME_DIR }, {"gpg-key", 1, NULL, GPG_KEY }, {"locale", 1, NULL, 'l' }, diff --git a/server/extcmd.c b/server/extcmd.c index c612b3c9..23b7f309 100644 --- a/server/extcmd.c +++ b/server/extcmd.c @@ -69,6 +69,7 @@ _run_extcmd(uid_t user_uid, char *cmd, char *so_buf, size_t so_buf_sz, int timeo if(so_buf == NULL) { + /* Since we do not have to capture output, we will fork here (which we * would have to do anyway if we are running as another user as well). */ @@ -78,6 +79,12 @@ _run_extcmd(uid_t user_uid, char *cmd, char *so_buf, size_t so_buf_sz, int timeo log_msg(LOG_ERR, "run_extcmd: fork failed: %s", strerror(errno)); return(EXTCMD_FORK_ERROR); } + if (pid > 0) + { + /* we are the parent + */ + wait(NULL); + } else if (pid == 0) { /* We are the child */ @@ -91,7 +98,6 @@ _run_extcmd(uid_t user_uid, char *cmd, char *so_buf, size_t so_buf_sz, int timeo exit(EXTCMD_SETUID_ERROR); } } - exit(WEXITSTATUS(system(cmd))); } diff --git a/server/fw_util.c b/server/fw_util.c index d10bcf0e..c01435d4 100644 --- a/server/fw_util.c +++ b/server/fw_util.c @@ -107,7 +107,7 @@ jump_rule_exists(int chain_num) while((fgets(line_buf, CMD_BUFSIZE-1, ipt)) != NULL) { /* Get past comments and empty lines (note: we only look at the - * first character. + * first character). */ if(IS_EMPTY_LINE(line_buf[0])) continue; @@ -127,6 +127,48 @@ jump_rule_exists(int chain_num) return(pos); } +/* Print all firewall rules currently instantiated by the running fwknopd + * daemon to stdout. +*/ +int +fw_dump_rules(fko_srv_options_t *opts) +{ + int i; + int pos, res, status, got_err = 0; + int jump_rule_num; + char cmd_buf[CMD_BUFSIZE] = {0}; + char err[CMD_BUFSIZE] = {0}; + + struct fw_chain *ch = opts->fw_config->chain; + + printf("Listing rules in fwknop chains...\n"); + for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++) + { + + if(fwc.chain[i].target[0] == '\0') + continue; + + /* Create the list command + */ + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS, + opts->fw_config->fw_command, + ch[i].table, + ch[i].to_chain + ); + + //printf("(%i) CMD: '%s'\n", i, cmd_buf); + res = run_extcmd(cmd_buf, NULL, 0, 0); + + /* Expect full success on this */ + if(! EXTCMD_IS_SUCCESS(res)) + { + log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err); + got_err++; + } + } + return; +} + /* Quietly flush and delete all fwknop custom chains. */ static void @@ -319,9 +361,8 @@ set_fw_chain_conf(int type, char *conf_str) } void -fw_initialize(fko_srv_options_t *opts) +fw_config_init(fko_srv_options_t *opts) { - int res; memset(&fwc, 0x0, sizeof(struct fw_config)); @@ -391,6 +432,14 @@ fw_initialize(fko_srv_options_t *opts) */ opts->fw_config = &fwc; + return; +} + +void +fw_initialize(void) +{ + int res; + /* Flush the chains (just in case) so we can start fresh. */ delete_all_chains(); diff --git a/server/fw_util.h b/server/fw_util.h index 9ca74b81..b0427f80 100644 --- a/server/fw_util.h +++ b/server/fw_util.h @@ -49,10 +49,12 @@ /* Function prototypes */ -void fw_initialize(fko_srv_options_t *opts); +void fw_config_init(fko_srv_options_t *opts); +void fw_initialize(void); void fw_cleanup(void); int process_spa_request(fko_srv_options_t *opts, spa_data_t *spdat); void check_firewall_rules(fko_srv_options_t *opts); +int fw_dump_rules(fko_srv_options_t *opts); #endif /* FW_UTIL_H */ diff --git a/server/fwknopd.c b/server/fwknopd.c index d7aef353..8bbf0e2f 100644 --- a/server/fwknopd.c +++ b/server/fwknopd.c @@ -178,6 +178,20 @@ main(int argc, char **argv) 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. @@ -185,7 +199,7 @@ main(int argc, char **argv) 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. + * Otherwise, attempt to get the pid file lock and go on. */ if(opts.foreground == 0) { @@ -243,9 +257,10 @@ main(int argc, char **argv) ); } - /* Initialize the firewall rules handler. + /* Prepare the firewall - i.e. flush any old rules and (for iptables) + * create fwknop chains. */ - fw_initialize(&opts); + fw_initialize(); /* If the TCP server option was specified, fire it up here. */ diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index f73ef675..e79f8c78 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -359,6 +359,7 @@ typedef struct fko_srv_options //unsigned char no_locale; /* Flag to not allow setting locale */ unsigned char restart; /* Restart fwknopd flag */ unsigned char status; /* Get fwknopd status flag */ + unsigned char fw_list; /* List current firewall rules */ unsigned char test; /* Test mode flag */ unsigned char verbose; /* Verbose mode flag */