diff options
author | lns <matzeton@googlemail.com> | 2018-06-07 17:59:50 +0200 |
---|---|---|
committer | lns <matzeton@googlemail.com> | 2018-06-07 17:59:50 +0200 |
commit | 18914495e90639c12eeec0805bbc74c82700e205 (patch) | |
tree | e60315e8ee57c86951e6e2ebfa687d42d675a3ce | |
parent | 019e585ada9b6c1eeeaeee6f29ce312e7e1f993f (diff) |
POTD skeleton #97.
Signed-off-by: lns <matzeton@googlemail.com>
-rw-r--r-- | src/main.c | 258 | ||||
-rw-r--r-- | src/utils.c | 34 | ||||
-rw-r--r-- | src/utils.h | 6 |
3 files changed, 211 insertions, 87 deletions
@@ -19,28 +19,48 @@ #include "forward.h" #include "jail.h" -static void jail_preinit(const char *jail_ports[], jail_ctx *ctx[], - const size_t siz); +static size_t jl_siz = 0; +static jail_ctx *jl_ctx = NULL; +static pid_t jl_pid = -1; + +static size_t prt_siz = 0; +static protocol_ctx *prt_ctx = NULL; + +static size_t rdr_siz = 0; +static redirector_ctx *rdr_ctx = NULL; +static pid_t rdr_pid = -1; + +static void jail_preinit(char jail_hosts[][2][NI_MAXHOST], + char jail_ports[][2][NI_MAXSERV], + jail_ctx *ctx[], const size_t siz); static pid_t jail_init(jail_ctx *ctx[], const size_t siz); -static void ssh_protocol_preinit(const char *ssh_ports[], protocol_ctx *ctx[], - const char *jail_ports[], const size_t siz); +static void ssh_protocol_preinit(char proto_hosts[][2][NI_MAXHOST], + char proto_ports[][2][NI_MAXSERV], + protocol_ctx *ctx[], + const size_t siz); static void ssh_protocol_init(protocol_ctx *ctx[], const size_t siz); -static void rdr_preinit(const char *rdr_ports[], redirector_ctx *ctx[], +static void rdr_preinit(char rdr_hosts[][2][NI_MAXHOST], + char rdr_ports[][2][NI_MAXSERV], + redirector_ctx *ctx[], const size_t siz); static pid_t rdr_init(redirector_ctx *ctx[], const size_t siz); -static int setup_instances(int validate_only); +static size_t validate_hostport_option(opt_name on, int process_forward); +static int process_options(int validate_only); -static void jail_preinit(const char *jail_ports[], jail_ctx *ctx[], - const size_t siz) + +static void jail_preinit(char jail_hosts[][2][NI_MAXHOST], + char jail_ports[][2][NI_MAXSERV], + jail_ctx *ctx[], const size_t siz) { for (size_t i = 0; i < siz; ++i) { - D("Initialising jail service on port %s", jail_ports[i]); + D("Initialising jail service on port %s:%s", + jail_hosts[i][0], jail_ports[i][0]); jail_init_ctx(&ctx[i], MAX_STACKSIZE); - //ctx[i]->newroot = strdup("/home/lns/git/busybox/sysroot"); - ctx[i]->newroot = strdup("/home/toni/git/busybox/_install"); - ABORT_ON_FATAL( jail_setup(ctx[i], "127.0.0.1", jail_ports[i]), + ctx[i]->newroot = strdup("/home/lns/git/busybox/sysroot"); + //ctx[i]->newroot = strdup("/home/toni/git/busybox/_install"); + ABORT_ON_FATAL( jail_setup(ctx[i], jail_hosts[i][0], jail_ports[i][0]), "Jail daemon setup" ); ABORT_ON_FATAL( jail_validate_ctx(ctx[i]), "Jail validation" ); @@ -60,14 +80,18 @@ static pid_t jail_init(jail_ctx *ctx[], const size_t siz) return jail_pid; } -static void ssh_protocol_preinit(const char *ssh_ports[], protocol_ctx *ctx[], - const char *jail_ports[], const size_t siz) +static void ssh_protocol_preinit(char proto_hosts[][2][NI_MAXHOST], + char proto_ports[][2][NI_MAXSERV], + protocol_ctx *ctx[], + const size_t siz) { for (size_t i = 0; i < siz; ++i) { ABORT_ON_FATAL( proto_init_ctx(&ctx[i], ssh_init_cb), "SSH Protocol init" ); - ABORT_ON_FATAL( proto_setup(ctx[i], "127.0.0.1", ssh_ports[i], - "127.0.0.1", jail_ports[i]), "SSH Protocol setup" ); + ABORT_ON_FATAL( proto_setup(ctx[i], + proto_hosts[i][0], proto_ports[i][0], + proto_hosts[i][1], proto_ports[i][1]), + "SSH Protocol setup" ); ABORT_ON_FATAL( proto_validate_ctx(ctx[i]), "SSH validation" ); } @@ -81,16 +105,22 @@ static void ssh_protocol_init(protocol_ctx *ctx[], const size_t siz) } } -static void rdr_preinit(const char *rdr_ports[], redirector_ctx *ctx[], +static void rdr_preinit(char rdr_hosts[][2][NI_MAXHOST], + char rdr_ports[][2][NI_MAXSERV], + redirector_ctx *ctx[], const size_t siz) { for (size_t i = 0; i < siz; ++i) { - D("Initialising redirector service on port %s", rdr_ports[i]); + D("Initialising redirector service on %s:%s to %s:%s", + rdr_hosts[i][0], rdr_ports[i][0], + rdr_hosts[i][1], rdr_ports[i][1]); ABORT_ON_FATAL( redirector_init_ctx(&ctx[i]), "Redirector init" ); - ABORT_ON_FATAL( redirector_setup(ctx[i], NULL, rdr_ports[i], - "127.0.0.1", "22222"), "Redirector setup" ); + ABORT_ON_FATAL( redirector_setup(ctx[i], + rdr_hosts[i][0], rdr_ports[i][0], + rdr_hosts[i][1], rdr_ports[i][1]), + "Redirector setup" ); ABORT_ON_FATAL( redirector_validate_ctx(ctx[i]), "Redirector validation" ); } @@ -112,42 +142,134 @@ static pid_t rdr_init(redirector_ctx *ctx[], const size_t siz) return rdr_pid; } -static int setup_instances(int validate_only) +static size_t validate_hostport_option(opt_name on, int process_forward) { - char *value = NULL; + char *value; struct opt_list *ol = NULL; - char *hostport[2]; - size_t hostport_siz[2]; - size_t siz; + size_t rc = 0, siz, off; + char hbuf[2][NI_MAXHOST]; + char sbuf[2][NI_MAXSERV]; + + if (!getopt_used(on)) + return 0; + + while ((value = getopt_strlist(on, &ol))) { + siz = parse_hostport_str(value, hbuf[0], sbuf[0]); + if (!siz) { + fprintf(stderr, "%s: invalid listen host:port " + "combination: '%s'\n", + arg0, value); + return 0; + } - if (getopt_used(OPT_REDIRECT)) - while ((value = getopt_strlist(OPT_REDIRECT, &ol))) { - siz = parse_hostport(value, hostport, hostport_siz); + off = siz; + siz = parse_hostport_str(value + off, hbuf[1], sbuf[1]); + if (process_forward) { if (!siz) { - fprintf(stderr, "%s: invalid redtirector host:port combination: '%s'\n", - arg0, value); - return 1; + fprintf(stderr, "%s: invalid forward host:port " + "combination: '%s'\n", + arg0, value + off); + return 0; } - } - if (getopt_used(OPT_PROTOCOL)) - while ((value = getopt_strlist(OPT_PROTOCOL, &ol))) { - siz = parse_hostport(value, hostport, hostport_siz); - if (!siz) { - fprintf(stderr, "%s: invalid protocol host:port combination: '%s'\n", - arg0, value); - return 1; + if (*(value + off + siz)) { + fprintf(stderr, "%s: garbage host:port string '%s'\n", + arg0, value + off + siz); + } + } else { + if (siz) { + fprintf(stderr, "%s: got a forward host:port string when none" + " is allowed '%s'\n", arg0, value + off); + return 0; + } + if (*(value + off + siz)) { + fprintf(stderr, "%s: got an invalid forward host:port string " + "when none" + " is allowed '%s'\n", arg0, value + off); + return 0; } + + off = 0; } - if (getopt_used(OPT_JAIL)) + + rc++; + } + + return rc; +} + +static int process_options(int validate_only) +{ + char *value = NULL; + struct opt_list *ol; + size_t i, siz; + + siz = validate_hostport_option(OPT_JAIL, 0); + if (siz && !validate_only) { + jl_siz = siz; + jl_ctx = (jail_ctx *) calloc(siz, sizeof *jl_ctx); + assert(jl_ctx); + + ol = NULL; + i = 0; + char hosts[jl_siz][2][NI_MAXHOST]; + char ports[jl_siz][2][NI_MAXSERV]; while ((value = getopt_strlist(OPT_JAIL, &ol))) { - siz = parse_hostport(value, hostport, hostport_siz); - if (!siz) { - fprintf(stderr, "%s: invalid jail host:port combination: '%s'\n", - arg0, value); - return 1; - } + memset(hosts[i], 0, sizeof hosts[i]); + memset(ports[i], 0, sizeof ports[i]); + + siz = parse_hostport_str(value, hosts[i][0], ports[i][0]); + i++; + } + + jail_preinit(hosts, ports, &jl_ctx, jl_siz); + jl_pid = jail_init(&jl_ctx, jl_siz); + } + + siz = validate_hostport_option(OPT_PROTOCOL, 1); + if (siz && !validate_only) { + prt_siz = siz; + prt_ctx = (protocol_ctx *) calloc(siz, sizeof *prt_ctx); + assert(prt_ctx); + + ol = NULL; + i = 0; + char hosts[prt_siz][2][NI_MAXHOST]; + char ports[prt_siz][2][NI_MAXSERV]; + while ((value = getopt_strlist(OPT_PROTOCOL, &ol))) { + memset(hosts[i], 0, sizeof hosts[i]); + memset(ports[i], 0, sizeof ports[i]); + + siz = parse_hostport_str(value, hosts[i][0], ports[i][0]); + siz = parse_hostport_str(value + siz, hosts[i][1], ports[i][1]); + i++; + } + + ssh_protocol_preinit(hosts, ports, &prt_ctx, prt_siz); + ssh_protocol_init(&prt_ctx, prt_siz); + } + + siz = validate_hostport_option(OPT_REDIRECT, 1); + if (siz && !validate_only) { + rdr_siz = siz; + rdr_ctx = (redirector_ctx *) calloc(siz, sizeof *rdr_ctx); + assert(rdr_ctx); + + ol = NULL; + i = 0; + char hosts[rdr_siz][2][NI_MAXHOST]; + char ports[rdr_siz][2][NI_MAXSERV]; + while ((value = getopt_strlist(OPT_REDIRECT, &ol))) { + memset(hosts[i], 0, sizeof hosts[i]); + memset(ports[i], 0, sizeof ports[i]); + + siz = parse_hostport_str(value, hosts[i][0], ports[i][0]); + siz = parse_hostport_str(value + siz, hosts[i][1], ports[i][1]); + i++; } - /* TODO: setup redirect/protocol/jail instances if validate_only == 0 */ + + rdr_preinit(hosts, ports, &rdr_ctx, rdr_siz); + rdr_init(&rdr_ctx, rdr_siz); + } return 0; } @@ -155,17 +277,8 @@ static int setup_instances(int validate_only) int main(int argc, char *argv[]) { char *value; - const size_t rdr_siz = 3; - const size_t proto_siz = 2; - const size_t jail_siz = 2; - const char *rdr_ports[rdr_siz]; - const char *proto_ports[proto_siz]; - const char *jail_ports[jail_siz]; - redirector_ctx *rdr[rdr_siz]; - protocol_ctx *ssh_proto[proto_siz]; - jail_ctx *jail[jail_siz]; int proc_status; - pid_t daemon_pid, rdr_pid, jail_pid, child_pid; + pid_t daemon_pid, child_pid; pseccomp_ctx *psc = NULL; (void) argc; @@ -177,7 +290,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if (setup_instances(1)) { + if (process_options(1)) { fprintf(stderr, "%s: invalid config detected\n", argv[0]); exit(EXIT_FAILURE); } @@ -208,7 +321,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); #ifdef HAVE_CONFIG_H - N("%s (C) 2018 Toni Uhlig (%s)", PACKAGE_STRING, PACKAGE_BUGREPORT); + N("%s (C) 2018 Toni Uhlig <%s>", PACKAGE_STRING, PACKAGE_BUGREPORT); #endif if (geteuid() != 0) { @@ -234,33 +347,16 @@ int main(int argc, char *argv[]) ABORT_ON_FATAL( set_master_sighandler(), "Master sighandler" ); - memset(jail, 0, sizeof(jail)); - jail_ports[0] = "33333"; - jail_ports[1] = "33334"; - jail_preinit(jail_ports, jail, SIZEOF(jail_ports)); - jail_pid = jail_init(jail, SIZEOF(jail_ports)); - - memset(ssh_proto, 0, sizeof(proto_ports)); - proto_ports[0] = "22222"; - proto_ports[1] = "22223"; - assert(SIZEOF(proto_ports) == SIZEOF(jail_ports)); - ssh_protocol_preinit(proto_ports, ssh_proto, jail_ports, proto_siz); - ssh_protocol_init(ssh_proto, proto_siz); - - memset(rdr, 0, sizeof(rdr)); - rdr_ports[0] = "2222"; - rdr_ports[1] = "2223"; - rdr_ports[2] = "22050"; - rdr_preinit(rdr_ports, rdr, SIZEOF(rdr_ports)); - rdr_pid = rdr_init(rdr, SIZEOF(rdr_ports)); + ABORT_ON_FATAL( process_options(0), + "Setup redirect/protocol/jail instances"); while (1) { child_pid = wait(&proc_status); - if (child_pid == jail_pid || + if (child_pid == jl_pid || child_pid == rdr_pid) { E2("%s daemon with pid %d terminated, exiting", - (child_pid == jail_pid ? "Jail" : "Redirector"), - (child_pid == jail_pid ? jail_pid : rdr_pid)); + (child_pid == jl_pid ? "Jail" : "Redirector"), + (child_pid == jl_pid ? jl_pid : rdr_pid)); kill(getpid(), SIGTERM); break; } else W2("Process with pid %d terminated", child_pid); diff --git a/src/utils.c b/src/utils.c index 6bf281f..7bbdc1e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -695,13 +695,13 @@ void escape_ascii_string(const char ascii[], size_t siz, char **dest, size_t *ne (*dest)[ns] = 0; } -size_t parse_hostport(char *str, char *result[2], +size_t parse_hostport(const char *str, const char *result[2], size_t siz[2]) { size_t i; - char *hostend = strchr(str, ':'); - char *portend; - char sep[] = ": \t\n\0"; + const char *hostend = strchr(str, ':'); + const char *portend; + const char sep[] = ": \t\n\0"; result[0] = NULL; result[1] = NULL; @@ -724,5 +724,29 @@ size_t parse_hostport(char *str, char *result[2], siz[0] = hostend - str - 1; siz[1] = portend - hostend; - return siz[0] + siz[1] + 1; + return siz[0] + siz[1] + 1 + (*portend != 0 ? 1 : 0); +} + +size_t parse_hostport_str(const char *str, char hbuf[NI_MAXHOST], + char sbuf[NI_MAXSERV]) +{ + const char *hostport[2]; + size_t hostport_siz[2]; + size_t siz; + + siz = parse_hostport(str, hostport, hostport_siz); + if (!siz) + return 0; + if (snprintf(hbuf, NI_MAXHOST, "%.*s", (int) hostport_siz[0], + hostport[0]) <= 0) + { + return 0; + } + if (snprintf(sbuf, NI_MAXSERV, "%.*s", (int) hostport_siz[1], + hostport[1]) <= 0) + { + return 0; + } + + return siz; } diff --git a/src/utils.h b/src/utils.h index b4baa70..8e7adc9 100644 --- a/src/utils.h +++ b/src/utils.h @@ -3,6 +3,7 @@ #include <stdlib.h> #include <sys/types.h> +#include <netdb.h> #ifndef SIZEOF #define SIZEOF(arr) (sizeof(arr)/sizeof(arr[0])) @@ -63,7 +64,10 @@ int update_setgroups_self(int allow); void escape_ascii_string(const char ascii[], size_t siz, char **dest, size_t *newsiz); -size_t parse_hostport(char *str, char *result[2], +size_t parse_hostport(const char *str, const char *result[2], size_t siz[2]); +size_t parse_hostport_str(const char *str, char hbuf[NI_MAXHOST], + char sbuf[NI_MAXSERV]); + #endif |