diff options
Diffstat (limited to 'service/src')
| -rw-r--r-- | service/src/.gitignore | 1 | ||||
| -rw-r--r-- | service/src/Makefile | 15 | ||||
| -rw-r--r-- | service/src/main.c | 168 | ||||
| -rw-r--r-- | service/src/util.c | 59 | ||||
| -rw-r--r-- | service/src/util.h | 4 |
5 files changed, 167 insertions, 80 deletions
diff --git a/service/src/.gitignore b/service/src/.gitignore index 362a687..edaffd1 100644 --- a/service/src/.gitignore +++ b/service/src/.gitignore @@ -2,3 +2,4 @@ stldoctor scans *.o vgcore.* +safe_* diff --git a/service/src/Makefile b/service/src/Makefile index c46988a..d7732b3 100644 --- a/service/src/Makefile +++ b/service/src/Makefile @@ -1,14 +1,21 @@ CFLAGS = -g -I . +# fortify source code +CFLAGS += -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 +LDFLAGS = -Wl,-z,now -Wl,-z,relro + .PHONY: all clean -all: stldoctor +all: build/stldoctor clean: - rm -f stldoctor *.o + rm -rf build + +build: + mkdir build -%.o: %.c %.h +build/%.o: %.c %.h | build $(CC) -c -o $@ $< $(CFLAGS) $(LDLIBS) -stldoctor: main.c stlfile.o util.o +build/stldoctor: build/$(PREFIX)stlfile.o build/$(PREFIX)util.o $(PREFIX)main.c | build $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) diff --git a/service/src/main.c b/service/src/main.c index 3d62fc7..959ef58 100644 --- a/service/src/main.c +++ b/service/src/main.c @@ -6,6 +6,7 @@ #include <fcntl.h> #include <sys/stat.h> #include <time.h> +#include <errno.h> #include "stlfile.h" #include "util.h" @@ -14,30 +15,37 @@ struct command { const char *name; - void (*func)(char *); + void (*func)(const char *); + const char *desc; }; int save_submission(struct parseinfo *info, char *data, int len); -void cat_cmd(char *arg); -void list_cmd(char *arg); -void exit_cmd(char *arg); -void echo_cmd(char *arg); -void submit_cmd(char *arg); -void query_cmd(char *arg); +void cat_cmd(const char *arg); +void help_cmd(const char *arg); +void exit_cmd(const char *arg); +void echo_cmd(const char *arg); +void upload_cmd(const char *arg); +void search_cmd(const char *arg); +void list_cmd(const char *arg); +void auth_cmd(const char *arg); + +void cleanexit(); struct command commands[] = { - { "cat", cat_cmd }, - { "help", list_cmd }, - { "exit", exit_cmd }, - { "echo", echo_cmd }, - { "submit", submit_cmd }, - { "query", query_cmd }, + { "cat", cat_cmd, "Cat cmd go prrrrr." }, + { "help", help_cmd, "You already know what this does." }, + { "exit", exit_cmd, "Closes the session." }, + { "echo", echo_cmd, "Repeat after me!" }, + { "upload", upload_cmd, "Upload an STL file to analyze." }, + { "search", search_cmd, "Search for an STL file by model name." }, + { "list", list_cmd, "List your uploaded files." }, + { "auth", auth_cmd, "Login to upload files to a private dir." } }; struct parseinfo cached; -const char *resultdir; -int echo = 0; +char *resultdir; +int echo = 0, loggedin = 0; int save_submission(struct parseinfo *info, char *stldata, int stlsize) @@ -46,7 +54,10 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) FILE *f = NULL; char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; - dirpath = aprintf("%s/%s-%i", resultdir, info->hash, time(NULL)); + if (loggedin) + dirpath = aprintf("%s/.%s-%i", resultdir, info->hash, time(NULL)); + else + dirpath = aprintf("%s/%s-%i", resultdir, info->hash, time(NULL)); if (mkdir(dirpath, S_IRWXU | S_IRWXG | S_IRWXO)) goto fail; modelpath = aprintf("%s/%s", dirpath, "model"); @@ -82,7 +93,7 @@ fail: } void -cat_cmd(char *arg) +cat_cmd(const char *arg) { if (arg && !strncmp(arg, "flag", 4)) dump("msgs/cat_flag"); @@ -91,10 +102,19 @@ cat_cmd(char *arg) } void -list_cmd(char *arg) +help_cmd(const char *arg) { int i; + if (arg) { + for (i = 0; i < ARRSIZE(commands); i++) { + if (!strcmp(commands[i].name, arg)) { + printf("%s\n", commands[i].desc); + return; + } + } + } + printf("Available commands:\n"); for (i = 0; i < ARRSIZE(commands); i++) printf("%s%s", i ? " " : "", commands[i].name); @@ -102,49 +122,53 @@ list_cmd(char *arg) } void -exit_cmd(char *arg) +exit_cmd(const char *arg) { exit(0); } void -echo_cmd(char *arg) +echo_cmd(const char *arg) { echo ^= 1; printf("Echo is %s\n", echo ? "enabled" : "disabled"); } void -submit_cmd(char *arg) +upload_cmd(const char *arg) { const char *bufp; char *end, *contents; size_t len; - bufp = ask("> How large is your file? "); + bufp = ask("How large is your file? "); len = strtoul(bufp, &end, 10); if (len <= 0 || len >= MAXFILESIZE || *end) { fprintf(stderr, "Invalid file length!\n"); return; } - printf("> Ok! Im listening..\n"); + printf("Ok! Im listening..\n"); contents = checkp(malloc(len + 1)); - fread(contents, 1, len, stdin); + if (fread(contents, 1, len, stdin) != len) { + fprintf(stderr, "Hm, I'm missing some bytes.. try again!\n"); + goto cleanup; + } contents[len] = '\0'; if ((cached.valid = parse_file(&cached, contents, len))) { if (save_submission(&cached, contents, len) != OK) fprintf(stderr, "Failed to save your submission!\n"); else - printf("> Your file was saved with ID %s!\n", cached.hash); + printf("Your file was saved with ID %s!\n", cached.hash); } +cleanup: free(contents); } void -query_cmd(char *arg) +search_cmd(const char *arg) { char *end, *scandir = NULL, *infopath = NULL, *modelpath = NULL; const char *hash; @@ -161,7 +185,7 @@ query_cmd(char *arg) } hash = cached.hash; } else { - hash = mhash(ask("> Model name: "), -1); + hash = mhash(arg ? arg : ask("Model name: "), -1); } if (!(d = opendir(resultdir))) return; @@ -178,7 +202,7 @@ query_cmd(char *arg) fprintf(stderr, "Sorry, couldnt find a matching scan result!\n"); goto cleanup; } else { - which = strtoul(ask("> Which of these results? "), &end, 10); + which = strtoul(ask("Which of these results? "), &end, 10); if (which >= i || which < 0 || *end) { fprintf(stderr, "Invalid index!\n"); goto cleanup; @@ -196,8 +220,9 @@ query_cmd(char *arg) } } + /* file got cleaned up during race condition by background task */ if (!scandir) { - fprintf(stderr, "Unexpected error!\n"); + fprintf(stderr, "Selected result spontaneously combusted!\n"); goto cleanup; } @@ -210,14 +235,14 @@ query_cmd(char *arg) print_info(&cached); - if (strchr(ask("> Download the model? "), 'y')) { + if (strchr(ask("Download the model? "), 'y')) { modelpath = aprintf("%s/%s", scandir, "model"); if (!(f = fopen(modelpath, "r"))) goto cleanup; fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); if (size > MAXFILESIZE) goto cleanup; - printf("> Here you go.. (%liB)\n", size); + printf("Here you go.. (%liB)\n", size); while ((i = getc(f)) != EOF) putc(i, stdout); fclose(f); @@ -233,6 +258,52 @@ cleanup: } void +list_cmd(const char *arg) +{ + DIR *d; + struct dirent *de; + + if (!loggedin) { + fprintf(stderr, "Not logged in!\n"); + return; + } + + if (!(d = opendir(resultdir))) return; + + while ((de = readdir(d))) { + if (*de->d_name == '.' && !strchr(".", de->d_name[1])) { + printf("%s\n", de->d_name); + } + } +} + +void +auth_cmd(const char *arg) +{ + const char *hash; + char *ndir; + + if (loggedin) { + fprintf(stderr, "Already logged in!\n"); + return; + } + + hash = mhash(arg ? arg : ask("Enter a password: "), -1); + ndir = aprintf("%s/.%s", resultdir, hash); + if (mkdir(ndir, S_IRWXU | S_IRWXG | S_IRWXO) && errno != EEXIST) { + fprintf(stderr, "Auth failed!\n"); + return; + } + + printf("Success!\n"); + + free(resultdir); + resultdir = ndir; + loggedin = 1; + cached.valid = 0; +} + +void cleanexit() { printf("see you later!\n"); @@ -242,11 +313,14 @@ cleanexit() int main() { - char linebuf[256], *cp, *arg; - int exit, i; + const char *cmd; + char *cp, *arg; + int exit, i, cmdlen; - if (!(resultdir = getenv("RESULTDIR"))) - resultdir = "scans"; + if (!(resultdir = checkp(strdup(getenv("RESULTDIR"))))) { + fprintf(stderr, "RESULTDIR not defined\n"); + return 1; + } setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); @@ -258,30 +332,24 @@ main() exit = 0; while (!exit) { - memset(linebuf, '\0', sizeof(linebuf)); - - printf("$ "); - exit = !fgets(linebuf, sizeof(linebuf), stdin); - if (exit || !*linebuf) break; - - if (*linebuf == '\n') continue; - if (linebuf[strlen(linebuf) - 1] == '\n') - linebuf[strlen(linebuf) - 1] = '\0'; - - if (echo) printf("%s\n", linebuf); + errno = 0; + cmd = ask("$ "); + if (!*cmd && errno == EBADMSG) break; + if (!*cmd) continue; - cp = strchr(linebuf, ' '); + cp = strchr(cmd, ' '); arg = cp ? cp + 1 : NULL; - if (cp) *cp = 0; + cmdlen = cp ? cp - cmd : strlen(cmd); for (i = 0; i < ARRSIZE(commands); i++) { - if (!strcmp(commands[i].name, linebuf)) { + if (!strncmp(commands[i].name, cmd, cmdlen) + && cmdlen == strlen(commands[i].name)) { commands[i].func(arg); break; } } - if (i == ARRSIZE(commands) && strlen(linebuf) != 0) + if (i == ARRSIZE(commands) && strlen(cmd) != 0) fprintf(stderr, "No such command!\n"); } } diff --git a/service/src/util.c b/service/src/util.c index bf6e872..31a2628 100644 --- a/service/src/util.c +++ b/service/src/util.c @@ -43,45 +43,52 @@ aprintf(const char *fmtstr, ...) } const char* -mhash(const char *filename, int len) +mhash(const char *str, int len) { - static const char *hexalph = "0123456789ABCDEF"; - static char buf[2 * MHASHLEN + 1]; - int i, k; - - if (len == -1) len = strlen(filename); - - for (i = 0; i < MIN(MHASHLEN, len); i++) { - unsigned char v = 0; - for (k = i; k < len; k += MHASHLEN) - v ^= filename[k]; - buf[i*2+0] = hexalph[(v >> 4) & 0x0f]; - buf[i*2+1] = hexalph[(v >> 0) & 0x0f]; - } + static char buf[MHASHLEN + 1]; + int i, k, v; + char c, *bp; - if (i == 0) { - memset(buf, '0', MHASHLEN); - } else if (i < MHASHLEN) { - for (k = 0; k < MHASHLEN; k++) - buf[k] = buf[k % i]; - } + /* VULN #2: BUFFER OVERFLOW */ + /* see documentation/README.md for more details */ + + if (len == -1) len = strlen(str) + 1; - buf[MHASHLEN] = '\0'; + for (v = 0, i = 0; i < len; i++) v += str[i]; + srand(v); + + for (bp = buf, i = 0; i < MHASHLEN / 2; i++) + bp += sprintf(bp, "%02x", str[i % len] ^ (rand() % 256)); return buf; } +int +checkalph(const char *str, const char *alph) +{ + int i; + + for (i = 0; i < strlen(str); i++) + if (!strchr(alph, str[i])) return 0; + + return 1; +} + void freadstr(FILE *f, char **dst) { - size_t start, len; + size_t start, len, tmp; + char c; + + /* VULN #1: BAD CAST */ + /* see documentation/README.md for more details */ start = ftell(f); - for (len = 0; fgetc(f) > 0; len++); + for (len = 0; (c = fgetc(f)) != EOF && c; len++); fseek(f, start, SEEK_SET); *dst = checkp(calloc(1, len + 1)); - fread(*dst, len, 1, f); + tmp = fread(*dst, len, 1, f); fgetc(f); } @@ -111,6 +118,8 @@ ask(const char *fmtstr, ...) if (echo) printf("%s\n", linebuf); } + if (fail) errno = EBADMSG; + return fail ? "" : linebuf; } @@ -123,7 +132,7 @@ dump(const char *filename) if (!(f = fopen(filename, "r"))) return; - while ((nb = fread(buf, 1, sizeof(buf), f))) + while ((nb = fread(buf, 1, sizeof(buf) - 1, f))) printf("%.*s\n", nb, buf); fclose(f); diff --git a/service/src/util.h b/service/src/util.h index 3496461..eaef14f 100644 --- a/service/src/util.h +++ b/service/src/util.h @@ -5,6 +5,7 @@ #include <stdarg.h> #include <string.h> #include <stdio.h> +#include <errno.h> #define ARRSIZE(x) (sizeof(x)/sizeof((x)[0])) #define MIN(x,y) ((x) > (y) ? (y) : (x)) @@ -12,7 +13,7 @@ #define NULLFREE(p) do { free(p); p = NULL; } while (0) -#define MHASHLEN 32 +#define MHASHLEN 40 enum { FAIL = 0, OK = 1 }; @@ -21,6 +22,7 @@ void* die(const char *fmtstr, ...); char* aprintf(const char *fmtstr, ...); const char* mhash(const char *filename, int len); +int checkalph(const char *str, const char *alph); void freadstr(FILE *f, char **dst); void fputstr(FILE *f, char *s); |
