aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <me@fwei.tk>2018-07-05 19:45:07 -0400
committerFranklin Wei <me@fwei.tk>2018-07-05 19:45:07 -0400
commit9aa64e1c89fae3efc92297657f2a8cf3de5b1047 (patch)
tree265befebafae978a0f1e7549f4c6f9f5389dfdcf
parent626224ade749f4429d5c098d8f27798da8405ca1 (diff)
downloadcsaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.zip
csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.tar.gz
csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.tar.bz2
csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.tar.xz
Add method to save module state; allows resuming from a previous run
-rw-r--r--main.c3
-rw-r--r--service_provider.c111
-rw-r--r--service_provider.h2
-rw-r--r--trusted_module.c51
-rw-r--r--trusted_module.h3
5 files changed, 153 insertions, 17 deletions
diff --git a/main.c b/main.c
index 3d2c808..15eec9e 100644
--- a/main.c
+++ b/main.c
@@ -29,6 +29,9 @@ void cleanup(void)
{
if(cleanup_socket)
unlink(cleanup_socket);
+#ifndef DUMMY
+ sp_save();
+#endif
}
void signal_handler(int sig)
diff --git a/service_provider.c b/service_provider.c
index 1b68a25..d31e833 100644
--- a/service_provider.c
+++ b/service_provider.c
@@ -67,6 +67,9 @@ struct service_provider {
void *db; /* sqlite3 handle */
struct iomt *iomt; /* backed by database */
+
+ sqlite3_stmt *lookup_record, *insert_record, *update_record,
+ *insert_version, *count_versions, *lookup_version, *find_empty;
};
/* Generate an EQ certificate for inserting a placeholder with index
@@ -208,6 +211,11 @@ int count_rows(void *db, const char *table)
return rows;
}
+void db_free(void *handle)
+{
+ sqlite3_close(handle);
+}
+
void *db_init(const char *filename, bool overwrite, bool *need_init)
{
sqlite3 *db;
@@ -222,8 +230,7 @@ void *db_init(const char *filename, bool overwrite, bool *need_init)
extern unsigned char sqlinit_txt[];
/* create tables */
- char *msg;
- assert(sqlite3_exec(db, (const char*)sqlinit_txt, NULL, NULL, &msg) == SQLITE_OK);
+ assert(sqlite3_exec(db, (const char*)sqlinit_txt, NULL, NULL, NULL) == SQLITE_OK);
*need_init = true;
}
@@ -245,6 +252,46 @@ void commit_transaction(void *db)
sqlite3_exec(handle, "COMMIT;", 0, 0, 0);
}
+int count_placeholders(void *db)
+{
+ sqlite3 *handle = db;
+ const char *sql = "SELECT COUNT(*) FROM FileLeaves WHERE Val = ?1;";
+
+ sqlite3_stmt *st;
+ sqlite3_prepare_v2(handle, sql, -1, &st, 0);
+
+ sqlite3_bind_blob(st, 1, &hash_null, sizeof(hash_null), SQLITE_STATIC);
+
+ assert(sqlite3_step(st) == SQLITE_ROW);
+
+ int count = sqlite3_column_int(st, 0);
+
+ sqlite3_finalize(st);
+
+ printf("Counted %d placeholders\n", count);
+
+ return count;
+}
+
+uint64_t max_fileindex(void *db)
+{
+ sqlite3 *handle = db;
+ const char *sql = "SELECT MAX(Idx) FROM FileRecords;";
+
+ sqlite3_stmt *st;
+ sqlite3_prepare_v2(handle, sql, -1, &st, 0);
+
+ uint64_t max = 0;
+ if(sqlite3_step(st) == SQLITE_ROW)
+ max = sqlite3_column_int64(st, 0);
+
+ sqlite3_finalize(st);
+
+ printf("maximum index is %lu\n", max);
+
+ return max;
+}
+
/* leaf count will be 2^logleaves */
/* will use old DB contents unless overwrite_db is true */
struct service_provider *sp_new(const void *key, size_t keylen,
@@ -262,12 +309,12 @@ struct service_provider *sp_new(const void *key, size_t keylen,
bool iomt_init = true;
sp->db = db_init(dbpath, overwrite_db, &iomt_init);
- sp->tm = tm_new(key, keylen);
-
sp->data_dir = data_dir;
if(iomt_init)
{
+ sp->tm = tm_new(key, keylen);
+
/* create IOMT in memory first, then commit to DB */
sp->iomt = iomt_new_from_db(sp->db,
"FileNodes", "FileLeaves",
@@ -297,14 +344,24 @@ struct service_provider *sp_new(const void *key, size_t keylen,
NULL, 0,
logleaves);
- /* TODO: set placeholder count, file index */
+ sp->tm = tm_new_from_savedstate("module_state");
+ if(!sp->tm)
+ {
+ warn("failed to load module state; creating fresh state (will probably fail)");
+ sp->tm = tm_new(key, keylen);
+ }
+
+ sp->n_placeholders = count_placeholders(sp->db);
+ sp->next_fileidx = max_fileindex(sp->db) + 1;
- warn("resuming from previous database; module will fail");
+ printf("Resuming from previous state...\n");
+#if 0
int leaves = count_rows(sp->db, "FileLeaves");
if(leaves != (1ULL << logleaves))
warn("logleaves value is inconsistent with leaf count in IOMT! (have %d, expect %d)",
leaves, 1 << logleaves);
+#endif
}
return sp;
@@ -335,6 +392,7 @@ void sp_free(struct service_provider *sp)
{
tm_free(sp->tm);
iomt_free(sp->iomt);
+ db_free(sp->db);
free(sp);
}
}
@@ -665,17 +723,12 @@ struct tm_cert sp_request(struct service_provider *sp,
/* returns a leaf idx (not a file idx!) */
static uint64_t find_empty_slot(struct service_provider *sp)
{
- static sqlite3_stmt *st = NULL;
+ sqlite3_stmt *st;
sqlite3 *handle = sp->db;
- if(!st)
- {
- const char *sql = "SELECT LeafIdx FROM FileLeaves WHERE Val = ?1 LIMIT 1;";
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
- }
- else
- sqlite3_reset(st);
+ const char *sql = "SELECT LeafIdx FROM FileLeaves WHERE Val = ?1 LIMIT 1;";
+ sqlite3_prepare_v2(handle, sql, -1, &st, 0);
sqlite3_bind_blob(st, 1, &hash_null, sizeof(hash_null), SQLITE_STATIC);
@@ -774,6 +827,7 @@ struct tm_request sp_createfile(struct service_provider *sp,
acl);
sp->n_placeholders--;
+ iomt_free(acl);
free(file_comp);
free(file_orders);
@@ -819,6 +873,8 @@ struct tm_request sp_modifyacl(struct service_provider *sp,
acl_comp, acl_orders, rec->acl->mt_logleaves,
iomt_getroot(new_acl));
+ free_record(rec);
+
free(file_comp);
free(file_orders);
free(acl_comp);
@@ -894,6 +950,8 @@ struct tm_request sp_modifyfile(struct service_provider *sp,
free(file_orders);
free(acl_orders);
+ free_record(rec);
+
hash_t req_hmac = sign_request(userdata, &req);
struct tm_cert vr;
@@ -1015,6 +1073,7 @@ struct version_info sp_fileinfo(struct service_provider *sp,
&rec->fr_cert, rec->fr_hmac,
ver ? &ver->vr_cert : NULL, ver ? ver->vr_hmac : hash_null,
hmac);
+ free_record(rec);
free_version(ver);
return ret;
@@ -1054,6 +1113,7 @@ void *sp_retrieve_file(struct service_provider *sp,
if(!ver)
{
+ free_record(rec);
*len = 0;
return NULL;
}
@@ -1091,6 +1151,7 @@ void *sp_retrieve_file(struct service_provider *sp,
if(composefile)
*composefile = iomt_dup(ver->composefile);
+ free_record(rec);
free_version(ver);
return ret;
@@ -1143,6 +1204,9 @@ static void sp_handle_client(struct service_provider *sp, int cl)
user_req.modify_acl.file_idx,
acl,
&ack_hmac);
+
+ iomt_free(acl);
+
if(write(cl, &ack_hmac, sizeof(ack_hmac)) != sizeof(ack_hmac))
return;
break;
@@ -1173,6 +1237,9 @@ static void sp_handle_client(struct service_provider *sp, int cl)
{
printf("Failed: %s\n", tm_geterror());
}
+
+ free(filebuf);
+
iomt_free(buildcode);
iomt_free(composefile);
write(cl, &ack_hmac, sizeof(ack_hmac));
@@ -1227,7 +1294,10 @@ static void sp_handle_client(struct service_provider *sp, int cl)
write(cl, &len, sizeof(len));
if(contents)
+ {
write(cl, contents, len);
+ free(contents);
+ }
break;
}
@@ -1239,6 +1309,18 @@ static void sp_handle_client(struct service_provider *sp, int cl)
}
}
+/* will be called by main.c's signal handler to save the module's
+ * state */
+static struct service_provider *global_sp = NULL;
+
+void sp_save(void)
+{
+ if(global_sp)
+ {
+ tm_savestate(global_sp->tm, "module_state");
+ }
+}
+
int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite)
{
#define BACKLOG 10
@@ -1252,6 +1334,7 @@ int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite)
signal(SIGPIPE, SIG_IGN);
struct service_provider *sp = sp_new("a", 1, logleaves, "files", dbpath, overwrite);
+ global_sp = sp;
while(1)
{
diff --git a/service_provider.h b/service_provider.h
index fdc7bc0..4dcb109 100644
--- a/service_provider.h
+++ b/service_provider.h
@@ -135,6 +135,8 @@ void sp_test(void);
#if defined(DUMMY) || !defined(CLIENT)
int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite);
+
+void sp_save(void);
#endif
#endif
diff --git a/trusted_module.c b/trusted_module.c
index 970db7d..2a5c61d 100644
--- a/trusted_module.c
+++ b/trusted_module.c
@@ -20,7 +20,7 @@
#include "trusted_module.h"
struct user_key {
- const void *key;
+ void *key; /* dynamic */
size_t len;
};
@@ -28,7 +28,7 @@ struct trusted_module {
hash_t root; /* root of IOMT */
/* shared secret with user */
- struct user_key *user_keys;
+ struct user_key *user_keys; /* dynamic */
size_t n_users;
/* secret for signing self-certificates */
@@ -56,8 +56,9 @@ struct trusted_module *tm_new(const void *key, size_t keylen)
tm->user_keys = calloc(1, sizeof(*tm->user_keys));
tm->n_users = 1;
- tm->user_keys[0].key = key;
tm->user_keys[0].len = keylen;
+ tm->user_keys[0].key = malloc(keylen);
+ memcpy(tm->user_keys[0].key, key, keylen);
/* initialize with a node of (1, 0, 1) in the tree */
struct iomt_node boot = (struct iomt_node) { 1, 1, hash_null };
@@ -69,10 +70,54 @@ struct trusted_module *tm_new(const void *key, size_t keylen)
void tm_free(struct trusted_module *tm)
{
+ for(int i = 0; i < tm->n_users; ++i)
+ free(tm->user_keys[i].key);
free(tm->user_keys);
free(tm);
}
+/* hack: no authentication at all */
+void tm_savestate(const struct trusted_module *tm, const char *filename)
+{
+ FILE *f = fopen(filename, "w");
+
+ fwrite(tm->secret, sizeof(tm->secret), 1, f);
+ fwrite(&tm->n_users, sizeof(tm->n_users), 1, f);
+ for(int i = 0; i < tm->n_users; ++i)
+ {
+ fwrite(&tm->user_keys[i].len, sizeof(tm->user_keys[i].len), 1, f);
+ fwrite(tm->user_keys[i].key, tm->user_keys[i].len, 1, f);
+ }
+
+ fwrite(&tm->root, sizeof(tm->root), 1, f);
+}
+
+struct trusted_module *tm_new_from_savedstate(const char *filename)
+{
+ FILE *f = fopen(filename, "r");
+
+ if(!f)
+ return NULL;
+
+ struct trusted_module *tm = calloc(1, sizeof(struct trusted_module));
+
+ fread(tm->secret, sizeof(tm->secret), 1, f);
+
+ fread(&tm->n_users, sizeof(tm->n_users), 1, f);
+ tm->user_keys = calloc(1, sizeof(*tm->user_keys) * tm->n_users);
+
+ for(int i = 0; i < tm->n_users; ++i)
+ {
+ fread(&tm->user_keys[i].len, sizeof(tm->user_keys[i].len), 1, f);
+ tm->user_keys[i].key = malloc(tm->user_keys[i].len);
+ fread(tm->user_keys[i].key, tm->user_keys[i].len, 1, f);
+ }
+
+ fread(&tm->root, sizeof(tm->root), 1, f);
+
+ return tm;
+}
+
static hash_t cert_sign(const struct trusted_module *tm, const struct tm_cert *cert)
{
return hmac_sha256(cert, sizeof(*cert), tm->secret, sizeof(tm->secret));
diff --git a/trusted_module.h b/trusted_module.h
index 6fca40a..fe4fbc1 100644
--- a/trusted_module.h
+++ b/trusted_module.h
@@ -104,7 +104,10 @@ static const struct version_info verinfo_null = { 0 };
/* creates 1 user with given shared secret */
struct trusted_module *tm_new(const void *key, size_t keylen);
+struct trusted_module *tm_new_from_savedstate(const char *filename);
+void tm_savestate(const struct trusted_module *tm, const char *filename);
void tm_free(struct trusted_module *tm);
+
void tm_test(void);
/* certificate generation routines */