From bc9e939a4cdb160c22809cd3b66dba67b8a6472a Mon Sep 17 00:00:00 2001 From: Christian Mauderer Date: Thu, 4 Aug 2016 13:20:04 +0200 Subject: pf: Add configuration via rc.conf. --- libbsd.py | 1 + libbsd_waf.py | 1 + rtemsbsd/include/machine/rtems-bsd-config.h | 4 + .../include/machine/rtems-bsd-rc-conf-services.h | 1 + rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c | 261 +++++++++++++++++++++ testsuite/rcconf02/test_main.c | 43 +++- 6 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c diff --git a/libbsd.py b/libbsd.py index d466ac68..73f5a67f 100755 --- a/libbsd.py +++ b/libbsd.py @@ -65,6 +65,7 @@ def rtems(mm): 'rtems/rtems-bsd-get-task-priority.c', 'rtems/rtems-bsd-get-task-stack-size.c', 'rtems/rtems-bsd-rc-conf-net.c', + 'rtems/rtems-bsd-rc-conf-pf.c', 'rtems/rtems-bsd-rc-conf.c', 'rtems/rtems-bsd-shell.c', 'rtems/rtems-bsd-shell-netcmds.c', diff --git a/libbsd_waf.py b/libbsd_waf.py index 5ae6ae1f..524b8bc1 100644 --- a/libbsd_waf.py +++ b/libbsd_waf.py @@ -1079,6 +1079,7 @@ def build(bld): 'rtemsbsd/rtems/rtems-bsd-get-task-priority.c', 'rtemsbsd/rtems/rtems-bsd-get-task-stack-size.c', 'rtemsbsd/rtems/rtems-bsd-rc-conf-net.c', + 'rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c', 'rtemsbsd/rtems/rtems-bsd-rc-conf.c', 'rtemsbsd/rtems/rtems-bsd-shell-dhcpcd.c', 'rtemsbsd/rtems/rtems-bsd-shell-netcmds.c', diff --git a/rtemsbsd/include/machine/rtems-bsd-config.h b/rtemsbsd/include/machine/rtems-bsd-config.h index 84562bf3..ed2a97ee 100644 --- a/rtemsbsd/include/machine/rtems-bsd-config.h +++ b/rtemsbsd/include/machine/rtems-bsd-config.h @@ -123,8 +123,11 @@ extern "C" { */ #if defined(RTEMS_BSD_CONFIG_FIREWALL_PF) #define RTEMS_BSD_CFGDECL_FIREWALL_PF SYSINIT_NEED_FIREWALL_PF + #define RTEMS_BSD_CFGDECL_FIREWALL_PF_SERVICE \ + RTEMS_BSD_RC_CONF_SYSINT(rc_conf_firewall_pf) #else #define RTEMS_BSD_CFGDECL_FIREWALL_PF + #define RTEMS_BSD_CFGDECL_FIREWALL_PF_SERVICE #endif /* RTEMS_BSD_CONFIG_FIREWALL_PF */ #if defined(RTEMS_BSD_CONFIG_FIREWALL_PFLOG) @@ -192,6 +195,7 @@ extern "C" { * Create the firewall */ RTEMS_BSD_CFGDECL_FIREWALL_PF; + RTEMS_BSD_CFGDECL_FIREWALL_PF_SERVICE; RTEMS_BSD_CFGDECL_FIREWALL_PFLOG; RTEMS_BSD_CFGDECL_FIREWALL_PFSYNC; diff --git a/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h b/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h index 34a8a8b8..1d14187a 100644 --- a/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h +++ b/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h @@ -155,6 +155,7 @@ extern void rtems_bsd_rc_conf_print_cmd(rtems_bsd_rc_conf* rc_conf, * Decls for the handlers. */ void rc_conf_net_init(void* arg); /* Installed by default. */ +void rc_conf_firewall_pf_init(void* arg); /* pf_enabled="YES" */ void rc_conf_telnetd_init(void* arg); /* telnetd_enabled="YES" */ void rc_conf_ftpd_init(void* arg); /* ftpd_enabled="YES" */ diff --git a/rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c b/rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c new file mode 100644 index 00000000..550bffba --- /dev/null +++ b/rtemsbsd/rtems/rtems-bsd-rc-conf-pf.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Handle the PF firewall directives found in rc.conf. + * - pf_enable + * - pf_rules + * - pf_flags + * + * Note: RTEMS ignores the + * - pf_program + * directive. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static char firewall_pf_rules_default[] = "/etc/pf.conf"; + +static int +firewall_pf_enable(rtems_bsd_rc_conf* rc_conf) +{ + char *args[] = { + "pfctl", + "-q", + "-e", + NULL + }; + + rtems_bsd_rc_conf_print_cmd(rc_conf, "pfctl", RTEMS_BSD_ARGC(args), + (const char **) args); + return rtems_bsd_command_pfctl(RTEMS_BSD_ARGC(args), args); +} + +static int +firewall_pf_flush( + rtems_bsd_rc_conf* rc_conf, + char what[]) +{ + char *flush[] = { + "pfctl", + "-q", + "-F", + what, + NULL + }; + + rtems_bsd_rc_conf_print_cmd(rc_conf, "pfctl", RTEMS_BSD_ARGC(flush), + (const char **) flush); + return rtems_bsd_command_pfctl(RTEMS_BSD_ARGC(flush), flush); +} + +/* + * Executes something like the following command line: + * pfctl -f [ [ [..]]] + */ +static int +firewall_pf_load_rules_with_extra_args( + rtems_bsd_rc_conf* rc_conf, + char *rules, + int argc, + const char **argv) +{ + char** args; + const int fixed_args = 2; /* "-f" and filename */ + int arg; + int r = -1; + bool prepare_failed = false; + + /* + * argc/argv contains something like the following: + * argc = 3 + * argv = {"pf_flags", "-i", "lo0"} + * + * Alternatively it might be + * argc = 0 + * argv = NULL + */ + + /* The code below assumes an argc >= 1. Fake it if there are no additional + * arguments. */ + if(argc == 0) { + argc = 1; + } + + args = calloc(argc + fixed_args + 1, sizeof(char*)); + if (args == NULL) { + return -1; + } + + args[0] = "pfctl"; + args[1] = "-f"; + args[2] = rules; + args[argc + fixed_args] = NULL; + + for (arg = 1; arg < argc; ++arg) { + args[arg + fixed_args] = strdup(argv[arg]); + if (args[arg + fixed_args] == NULL) { + prepare_failed = true; + break; + } + } + + if (prepare_failed == false) { + rtems_bsd_rc_conf_print_cmd(rc_conf, "pfctl", argc + fixed_args, + (const char **) args); + r = rtems_bsd_command_pfctl(argc + fixed_args, args); + } else { + r = EXIT_FAILURE; + } + + for (arg = 1; arg < argc; ++arg) { + free(args[arg + fixed_args]); + } + free(args); + + return r; +} + +static int +firewall_pf_service(rtems_bsd_rc_conf* rc_conf) +{ + rtems_bsd_rc_conf_argc_argv* aa; + int r; + int erroroccured = 0; + + aa = rtems_bsd_rc_conf_argc_argv_create(); + if (aa == NULL) + return -1; + + r = rtems_bsd_rc_conf_find(rc_conf, "pf_enable", aa); + if (r == 0) { + if (aa->argc == 2 && strcasecmp("YES", aa->argv[1]) == 0) { + char* rules = firewall_pf_rules_default; + int argc = 0; + const char** argv = NULL; + + if (erroroccured == 0) { + r = rtems_bsd_rc_conf_find(rc_conf, "pf_rules", aa); + if (r == 0) { + if (aa->argc == 2) { + rules = strdup(aa->argv[1]); + if (rules == NULL) { + fprintf(stderr, + "error: pf: Could not create rule file string: %s\n", + strerror(errno)); + erroroccured = -1; + } + } else { + fprintf(stderr, + "error: pf: Syntax error in pf_rules directive.\n"); + erroroccured = -1; + } + } + } + + if (erroroccured == 0) { + r = rtems_bsd_rc_conf_find(rc_conf, "pf_flags", aa); + if (r == 0) { + argc = aa->argc; + argv = aa->argv; + } + } + + /* + * FreeBSD does the following on pf_start() in /etc/rc.d/pf: + * ---- + * check_startmsgs && echo -n 'Enabling pf' + * $pf_program -F all > /dev/null 2>&1 + * $pf_program -f "$pf_rules" $pf_flags + * if ! $pf_program -s info | grep -q "Enabled" ; then + * $pf_program -eq + * fi + * check_startmsgs && echo '.' + * ---- + * We should do roughly the same + */ + if (erroroccured == 0) { + r = firewall_pf_flush(rc_conf, "all"); + if(r != EXIT_SUCCESS) { + fprintf(stderr, + "error: pf: Could not flush.\n"); + erroroccured = -1; + } + } + + if (erroroccured == 0) { + r = firewall_pf_load_rules_with_extra_args(rc_conf, rules, argc, argv); + if (r != EXIT_SUCCESS) { + fprintf(stderr, + "error: pf: Could not load rules.\n"); + erroroccured = -1; + } + } + + if (erroroccured == 0) { + r = firewall_pf_enable(rc_conf); + if (r != EXIT_SUCCESS) { + fprintf(stderr, + "error: pf: Could not enable firewall.\n"); + erroroccured = -1; + } + } + + if (rules != firewall_pf_rules_default && rules != NULL) { + free(rules); + } + } + } + + rtems_bsd_rc_conf_argc_argv_destroy(aa); + + return erroroccured; +} + +void +rc_conf_firewall_pf_init(void* arg) +{ + int r; + r = rtems_bsd_rc_conf_service_add("pf", + "after:network;before:telnetd;", + firewall_pf_service); + if (r < 0) + fprintf(stderr, + "error: pf service add failed: %s\n", strerror(errno)); +} diff --git a/testsuite/rcconf02/test_main.c b/testsuite/rcconf02/test_main.c index 735e5554..498621f2 100644 --- a/testsuite/rcconf02/test_main.c +++ b/testsuite/rcconf02/test_main.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -122,7 +123,39 @@ static const char* rc_conf_text = \ "\n" \ "ftpd_enable=\"YES\"\n" \ "ftpd_options=\"-v -p 21 -C 10 -P 150 -L -I 10 -R /\"\n" \ - "n"; + "\n" \ + "pf_enable=\"YES\"\n" \ + "pf_rules=\"/etc/mypf.conf\"\n" \ + "pf_flags=\"-q -z\"\n" \ + "\n"; + +static const char* pf_conf_text = "pass all\n"; +static const char* pf_os_text = "# empty\n"; + +static void +prepare_files(void) +{ + size_t len; + size_t written; + int fd; + int rv; + + len = strlen(pf_conf_text); + fd = open("/etc/mypf.conf", O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd != -1); + written = write(fd, pf_conf_text, len); + assert(written == len); + rv = close(fd); + assert(rv == 0); + + len = strlen(pf_os_text); + fd = open("/etc/pf.os", O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd != -1); + written = write(fd, pf_os_text, len); + assert(written == len); + rv = close(fd); + assert(rv == 0); +} static void test_rc_conf_script(void) @@ -133,6 +166,9 @@ test_rc_conf_script(void) const char* netstat_args[] = { "netstat", "-rn", NULL }; + const char* pfctl_args[] = { + "pfctl", "-s", "rules", NULL + }; printf("--------------- rc.conf -----------------\n"); printf(rc_conf_text); @@ -144,6 +180,8 @@ test_rc_conf_script(void) rtems_bsd_command_ifconfig(1, (char**) ifconfg_args); printf("-------------- NETSTAT ------------------\n"); rtems_bsd_command_netstat(2, (char**) netstat_args); + printf("-------------- PFCTL --------------------\n"); + rtems_bsd_command_pfctl(RTEMS_BSD_ARGC(pfctl_args), (char **) pfctl_args); printf("-----------------------------------------\n"); } @@ -181,6 +219,7 @@ shell(void) static void test_main(void) { + prepare_files(); test_rc_conf_script(); shell(); exit(0); @@ -201,6 +240,7 @@ test_main(void) &rtems_shell_NETSTAT_Command, \ &rtems_shell_IFCONFIG_Command, \ &rtems_shell_TCPDUMP_Command, \ + &rtems_shell_PFCTL_Command, \ &rtems_shell_SYSCTL_Command #define CONFIGURE_SHELL_COMMAND_CPUUSE @@ -229,6 +269,7 @@ test_main(void) #define RTEMS_BSD_CONFIG_SERVICE_TELNETD #define RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE (16 * 1024) #define RTEMS_BSD_CONFIG_SERVICE_FTPD +#define RTEMS_BSD_CONFIG_FIREWALL_PF #define CONFIGURE_MAXIMUM_DRIVERS 32 -- cgit v1.2.3