commit 1490268ea6ae75e5e9b78861c56dc9b04db903f3
parent 2a8416eaa85af6348fe34859859a7fb39db2003d
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 10 May 2021 17:18:28 +0200
extended query function to load file info, added poc test
Diffstat:
6 files changed, 197 insertions(+), 121 deletions(-)
diff --git a/service/src/printdoc.c b/service/src/printdoc.c
@@ -10,99 +10,51 @@
#include "stlfile.h"
#include "util.h"
+#define MAXFILESIZE 7000
+
struct command {
const char *name;
void (*func)(char *);
};
-void search_cmd(char *arg);
-void submit_cmd(char *arg);
-void list_cmd(char *arg);
+int save_submission(struct parseinfo *info, char *data, int len);
+
void cat_cmd(char *arg);
+void list_cmd(char *arg);
+void submit_cmd(char *arg);
+void query_cmd(char *arg);
struct command commands[] = {
- { "submit", submit_cmd },
{ "cat", cat_cmd },
{ "help", list_cmd },
- { "search", search_cmd }
+ { "submit", submit_cmd },
+ { "query", query_cmd },
};
-struct parseinfo lastrun;
+struct parseinfo cached;
const char *resultdir;
-void
-search_cmd(char *arg)
-{
- char *end, *resultfile = NULL;
- const char *hash;
- struct dirent *de;
- int i, which;
- DIR *d = NULL;
-
- if (lastrun.valid)
- hash = lastrun.hash;
- else
- hash = mhash(ask("What is the model name?\n"), -1);
-
- d = opendir("scans");
- if (!d) return;
-
- i = 0;
- while ((de = readdir(d))) {
- if (de->d_type != DT_DIR && !strpfcmp(hash, de->d_name)) {
- printf("%i : %s\n", i, de->d_name);
- i++;
- }
- }
-
- if (i == 0) {
- fprintf(stderr, "Sorry, couldnt find a matching scan result!\n");
- goto cleanup;
- } else {
- which = strtoul(ask("Which of these results?\n"), &end, 10);
- if (which >= i || which < 0 || *end) {
- fprintf(stderr, "Invalid index!\n");
- goto cleanup;
- }
- }
-
- while ((de = readdir(d))) {
- if (de->d_type != DT_DIR && !strpfcmp(hash, de->d_name)) {
- if (i == which) {
- resultfile = aprintf("scans/%s/info", strdup(de->d_name));
- break;
- }
- i++;
- }
- }
-
- if (resultfile)
- dump(resultfile);
-
-cleanup:
- free(resultfile);
- closedir(d);
-}
-
int
-save_submission(char *stldata, int stlsize)
+save_submission(struct parseinfo *info, char *stldata, int stlsize)
{
DIR *d;
FILE *f;
char *dirpath = NULL, *infopath = NULL, *modelpath = NULL;
- dirpath = aprintf("%s/%s-%i", resultdir, lastrun.hash, time(NULL));
+ 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");
if (!(f = fopen(modelpath, "w+"))) goto fail;
if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail;
fclose(f);
+ f = NULL;
infopath = aprintf("%s/%s", dirpath, "info");
if (!(f = fopen(infopath, "w+"))) goto fail;
- if (save_info(&lastrun, f) != OK) goto fail;
+ if (save_info(info, f) != OK) goto fail;
fclose(f);
+ f = NULL;
free(dirpath);
free(modelpath);
@@ -111,6 +63,8 @@ save_submission(char *stldata, int stlsize)
return OK;
fail:
+ if (f) fclose(f);
+
remove(infopath);
remove(modelpath);
remove(dirpath);
@@ -123,54 +77,135 @@ fail:
}
void
+cat_cmd(char *arg)
+{
+ if (arg && !strncmp(arg, "flag", 4))
+ dump("msgs/cat_flag");
+ else
+ printf("meow\n");
+}
+
+void
+list_cmd(char *arg)
+{
+ int i;
+
+ printf("Available commands:\n");
+ for (i = 0; i < ARRSIZE(commands); i++)
+ printf("%s%s", i ? " " : "", commands[i].name);
+ printf("\n");
+}
+
+void
submit_cmd(char *arg)
{
const char *bufp;
char *end, *contents;
size_t len;
- bufp = ask("How large is your file?\n");
+ bufp = ask("> How large is your file? ");
len = strtoul(bufp, &end, 10);
- if (len <= 0 || len >= 10000 || *end) {
+ 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);
contents[len] = '\0';
- lastrun.valid = parse_file(&lastrun, contents, len);
-
- if (lastrun.valid) {
- if (save_submission(contents, len) != OK)
+ 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", lastrun.hash);
+ printf("> Your file was saved with ID %s!\n", cached.hash);
}
free(contents);
}
void
-cat_cmd(char *arg)
+query_cmd(char *arg)
{
- if (arg && !strncmp(arg, "flag", 4))
- dump("msgs/cat_flag");
+ char *end, *scandir = NULL, *infopath = NULL, *modelpath = NULL;
+ const char *hash;
+ struct dirent *de;
+ int i, which, dirstart;
+ DIR *d = NULL;
+ FILE *f = NULL;
+ size_t size;
+
+ if (cached.valid)
+ hash = cached.hash;
else
- printf("meow\n");
-}
+ hash = mhash(ask("> What is the model name? "), -1);
-void
-list_cmd(char *arg)
-{
- int i;
+ if (!(d = opendir(resultdir))) return;
- printf("Available commands:\n");
- for (i = 0; i < ARRSIZE(commands); i++)
- printf("%s%s", i ? " " : "", commands[i].name);
- printf("\n");
+ dirstart = telldir(d);
+ for (i = 0; (de = readdir(d));) {
+ if (de->d_type == DT_DIR && !strpfcmp(hash, de->d_name)) {
+ printf("%i : %s\n", i, de->d_name);
+ i++;
+ }
+ }
+
+ if (i == 0) {
+ fprintf(stderr, "Sorry, couldnt find a matching scan result!\n");
+ goto cleanup;
+ } else {
+ which = strtoul(ask("> Which of these results? "), &end, 10);
+ if (which >= i || which < 0 || *end) {
+ fprintf(stderr, "Invalid index!\n");
+ goto cleanup;
+ }
+ }
+
+ seekdir(d, dirstart);
+ for (i = 0; (de = readdir(d));) {
+ if (de->d_type == DT_DIR && !strpfcmp(hash, de->d_name)) {
+ if (i == which) {
+ scandir = aprintf("%s/%s", resultdir, de->d_name);
+ break;
+ }
+ i++;
+ }
+ }
+
+ if (!scandir) {
+ fprintf(stderr, "Unexpected error!\n");
+ goto cleanup;
+ }
+
+ infopath = aprintf("%s/%s", scandir, "info");
+ if (!(f = fopen(infopath, "r"))) goto cleanup;
+ if (load_info(&cached, f) != OK) goto cleanup;
+ fclose(f);
+ f = NULL;
+
+ print_info(&cached);
+
+ 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);
+ while ((i = getc(f)) != EOF)
+ putc(i, stdout);
+ fclose(f);
+ f = NULL;
+ }
+
+cleanup:
+ if (f) fclose(f);
+ closedir(d);
+ free(scandir);
+ free(infopath);
+ free(modelpath);
}
int
@@ -180,7 +215,11 @@ main()
int exit, i;
if (!(resultdir = getenv("RESULTDIR")))
- resultdir = "/data";
+ resultdir = "scans";
+
+ setvbuf(stdin, NULL, _IONBF, 0);
+ setvbuf(stdout, NULL, _IONBF, 0);
+ setvbuf(stderr, NULL, _IONBF, 0);
dump("msgs/welcome");
@@ -211,5 +250,5 @@ main()
}
printf("see you later!\n");
- free_info(&lastrun);
+ free_info(&cached);
}
diff --git a/service/src/stlfile.c b/service/src/stlfile.c
@@ -254,12 +254,14 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
const char *tmp;
char *bp;
+ if (len < 7) return FAIL;
+
if (info->valid) free_info(info);
for (bp = buf; strchr(wsset, *bp); bp++);
/* check bin vs ascii with first keyword */
- status = !strncmp("solid ", bp, 6)
+ status = !strncmp("solid", bp, 5) && strchr(wsset, bp[5])
? parse_file_ascii(info, buf, len)
: parse_file_bin(info, buf, len);
if (status == FAIL) return FAIL;
@@ -312,8 +314,8 @@ load_info(struct parseinfo *info, FILE *f)
nread += fread(&info->loopcount, sizeof(int), 1, f);
for (i = 0; i < 3; i++) {
- nread += fwrite(&info->bbmin[i], sizeof(float), 1, f);
- nread += fwrite(&info->bbmax[i], sizeof(float), 1, f);
+ nread += fread(&info->bbmin[i], sizeof(float), 1, f);
+ nread += fread(&info->bbmax[i], sizeof(float), 1, f);
}
nread += fread(info->header, 80, 1, f);
@@ -323,6 +325,8 @@ load_info(struct parseinfo *info, FILE *f)
freadstr(f, &info->modelname);
freadstr(f, &info->hash);
+ info->valid = 1;
+
return OK;
}
@@ -333,10 +337,12 @@ print_info(struct parseinfo *info)
#define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ')
- printf("Name: %s\n", info->modelname);
+ printf(" === Model info === \n");
+
+ printf(" Name: %s\n", info->modelname);
if (info->type == TYPE_BIN) {
- printf("Header:\n");
+ printf(" Header:\n ");
for (i = 0; i < 80; i += k) {
for (k = 0; k < MIN(80 - i, 20); k++)
printf(" %02x", (uint8_t) info->header[i+k]);
@@ -347,12 +353,14 @@ print_info(struct parseinfo *info)
}
}
- printf("Hash: %s\n", info->hash);
- printf("Triangles: %i\n", info->loopcount);
- printf("Bounding Box: %.2f x %.2f x %.2f\n",
+ printf(" Hash: %s\n", info->hash);
+ printf(" Triangles: %i\n", info->loopcount);
+ printf(" Bounding Box: %.2f x %.2f x %.2f\n",
info->bbmax[0] - info->bbmin[0],
info->bbmax[1] - info->bbmin[1],
info->bbmax[2] - info->bbmin[2]);
+
+ printf(" ================== \n");
}
void
diff --git a/service/src/stlfile.h b/service/src/stlfile.h
@@ -46,6 +46,7 @@ struct parseinfo {
int parse_file(struct parseinfo *info, char *buf, size_t len);
int save_info(struct parseinfo *info, FILE *f);
+int load_info(struct parseinfo *info, FILE *f);
void print_info(struct parseinfo *info);
void free_info(struct parseinfo *info);
diff --git a/service/src/test.sh b/service/src/test.sh
@@ -26,26 +26,54 @@ checkleaks() {
export RESULTDIR="scans"
-announce "Trying ASCII STL"
-(
- echo "submit"
- cat tests/sample-ascii.stl | wc -c
- cat tests/sample-ascii.stl
-) | checkleaks
-
-announce "Trying BIN STL"
-(
- echo "submit"
- cat tests/sample-binary.stl | wc -c
- cat tests/sample-binary.stl
- echo "testname"
-) | checkleaks
-
-
-announce "Testing Proof-Of-Concept"
-(
- echo "submit"
- cat tests/evil1.stl | wc -c
- cat tests/evil1.stl
-) | checkleaks
+if [ "$1" == "stl" ]; then
+ announce "Testing ASCII STL Parsing"
+ (
+ echo "submit"
+ cat tests/sample-ascii.stl | wc -c
+ cat tests/sample-ascii.stl
+ ) | checkleaks
+
+ announce "Testing BIN STL Parsing"
+ (
+ echo "submit"
+ cat tests/sample-binary.stl | wc -c
+ cat tests/sample-binary.stl
+ echo "testname"
+ ) | checkleaks
+
+elif [ "$1" == "poc" ]; then
+
+ announce "Testing Proof-Of-Concept"
+
+ rm -rf scans/*
+
+ echo -e "\n--- Uploading evil STL ---\n" 1>&2
+ (
+ echo "submit"
+ cat tests/evil1.stl | wc -c
+ cat tests/evil1.stl
+ echo "AAAA"
+ ) | ./printdoc
+
+ echo -e "\n--- Testing Exploit ---\n" 1>&2
+
+ (
+ echo "query"
+ echo "AAAA"
+ echo "0"
+ echo "n"
+
+ echo "query"
+ ) | ./printdoc
+
+else
+ (
+ echo "submit"
+ echo "2"
+ echo "AA"
+ echo "AAAA"
+ ) | ./printdoc
+
+fi
diff --git a/service/src/tests/evil1.stl b/service/src/tests/evil1.stl
@@ -1,4 +1,4 @@
-solid test˙
+solid
facet normal 0 0 1.0
outer loop
vertex 1 0 0
@@ -6,4 +6,4 @@ solid test
vertex 0 1 0
endloop
endfacet
-endsolid
-\ No newline at end of file
+endsolid
diff --git a/service/src/util.c b/service/src/util.c
@@ -55,8 +55,8 @@ mhash(const char *filename, int len)
unsigned char v = 0;
for (k = i; k < len; k += MHASHLEN)
v ^= filename[k];
- buf[i*2+0] = hexalph[(v >> 0) & 0x0f];
buf[i*2+1] = hexalph[(v >> 4) & 0x0f];
+ buf[i*2+0] = hexalph[(v >> 0) & 0x0f];
}
if (i == 0) {
@@ -78,7 +78,8 @@ freadstr(FILE *f, char **dst)
char c;
start = ftell(f);
- while ((c = fgetc(f)) != EOF && c) len++;
+ for (len = 0; (c = fgetc(f)) != EOF && c; len++);
+ fseek(f, start, SEEK_SET);
*dst = calloc(len + 1, 1);
fread(*dst, len, 1, f);