From 6b110ddc155bbd5c0550847a632b3c5f30825c69 Mon Sep 17 00:00:00 2001 From: Oleg Borodin Date: Tue, 15 Aug 2023 08:35:06 +0200 Subject: [PATCH] at work --- Makefile | 2 +- Makefile.am | 2 +- Makefile.in | 2 +- README.md | 16 ++++ clparser.c | 19 ++++- clparser.h | 5 +- clparser_test.c | 4 +- cworker.c | 41 ++++++++-- cworker.conf | 2 + cworker.h | 3 +- main.c | 4 +- works/exec01.c | 187 +++++++++++++++++++++++++++++++++++++++++++ works/exec02.c | 121 ++++++++++++++++++++++++++++ works/newroot/foo.go | 21 +++++ 14 files changed, 411 insertions(+), 18 deletions(-) create mode 100644 README.md create mode 100644 works/exec01.c create mode 100644 works/exec02.c create mode 100644 works/newroot/foo.go diff --git a/Makefile b/Makefile index cf71335..94de9e0 100644 --- a/Makefile +++ b/Makefile @@ -873,7 +873,7 @@ uninstall-am: uninstall-sbinPROGRAMS $(CC) -I. -pthread $(CPPFLAGS) $(CFLAGS) -c -o $@ $< run: $(sbin_PROGRAMS) - ./cworker + ./cworker --port=9002 test: $(bin_TESTS) @for test in $(bin_TESTS); do \ diff --git a/Makefile.am b/Makefile.am index de1042f..62b5416 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,7 @@ common_SOURCES = \ rcache.h run: $(sbin_PROGRAMS) - ./cworker + ./cworker --port=9002 if HAVE_VALGRIND VALGRIND_OPT = --tool=memcheck diff --git a/Makefile.in b/Makefile.in index f73bd5a..e1073f9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -873,7 +873,7 @@ uninstall-am: uninstall-sbinPROGRAMS $(CC) -I. -pthread $(CPPFLAGS) $(CFLAGS) -c -o $@ $< run: $(sbin_PROGRAMS) - ./cworker + ./cworker --port=9002 test: $(bin_TESTS) @for test in $(bin_TESTS); do \ diff --git a/README.md b/README.md new file mode 100644 index 0000000..dfefc49 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +#cworker mini framework + +Минималисткий набор для создания сетевого или локального сервиса +с использованием только C (взамен ранее написанного и утерянного). + +Цель: создание системных сервисов + +В наличии: +* cflexer/cfparser - разбор конфигурационого файла +* cllexer/clparser - разбор опций коммандной строки +* jlexer/jparser - разбор json описания (пока только key-value) +* rcache - буферизованное чтение из открытого дескриптора + +* cworker - каркас сетевого сервиса + +В разработке. diff --git a/clparser.c b/clparser.c index bb000b9..45f5d51 100644 --- a/clparser.c +++ b/clparser.c @@ -7,7 +7,7 @@ #include #include - +#include #include #define INIT_BSIZE 64 @@ -155,19 +155,32 @@ int clparser_parse(clparser_t * parser, char** argv, int argc) { for (int i = 0; i < parser->bindsize; i++) { if (strcmp(parser->bindarr[i].key, key) == 0) { switch (parser->bindarr[i].type) { - case CLTYPE_INT:{ + case CLVALTYPE_INT:{ char* eptr = NULL; *(int *)(parser->bindarr[i].ref) = (int)strtol(val, &eptr, 10); free(key); free(val); break; } - case CLTYPE_STR:{ + case CLVALTYPE_STR:{ *(char **)(parser->bindarr[i].ref) = strcopy(val); free(key); free(val); break; } + case CLVALTYPE_BOOL:{ + *(bool*)(parser->bindarr[i].ref) = false; + if (strcmp(val, "true") == 0) { + *(bool*)(parser->bindarr[i].ref) = true; + } else if (strcmp(val, "false") == 0) { + *(bool*)(parser->bindarr[i].ref) = false; + } else { + log_error("wrong boolean key value: %s = %s", key, val); + } + free(key); + free(val); + break; + } } } } diff --git a/clparser.h b/clparser.h index fbd098c..4446f8e 100644 --- a/clparser.h +++ b/clparser.h @@ -19,8 +19,9 @@ typedef struct { int bindsize; } clparser_t; -#define CLTYPE_INT 1 -#define CLTYPE_STR 2 +#define CLVALTYPE_INT 1 +#define CLVALTYPE_STR 2 +#define CLVALTYPE_BOOL 3 void clparser_init(clparser_t* parser, cllexer_t* lexer); void clparser_bind(clparser_t* parser, int type, char* key, void* ref); diff --git a/clparser_test.c b/clparser_test.c index dad62d5..acba7aa 100644 --- a/clparser_test.c +++ b/clparser_test.c @@ -28,8 +28,8 @@ int main(void) { int id = 0; char* name = ""; - clparser_bind(&parser, CLTYPE_INT, "id", (void *)&id); - clparser_bind(&parser, CLTYPE_STR, "name", (void *)&name); + clparser_bind(&parser, CLVALTYPE_INT, "id", (void *)&id); + clparser_bind(&parser, CLVALTYPE_STR, "name", (void *)&name); if (clparser_parse(&parser, &argv[1], argc - 1) < 0) { printf("parse args error\n"); diff --git a/cworker.c b/cworker.c index 471d3b2..b75e849 100644 --- a/cworker.c +++ b/cworker.c @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include #include @@ -31,12 +33,12 @@ int cworker_readconf(cworker_t* worker) { cflexer_init(&lexer, &cache); cfparser_init(&parser, &lexer); - if (cfparser_parse(&parser)) { - log_error("parse args error\n"); + if (cfparser_parse(&parser) < 0) { + log_error("parse config error\n"); return -1; } - cfparser_bind(&parser, CFVALTYPE_STR, "port", (void *)&(worker->port)); + cfparser_bind(&parser, CFVALTYPE_INT, "port", (void *)&(worker->port)); cfparser_destroy(&parser); cflexer_destroy(&lexer); @@ -45,16 +47,45 @@ int cworker_readconf(cworker_t* worker) { return 0; } -int cworker_init(cworker_t* worker) { + +int cworker_readopts(cworker_t* worker, char** argv, int argc) { + log_debug("reading options"); + + cllexer_t lexer; + clparser_t parser; + + cllexer_init(&lexer); + clparser_init(&parser, &lexer); + + clparser_bind(&parser, CLVALTYPE_INT, "port", (void *)&(worker->port)); + + if (clparser_parse(&parser, &argv[1], argc - 1) < 0) { + log_error("parse args error\n"); + return -1; + } + + return 0; +} + +const int64_t default_port = 9701; + +int cworker_init(cworker_t* worker, char** argv, int argc) { log_debug("init service"); - worker->port = 9701; + worker->port = default_port; if (cworker_readconf(worker) < 0) { log_error("reading config error\n"); return -1; } + if (cworker_readopts(worker, argv, argc) < 0) { + log_error("reading config error\n"); + return -1; + } + + log_debug("port: %d", worker->port); + return 0; } diff --git a/cworker.conf b/cworker.conf index e69de29..e5fd76a 100644 --- a/cworker.conf +++ b/cworker.conf @@ -0,0 +1,2 @@ + +port = 9001 # listen port diff --git a/cworker.h b/cworker.h index 524e32e..306a478 100644 --- a/cworker.h +++ b/cworker.h @@ -8,7 +8,8 @@ typedef struct { int64_t port; } cworker_t; -int cworker_init(cworker_t* worker); +int cworker_init(cworker_t* worker, char** argv, int argc); + int cworker_detach(cworker_t* worker); int cworker_configure(cworker_t* worker); int cworker_build(cworker_t* worker); diff --git a/main.c b/main.c index 7f5bcef..b571acc 100644 --- a/main.c +++ b/main.c @@ -13,7 +13,7 @@ int main(int argc, char **argv) { cworker_t worker; - if (cworker_init(&worker) < 0) { + if (cworker_init(&worker, argv, argc) < 0) { log_error("cannot init service"); return 1; } @@ -29,7 +29,7 @@ int main(int argc, char **argv) { log_error("cannot build service"); return 1; } - if (cworker_build(&worker) < 0) { + if (cworker_run(&worker) < 0) { log_error("cannot run service"); return 1; } diff --git a/works/exec01.c b/works/exec01.c new file mode 100644 index 0000000..74991cb --- /dev/null +++ b/works/exec01.c @@ -0,0 +1,187 @@ +/* + * + * Copyright 2023 Oleg Borodin + * + */ + + +#include +#include +#include + + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//#include +//#include +//#include + +//#include +//#include +//#include +//#include + +#include + + +char* _gethostname(void) { + size_t len; + char* res = NULL; + char* mibstr = "kern.hostname"; + sysctlbyname(mibstr, NULL, &len, NULL, 0); + res = malloc(len); + sysctlbyname(mibstr, res, &len, NULL, 0); + return res; +} + + +int getintsysctl(char* mibname) { + int res = 0; + size_t size = sizeof(int); + sysctlbyname(mibname, &res, &size, NULL, 0); + return res; +} + +int setintsysctl(char* mibname, int val) { + int res = 0; + sysctlbyname(mibname, NULL, NULL, &val, sizeof(int)); + return res; +} + +int run() { + + pid_t childpid; + + int pstdout[2]; + if (pipe(pstdout) < 0) { + return -errno; + } + int pstderr[2]; + if (pipe(pstderr) < 0) { + return -errno; + } + + //if (chroot("./newroot/") != 0) { + //printf("child chroot error\n"); + //return 0; + //} + + if((childpid = fork()) < 0) { + return -errno; + } + + if (childpid == 0) { + /* child */ + printf("#1 child %d\n", getpid()); + + setintsysctl("security.jail.set_hostname_allowed", 0); + setintsysctl("security.jail.set_hostname_allowed", 0); + setintsysctl("security.jail.sysvipc_allowed", 0); + setintsysctl("security.jail.allow_raw_sockets", 0); + setintsysctl("security.jail.chflags_allowed", 0); + setintsysctl("security.jail.mount_allowed", 0); + setintsysctl("security.jail.socket_unixiproute_only", 0); + + close(pstdout[0]); + close(pstderr[0]); + + dup2(pstdout[1], STDOUT_FILENO); + dup2(pstderr[1], STDERR_FILENO); + + printf("#2 child %d\n", getpid()); + + //if (chroot("./newroot/") != 0) { + // printf("child chroot error\n"); + // return 0; + //} + + //char cmd[] = "./newroot/foo"; + //char cmd[] = "/bin/ls"; + //char *const params[] = { cmd, NULL}; + //if (execv(cmd, params) < 0) { + // printf("child exec error\n"); + // return 0; + //}; + + struct in_addr inaddr; + inet_pton(AF_INET, "192.168.52.7", &inaddr); + + struct jail j = { + .version = JAIL_API_VERSION, + .path = "./newroot", + .hostname = "localhost", + .jailname = "test", + .ip4s = 1, + .ip6s = 0, + .ip4 = &inaddr, + .ip6 = NULL + }; + + int id = jail(&j); + if (id < 0) { + printf("cannon jail process, error: %s\n", strerror(errno)); + exit(1); + } + + printf("jailed = %d\n", getintsysctl("security.jail.jailed")); + printf("jid = %d\n", id); + + //char* newhostname = "foohost"; + // if (sethostname(newhostname, strlen(newhostname)) < 0) { + // printf("hostname don't set, error: %s\n", strerror(errno)); + //} + + char hostname[NAME_MAX]; + gethostname(hostname, NAME_MAX); + printf("host = %s\n", hostname); + + //lsif(); + + setgid(1000); + setuid(1000); + char* cmd = "./foo"; + execl(cmd, cmd, NULL); + + } else { + /* parent */ + printf("parent %d\n", getpid()); + close(pstdout[1]); + close(pstderr[1]); + + char buffer[16]; + int n = 0; + while ((n = read(pstdout[0], buffer, sizeof(buffer) - 1)) != 0) { + buffer[n] = '\0'; + printf("%s", buffer); + } + } + + int status = 0; + waitpid(childpid, &status, 0); + + return 0; +} + + +int main(int argc, char **argv) { + + if (run() < 0) { + printf("run error\n"); + return 1; + } + return 0; +} diff --git a/works/exec02.c b/works/exec02.c new file mode 100644 index 0000000..648dbcc --- /dev/null +++ b/works/exec02.c @@ -0,0 +1,121 @@ +/* + * + * Copyright 2023 Oleg Borodin + * + */ + + +#include +#include +#include + + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +//#include +//#include +//#include + +//#include +//#include +//#include +//#include + +#include + + + +int copy(int srcfd, int dstfd) { + char buffer[1024]; + int n = 0; + while ((n = read(srcfd, buffer, sizeof(buffer) - 1)) != 0) { + buffer[n] = '\0'; + write(dstfd, buffer, n); + } + return 0; +} + +int exec() { + + char* cmd = "/foo1"; + char* basepath = "./newroot"; + char* v4addr = "192.168.52.7"; + char* hostname = "localhost"; + char* logpath = "output.log"; + + int logfd; + if ((logfd = open(logpath, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) { + return -errno; + } + + pid_t childpid = 0; + + int stdoutfd[2]; + + if (pipe(stdoutfd) < 0) { + return -errno; + } + + if((childpid = fork()) < 0) { + return -errno; + } + + if (childpid == 0) { + /* child */ + close(stdoutfd[0]); + dup2(stdoutfd[1], STDOUT_FILENO); + dup2(stdoutfd[1], STDERR_FILENO); + + struct in_addr inaddr; + inet_pton(AF_INET, v4addr, &inaddr); + + struct jail j = { + .version = JAIL_API_VERSION, + .path = basepath, + .hostname = hostname, + .jailname = "test", + .ip4s = 1, + .ip6s = 0, + .ip4 = &inaddr, + .ip6 = NULL + }; + int id = 0; + if ((id = jail(&j)) < 0) { + return -1; + } + if (execl(cmd, cmd, NULL) < 0) { + return -1; + } + } else { + /* parent */ + close(stdoutfd[1]); + + if (copy(stdoutfd[0], logfd) < 0) { + return -1; + } + } + return 0; +} + +int main(int argc, char **argv) { + if (exec() < 0) { + return 1; + } + return 0; +} diff --git a/works/newroot/foo.go b/works/newroot/foo.go new file mode 100644 index 0000000..4f7f9ef --- /dev/null +++ b/works/newroot/foo.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "time" + "os" +) + +func main() { + var i int + for { + i++ + time.Sleep(1 * time.Second) + wd, _ := os.Getwd() + fmt.Printf("hello %s\n", wd) + if i > 20 { + goto exit + } + } + exit: +}