From 3678522872493d24cdae0c0541e697edd2afb073 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Tue, 9 Oct 2012 17:43:34 +1030 Subject: [PATCH] Issue #17, add AUTHOR column to Rhizome MANIFESTS table Replace ".selfsigned" column with ".author" and ".fromhere" columns in output of "rhizome list" command. (Note that a "sender" column is already present.) Add 'author' field to struct rhizome_manifest. Log all fully rendered SQL statements on DEBUG_RHIZOME. Update 'rhizomeops' test cases and improve the assert_rhizome_list() test function to be able to assert authorship of files. --- commandline.c | 26 ++++++++------- rhizome.c | 11 ++++--- rhizome.h | 7 +++- rhizome_crypto.c | 12 ++++--- rhizome_database.c | 77 +++++++++++++++++++++++++++++++++---------- rhizome_direct_http.c | 15 ++++----- testdefs_rhizome.sh | 23 +++++++++---- tests/rhizomeops | 40 +++++++++++----------- 8 files changed, 138 insertions(+), 73 deletions(-) diff --git a/commandline.c b/commandline.c index fe861582..1d283bc4 100644 --- a/commandline.c +++ b/commandline.c @@ -1030,8 +1030,13 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_ } /* Bind an ID to the manifest, and also bind the file. Then finalise the manifest. But if the manifest already contains an ID, don't override it. */ + if (authorSidHex[0]) { + if (debug & DEBUG_RHIZOME) + DEBUGF("author=%s", authorSidHex); + memcpy(m->author, authorSid, SID_SIZE); + } if (rhizome_manifest_get(m, "id", NULL, 0) == NULL) { - if (rhizome_manifest_bind_id(m, authorSidHex[0] ? authorSid : NULL)) { + if (rhizome_manifest_bind_id(m) == -1) { rhizome_manifest_free(m); m = NULL; return WHY("Could not bind manifest to an ID"); @@ -1067,22 +1072,19 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_ PGS @20121003 - Hang on, didn't we create the ID above? Presumably the following does NOT in fact generate a bundle ID. */ - rhizome_manifest *mout = NULL; - if (debug & DEBUG_RHIZOME) DEBUGF("rhizome_add_manifest(author='%s')", authorSidHex); - int ret=0; - if (rhizome_manifest_check_duplicate(m,&mout)==2) - { - /* duplicate found -- verify it so that we can write it out later */ - rhizome_manifest_verify(mout); - ret=2; - } else { + rhizome_manifest *mout = NULL; + if (rhizome_manifest_check_duplicate(m, &mout) == 2) { + /* duplicate found -- verify it so that we can write it out later */ + rhizome_manifest_verify(mout); + ret=2; + } else { /* not duplicate, so finalise and add to database */ if (rhizome_manifest_finalise(m)) { rhizome_manifest_free(m); return WHY("Could not finalise manifest"); } - if (rhizome_add_manifest(m,255 /* TTL */)) { + if (rhizome_add_manifest(m, 255 /* TTL */)) { rhizome_manifest_free(m); return WHY("Manifest not added to Rhizome database"); } @@ -1090,7 +1092,7 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_ /* If successfully added, overwrite the manifest file so that the Java component that is invoking this command can read it to obtain feedback on the result. */ - rhizome_manifest *mwritten=mout?mout:m; + rhizome_manifest *mwritten = mout ? mout : m; if (manifestpath[0] && rhizome_write_manifest_file(mwritten, manifestpath) == -1) ret = WHY("Could not overwrite manifest file."); diff --git a/rhizome.c b/rhizome.c index 93bf88f6..1d81b055 100644 --- a/rhizome.c +++ b/rhizome.c @@ -149,9 +149,10 @@ int rhizome_manifest_check_sanity(rhizome_manifest *m_in) by joining the parent group. */ -int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *authorSid) +int rhizome_manifest_bind_id(rhizome_manifest *m_in) { - rhizome_manifest_createid(m_in); + if (rhizome_manifest_createid(m_in) == -1) + return -1; /* The ID is implicit in transit, but we need to store it in the file, so that reimporting manifests on receiver nodes works easily. We might implement something that strips the id variable out of the manifest when sending it, or some other scheme to avoid sending all the @@ -159,7 +160,7 @@ int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *author char id[RHIZOME_MANIFEST_ID_STRLEN + 1]; rhizome_bytes_to_hex_upper(m_in->cryptoSignPublic, id, RHIZOME_MANIFEST_ID_BYTES); rhizome_manifest_set(m_in, "id", id); - if (authorSid) { + if (!is_sid_any(m_in->author)) { /* Set the BK using the provided authorship information. Serval Security Framework defines BK as being: BK = privateKey XOR sha512(RS##BID), where BID = cryptoSignPublic, @@ -168,7 +169,7 @@ int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *author privateKey = BK XOR sha512(RS##BID), so the same function can be used to encrypt and decrypt the BK field. */ unsigned char bkbytes[RHIZOME_BUNDLE_KEY_BYTES]; - if (rhizome_bk_xor(authorSid, m_in->cryptoSignPublic, m_in->cryptoSignSecret, bkbytes) == 0) { + if (rhizome_bk_xor(m_in->author, m_in->cryptoSignPublic, m_in->cryptoSignSecret, bkbytes) == 0) { char bkhex[RHIZOME_BUNDLE_KEY_STRLEN + 1]; (void) tohex(bkhex, bkbytes, RHIZOME_BUNDLE_KEY_BYTES); if (debug&DEBUG_RHIZOME) DEBUGF("set BK=%s", bkhex); @@ -281,7 +282,7 @@ int rhizome_manifest_check_file(rhizome_manifest *m_in) /* Check if a manifest is already stored for the same payload with the same details. This catches the case of "dna rhizome add file " on the same file more than once. (Debounce!) */ -int rhizome_manifest_check_duplicate(rhizome_manifest *m_in,rhizome_manifest **m_out) +int rhizome_manifest_check_duplicate(rhizome_manifest *m_in, rhizome_manifest **m_out) { if (debug & DEBUG_RHIZOME) DEBUG("Checking for duplicate"); if (m_out) *m_out = NULL; diff --git a/rhizome.h b/rhizome.h index 54c65f82..912e3cd7 100644 --- a/rhizome.h +++ b/rhizome.h @@ -132,6 +132,11 @@ typedef struct rhizome_manifest { int group_count; char *groups[MAX_MANIFEST_VARS]; + /* Author of the manifest. A reference to a local keyring entry. Manifests + * not authored locally will have the ANY author (all zeros). + */ + unsigned char author[SID_SIZE]; + } rhizome_manifest; /* Supported service identifiers. These go in the 'service' field of every @@ -222,7 +227,7 @@ int rhizome_manifest_check_sanity(rhizome_manifest *m_in); int rhizome_manifest_check_file(rhizome_manifest *m_in); int rhizome_manifest_check_duplicate(rhizome_manifest *m_in,rhizome_manifest **m_out); -int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *authorSid); +int rhizome_manifest_bind_id(rhizome_manifest *m_in); int rhizome_manifest_bind_file(rhizome_manifest *m_in,const char *filename,int encryptP); int rhizome_manifest_finalise(rhizome_manifest *m); int rhizome_add_manifest(rhizome_manifest *m_in,int ttl); diff --git a/rhizome_crypto.c b/rhizome_crypto.c index 232b0c1a..82f3107c 100644 --- a/rhizome_crypto.c +++ b/rhizome_crypto.c @@ -112,10 +112,14 @@ int rhizome_extract_privatekey(rhizome_manifest *m, const unsigned char *authorS /* Test to see if the given manifest was created (signed) by any unlocked identity currently in the keyring. - Returns -1 if an error occurs, eg, the manifest contains an invalid BK field. - Return 0 if the manifest's BK field was produced by any currently unlocked SID. - Returns 1 if the manifest has no BK field. - Returns 2 otherwise. + - Returns -1 if an error occurs, eg, the manifest contains an invalid BK field. + - Return 0 if the manifest's BK field was produced by any currently unlocked SID. + - Returns 1 if the manifest has no BK field. + - Returns 2 otherwise. + Currently unused; was called from rhizome_list_manifests() to compute the now-defunct + ".selfsigned" column, but that made the Rhizome List view too slow in the Serval Mesh app. + See issue servalproject/serval-dna#17. + @author Andrew Bettison */ int rhizome_is_self_signed(rhizome_manifest *m) { diff --git a/rhizome_database.c b/rhizome_database.c index d5413e6b..0f56a218 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -120,6 +120,12 @@ int rhizome_manifest_priority(sqlite_retry_state *retry, const char *id) return (int) result; } +static void sqlite_trace_callback(void *context, const char *rendered_sql) +{ + if (debug & DEBUG_RHIZOME) + DEBUG(rendered_sql); +} + int rhizome_opendb() { if (rhizome_db) return 0; @@ -137,6 +143,7 @@ int rhizome_opendb() if (sqlite3_open(dbpath,&rhizome_db)){ RETURN(WHYF("SQLite could not open database %s: %s", dbpath, sqlite3_errmsg(rhizome_db))); } + sqlite3_trace(rhizome_db, sqlite_trace_callback, NULL); int loglevel = (debug & DEBUG_RHIZOME) ? LOG_LEVEL_DEBUG : LOG_LEVEL_SILENT; /* Read Rhizome configuration */ @@ -149,7 +156,7 @@ int rhizome_opendb() /* Create tables as required */ sqlite_exec_void_loglevel(loglevel, "PRAGMA auto_vacuum=2;"); if ( sqlite_exec_void("CREATE TABLE IF NOT EXISTS GROUPLIST(id text not null primary key, closed integer,ciphered integer,priority integer);") == -1 - || sqlite_exec_void("CREATE TABLE IF NOT EXISTS MANIFESTS(id text not null primary key, manifest blob, version integer,inserttime integer, bar blob, filesize integer, filehash text);") == -1 + || sqlite_exec_void("CREATE TABLE IF NOT EXISTS MANIFESTS(id text not null primary key, manifest blob, version integer,inserttime integer, bar blob, filesize integer, filehash text, author text);") == -1 || sqlite_exec_void("CREATE TABLE IF NOT EXISTS FILES(id text not null primary key, data blob, length integer, highestpriority integer, datavalid integer, inserttime integer);") == -1 || sqlite_exec_void("DROP TABLE IF EXISTS FILEMANIFESTS;") == -1 || sqlite_exec_void("CREATE TABLE IF NOT EXISTS GROUPMEMBERSHIPS(manifestid text not null, groupid text not null);") == -1 @@ -159,7 +166,7 @@ int rhizome_opendb() } /* Create indexes if they don't already exist */ - sqlite_exec_void_loglevel(LOG_LEVEL_WARN,"CREATE INDEX IF NOT EXISTS bundlesizeindex ON manifests (filesize);"); + sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS bundlesizeindex ON manifests (filesize);"); sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_HASH ON MANIFESTS(filehash);"); /* Clean out half-finished entries from the database */ @@ -669,12 +676,14 @@ int rhizome_store_bundle(rhizome_manifest *m) filehash[0] = '\0'; } + const char *author = is_sid_any(m->author) ? NULL : alloca_tohex_sid(m->author); + sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1) return -1; sqlite3_stmt *stmt; - if ((stmt = sqlite_prepare(&retry, "INSERT OR REPLACE INTO MANIFESTS(id,manifest,version,inserttime,bar,filesize,filehash) VALUES(?,?,?,?,?,?,?);")) == NULL) + if ((stmt = sqlite_prepare(&retry, "INSERT OR REPLACE INTO MANIFESTS(id,manifest,version,inserttime,bar,filesize,filehash,author) VALUES(?,?,?,?,?,?,?,?);")) == NULL) goto rollback; if (!( sqlite_code_ok(sqlite3_bind_text(stmt, 1, manifestid, -1, SQLITE_TRANSIENT)) && sqlite_code_ok(sqlite3_bind_blob(stmt, 2, m->manifestdata, m->manifest_bytes, SQLITE_TRANSIENT)) @@ -683,6 +692,7 @@ int rhizome_store_bundle(rhizome_manifest *m) && sqlite_code_ok(sqlite3_bind_blob(stmt, 5, bar, RHIZOME_BAR_BYTES, SQLITE_TRANSIENT)) && sqlite_code_ok(sqlite3_bind_int64(stmt, 6, m->fileLength)) && sqlite_code_ok(sqlite3_bind_text(stmt, 7, filehash, -1, SQLITE_TRANSIENT)) + && sqlite_code_ok(sqlite3_bind_text(stmt, 8, author, -1, SQLITE_TRANSIENT)) )) { WHYF("query failed, %s: %s", sqlite3_errmsg(rhizome_db), sqlite3_sql(stmt)); goto rollback; @@ -758,7 +768,7 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch { IN(); strbuf b = strbuf_alloca(1024); - strbuf_sprintf(b, "SELECT id, manifest, version, inserttime FROM manifests ORDER BY inserttime DESC"); + strbuf_sprintf(b, "SELECT id, manifest, version, inserttime, author FROM manifests ORDER BY inserttime DESC"); if (limit) strbuf_sprintf(b, " LIMIT %u", limit); if (offset) @@ -771,13 +781,14 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch return -1; int ret = 0; size_t rows = 0; - cli_puts("11"); cli_delim("\n"); // number of columns + cli_puts("12"); cli_delim("\n"); // number of columns cli_puts("service"); cli_delim(":"); cli_puts("id"); cli_delim(":"); cli_puts("version"); cli_delim(":"); cli_puts("date"); cli_delim(":"); cli_puts(".inserttime"); cli_delim(":"); - cli_puts(".selfsigned"); cli_delim(":"); + cli_puts(".author"); cli_delim(":"); + cli_puts(".fromhere"); cli_delim(":"); cli_puts("filesize"); cli_delim(":"); cli_puts("filehash"); cli_delim(":"); cli_puts("sender"); cli_delim(":"); @@ -785,11 +796,14 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch cli_puts("name"); cli_delim("\n"); // should be last, because name may contain ':' while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) { ++rows; - if (!( sqlite3_column_count(statement) == 4 + if (!( sqlite3_column_count(statement) == 5 && sqlite3_column_type(statement, 0) == SQLITE_TEXT && sqlite3_column_type(statement, 1) == SQLITE_BLOB && sqlite3_column_type(statement, 2) == SQLITE_INTEGER && sqlite3_column_type(statement, 3) == SQLITE_INTEGER + && ( sqlite3_column_type(statement, 4) == SQLITE_TEXT + || sqlite3_column_type(statement, 4) == SQLITE_NULL + ) )) { ret = WHY("Incorrect statement column"); break; @@ -804,6 +818,7 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob() long long q_version = sqlite3_column_int64(statement, 2); long long q_inserttime = sqlite3_column_int64(statement, 3); + const char *q_author = (const char *) sqlite3_column_text(statement, 4); if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize) == -1) { WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid); } else { @@ -829,14 +844,29 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch long long blob_date = rhizome_manifest_get_ll(m, "date"); const char *blob_filehash = rhizome_manifest_get(m, "filehash", NULL, 0); long long blob_filesize = rhizome_manifest_get_ll(m, "filesize"); - int self_signed = rhizome_is_self_signed(m) ? 0 : 1; + int from_here = 0; + if (q_author) { + DEBUGF("q_author=%s", alloca_str_toprint(q_author)); + unsigned char authorSid[SID_SIZE]; + stowSid(authorSid, 0, q_author); + int cn = 0, in = 0, kp = 0; + from_here = keyring_find_sid(keyring, &cn, &in, &kp, authorSid); + } + if (!from_here && blob_sender) { + DEBUGF("blob_sender=%s", alloca_str_toprint(blob_sender)); + unsigned char senderSid[SID_SIZE]; + stowSid(senderSid, 0, blob_sender); + int cn = 0, in = 0, kp = 0; + from_here = keyring_find_sid(keyring, &cn, &in, &kp, senderSid); + } if (debug & DEBUG_RHIZOME) DEBUGF("manifest payload size = %lld", blob_filesize); cli_puts(blob_service ? blob_service : ""); cli_delim(":"); cli_puts(q_manifestid); cli_delim(":"); cli_printf("%lld", blob_version); cli_delim(":"); cli_printf("%lld", blob_date); cli_delim(":"); cli_printf("%lld", q_inserttime); cli_delim(":"); - cli_printf("%d", self_signed); cli_delim(":"); + cli_puts(q_author ? q_author : ""); cli_delim(":"); + cli_printf("%d", from_here); cli_delim(":"); cli_printf("%lld", blob_filesize); cli_delim(":"); cli_puts(blob_filehash ? blob_filehash : ""); cli_delim(":"); cli_puts(blob_sender ? blob_sender : ""); cli_delim(":"); @@ -1104,7 +1134,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, } char sqlcmd[1024]; strbuf b = strbuf_local(sqlcmd, sizeof sqlcmd); - strbuf_puts(b, "SELECT id, manifest, version FROM manifests WHERE "); + strbuf_puts(b, "SELECT id, manifest, version, author FROM manifests WHERE "); if (m->fileLength != 0) { if (!m->fileHashedP) return WHY("Manifest payload is not hashed"); @@ -1115,8 +1145,6 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, strbuf_puts(b, " AND version = ?"); if (strbuf_overrun(b)) return WHYF("SQL command too long: %s", strbuf_str(b)); - if (debug & DEBUG_RHIZOME) - DEBUGF("sql query: %s", sqlcmd); int ret = 0; sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; sqlite3_stmt *statement = sqlite_prepare(&retry, "%s", strbuf_str(b)); @@ -1137,10 +1165,13 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) { ++rows; if (debug & DEBUG_RHIZOME) DEBUGF("Row %d", rows); - if (!( sqlite3_column_count(statement) == 3 + if (!( sqlite3_column_count(statement) == 4 && sqlite3_column_type(statement, 0) == SQLITE_TEXT && sqlite3_column_type(statement, 1) == SQLITE_BLOB && sqlite3_column_type(statement, 2) == SQLITE_INTEGER + && ( sqlite3_column_type(statement, 3) == SQLITE_TEXT + || sqlite3_column_type(statement, 3) == SQLITE_NULL + ) )) { ret = WHY("Incorrect statement columns"); break; @@ -1220,7 +1251,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, strbuf_sprintf(b, " name=\"%s\"", blob_name); ret = 1; } - } else if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) { + } else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) { const char *blob_sender = rhizome_manifest_get(blob_m, "sender", NULL, 0); const char *blob_recipient = rhizome_manifest_get(blob_m, "recipient", NULL, 0); if (blob_sender && !strcasecmp(blob_sender, sender) && blob_recipient && !strcasecmp(blob_recipient, recipient)) { @@ -1230,6 +1261,12 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, } } if (ret == 1) { + const char *q_author = (const char *) sqlite3_column_text(statement, 3); + if (q_author) { + if (debug & DEBUG_RHIZOME) + strbuf_sprintf(b, " .author=%s", q_author); + stowSid(blob_m->author, 0, q_author); + } memcpy(blob_m->cryptoSignPublic, manifest_id, RHIZOME_MANIFEST_ID_BYTES); memcpy(blob_m->fileHexHash, m->fileHexHash, RHIZOME_FILEHASH_STRLEN + 1); blob_m->fileHashedP = 1; @@ -1237,7 +1274,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, blob_m->version = q_version; *found = blob_m; DEBUGF("Found duplicate payload: service=%s%s version=%llu hexhash=%s", - blob_service, strbuf_str(b), blob_m->version, blob_m->fileHexHash + blob_service, strbuf_str(b), blob_m->version, blob_m->fileHexHash, q_author ? q_author : "" ); break; } @@ -1263,7 +1300,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp) if (fromhexstr(manifest_id, manifestid, RHIZOME_MANIFEST_ID_BYTES) == -1) return WHY("Invalid manifest ID"); sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; - sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id, manifest, version, inserttime FROM manifests WHERE id = ?"); + sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id, manifest, version, inserttime, author FROM manifests WHERE id = ?"); if (!statement) return -1; char manifestIdUpper[RHIZOME_MANIFEST_ID_STRLEN + 1]; @@ -1272,11 +1309,12 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp) int ret = 0; rhizome_manifest *m = NULL; while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) { - if (!( sqlite3_column_count(statement) == 4 + if (!( sqlite3_column_count(statement) == 5 && sqlite3_column_type(statement, 0) == SQLITE_TEXT && sqlite3_column_type(statement, 1) == SQLITE_BLOB && sqlite3_column_type(statement, 2) == SQLITE_INTEGER && sqlite3_column_type(statement, 3) == SQLITE_INTEGER + && sqlite3_column_type(statement, 4) == SQLITE_TEXT )) { ret = WHY("Incorrect statement column"); break; @@ -1323,6 +1361,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp) else m->version = blob_version; if (ret == 1) { + const char *q_author = (const char *) sqlite3_column_text(statement, 4); cli_puts("service"); cli_delim(":"); cli_puts(blob_service); cli_delim("\n"); cli_puts("manifestid"); cli_delim(":"); @@ -1331,6 +1370,10 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp) cli_printf("%lld", (long long) sqlite3_column_int64(statement, 2)); cli_delim("\n"); cli_puts("inserttime"); cli_delim(":"); cli_printf("%lld", (long long) sqlite3_column_int64(statement, 3)); cli_delim("\n"); + if (q_author) { + cli_puts(".author"); cli_delim(":"); + cli_puts(q_author); cli_delim("\n"); + } cli_puts("filesize"); cli_delim(":"); cli_printf("%lld", (long long) m->fileLength); cli_delim("\n"); if (m->fileLength != 0) { diff --git a/rhizome_direct_http.c b/rhizome_direct_http.c index 7e58a2d1..485d31fa 100644 --- a/rhizome_direct_http.c +++ b/rhizome_direct_http.c @@ -251,18 +251,17 @@ int rhizome_direct_form_received(rhizome_http_request *r) if (debug & DEBUG_RHIZOME) DEBUGF("manifest contains name=\"%s\"", name); } - const char *senderhex - = rhizome_manifest_get(m, "sender", NULL, 0); - if (!senderhex) senderhex=confValueGet("rhizome.api.addfile.author",NULL); - unsigned char authorSid[SID_SIZE]; - if (senderhex) fromhexstr(authorSid,senderhex,SID_SIZE); - const char *bskhex - =confValueGet("rhizome.api.addfile.bundlesecretkey", NULL); + const char *senderhex = rhizome_manifest_get(m, "sender", NULL, 0); + if (!senderhex) + senderhex = confValueGet("rhizome.api.addfile.author", NULL); + if (senderhex) + fromhexstr(m->author, senderhex, SID_SIZE); + const char *bskhex = confValueGet("rhizome.api.addfile.bundlesecretkey", NULL); /* Bind an ID to the manifest, and also bind the file. Then finalise the manifest. But if the manifest already contains an ID, don't override it. */ if (rhizome_manifest_get(m, "id", NULL, 0) == NULL) { - if (rhizome_manifest_bind_id(m, senderhex ? authorSid : NULL)) { + if (rhizome_manifest_bind_id(m)) { rhizome_manifest_free(m); m = NULL; rhizome_direct_clear_temporary_files(r); diff --git a/testdefs_rhizome.sh b/testdefs_rhizome.sh index 9543ee38..7f586647 100644 --- a/testdefs_rhizome.sh +++ b/testdefs_rhizome.sh @@ -47,17 +47,22 @@ assert_manifest_complete() { assert_rhizome_list() { assertStdoutLineCount --stderr '==' $(($# + 2)) - assertStdoutIs --stderr --line=1 -e '11\n' - assertStdoutIs --stderr --line=2 -e 'service:id:version:date:.inserttime:.selfsigned:filesize:filehash:sender:recipient:name\n' + assertStdoutIs --stderr --line=1 -e '12\n' + assertStdoutIs --stderr --line=2 -e 'service:id:version:date:.inserttime:.author:.fromhere:filesize:filehash:sender:recipient:name\n' local filename + local re__author="\($rexp_sid\)\{0,1\}" + local re__fromhere local re__inserttime="$rexp_date" for filename; do - re__selfsigned=1 + re__fromhere=1 case "$filename" in - *!) filename="${filename%!}"; re__selfsigned=0;; + *@*) re__author="${filename##*@}"; filename="${filename%@*}";; + esac + case "$filename" in + *!) re__fromhere=0; filename="${filename%!}";; esac unpack_manifest_for_grep "$filename" - assertStdoutGrep --stderr --matches=1 "^$re_service:$re_manifestid:$re_version:$re_date:$re__inserttime:$re__selfsigned:$re_filesize:$re_filehash:$re_sender:$re_recipient:$re_name\$" + assertStdoutGrep --stderr --matches=1 "^$re_service:$re_manifestid:$re_version:$re_date:$re__inserttime:$re__author:$re__fromhere:$re_filesize:$re_filehash:$re_sender:$re_recipient:$re_name\$" done } @@ -110,6 +115,8 @@ unpack_manifest_for_grep() { re_version="$rexp_version" re_date="$rexp_date" re_secret="$rexp_bundlesecret" + re_sender="\($rexp_sid\)\{0,1\}" + re_recipient="\($rexp_sid\)\{0,1\}" re_name=$(escape_grep_basic "${filename##*/}") local filesize=$($SED -n -e '/^filesize=/s///p' "$filename.manifest" 2>/dev/null) if [ "$filesize" = 0 ]; then @@ -124,11 +131,11 @@ unpack_manifest_for_grep() { # file, then use its file hash to check the rhizome list '' output. local filehash=$($SED -n -e '/^filehash=/s///p' "$filename.manifest" 2>/dev/null) if [ "$filehash" = "$re_filehash" ]; then + re_service=$($SED -n -e '/^service=/s///p' "$filename.manifest") + re_service=$(escape_grep_basic "$re_service") re_manifestid=$($SED -n -e '/^id=/s///p' "$filename.manifest") re_version=$($SED -n -e '/^version=/s///p' "$filename.manifest") re_date=$($SED -n -e '/^date=/s///p' "$filename.manifest") - re_service=$($SED -n -e '/^service=/s///p' "$filename.manifest") - re_service=$(escape_grep_basic "$re_service") re_sender=$($SED -n -e '/^sender=/s///p' "$filename.manifest") re_recipient=$($SED -n -e '/^recipient=/s///p' "$filename.manifest") case "$re_service" in @@ -138,6 +145,8 @@ unpack_manifest_for_grep() { ;; *) re_name= + re_sender="$rexp_sid" + re_recipient="$rexp_sid" ;; esac fi diff --git a/tests/rhizomeops b/tests/rhizomeops index 8c8da22a..d156031a 100755 --- a/tests/rhizomeops +++ b/tests/rhizomeops @@ -141,7 +141,7 @@ test_AddEmpty() { assertGrep .manifest '^name=$' assertGrep .manifest '^filesize=0$' executeOk_servald rhizome list '' - assert_rhizome_list '' + assert_rhizome_list @$SIDB1 } doc_AddThenList="List contains one file after one add" @@ -157,11 +157,11 @@ test_AddThenList() { # Add first file executeOk_servald rhizome add file $SIDB1 '' file1 file1.manifest executeOk_servald rhizome list '' - assert_rhizome_list file1 + assert_rhizome_list file1@$SIDB1 # Add second file executeOk_servald rhizome add file $SIDB1 '' file2 file2.manifest executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 } doc_AddThenExtractManifest="Extract manifest after one add" @@ -171,7 +171,7 @@ setup_AddThenExtractManifest() { echo "A test file" >file1 executeOk_servald rhizome add file $SIDB1 '' file1 file1.manifest executeOk_servald rhizome list '' - assert_rhizome_list file1 + assert_rhizome_list file1@$SIDB1 extract_manifest_id manifestid file1.manifest extract_manifest_version version file1.manifest extract_manifest_filehash filehash file1.manifest @@ -179,14 +179,15 @@ setup_AddThenExtractManifest() { test_AddThenExtractManifest() { executeOk_servald rhizome extract manifest $manifestid file1x.manifest assert cmp file1.manifest file1x.manifest - assertStdoutLineCount '==' 6 + assertStdoutLineCount '==' 7 local size=$(( $(cat file1 | wc -c) + 0 )) assertStdoutGrep --matches=1 "^service:file$" - assertStdoutGrep --matches=1 "^manifestid:$manifestid$" - assertStdoutGrep --matches=1 "^version:$version$" - assertStdoutGrep --matches=1 "^inserttime:[0-9]\+$" - assertStdoutGrep --matches=1 "^filehash:$filehash$" - assertStdoutGrep --matches=1 "^filesize:$size$" + assertStdoutGrep --matches=1 "^manifestid:$manifestid\$" + assertStdoutGrep --matches=1 "^version:$version\$" + assertStdoutGrep --matches=1 "^inserttime:[0-9]\+\$" + assertStdoutGrep --matches=1 "^\.author:$SIDB1\$" + assertStdoutGrep --matches=1 "^filehash:$filehash\$" + assertStdoutGrep --matches=1 "^filesize:$size\$" } doc_ExtractMissingManifest="Extract non-existent manifest" @@ -226,7 +227,7 @@ setup_AddThenExtractFile() { executeOk_servald rhizome add file $SIDB1 '' file1 file1.manifest tfw_cat --stderr executeOk_servald rhizome list '' - assert_rhizome_list file1 + assert_rhizome_list file1@$SIDB1 extract_manifest_filehash filehash file1.manifest } test_AddThenExtractFile() { @@ -284,7 +285,7 @@ setup_AddDuplicate() { extract_stdout_secret file2_secret # Make sure they are both in the list. executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 } test_AddDuplicate() { # Add first file again - nothing should change in its manifests, and it @@ -294,7 +295,7 @@ test_AddDuplicate() { assert [ -s file1.manifestA ] assert_stdout_add_file file1 executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 strip_signatures file1.manifest file1.manifestA assert diff file1.manifest file1.manifestA # Repeat for second file. @@ -302,7 +303,7 @@ test_AddDuplicate() { assert [ -s file2.manifestA ] assert_stdout_add_file file2 executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 strip_signatures file2.manifest file2.manifestA assert diff file2.manifest file2.manifestA } @@ -320,7 +321,7 @@ test_AddMismatched() { assert cmp file1.manifest file1_2.manifest # And rhizome store should be unchanged. executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 } doc_AddUpdateSameVersion="Add new payload to existing manifest with same version fails" @@ -343,7 +344,7 @@ test_AddUpdateSameVersion() { assert cmp file1_2.manifest file1_2.manifest.orig # And rhizome store should be unchanged. executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 } doc_AddUpdateNewVersion="Add new payload to existing manifest with new version" @@ -357,11 +358,12 @@ setup_AddUpdateNewVersion() { test_AddUpdateNewVersion() { tfw_cat -v file1_2.manifest executeOk_servald rhizome add file $SIDB1 '' file1_2 file1_2.manifest + tfw_cat --stderr assert_stdout_add_file file1_2 name=file1 assert_manifest_newer file1.manifest file1_2.manifest # Rhizome store contents reflect new payload. executeOk_servald rhizome list '' - assert_rhizome_list file1_2 file2 + assert_rhizome_list file1_2@$SIDB1 file2@$SIDB1 } doc_AddUpdateNoAuthor="Cannot add new payload to authorless manifest" @@ -376,7 +378,7 @@ test_AddUpdateNoAuthor() { assertExitStatus '!=' 0 # Rhizome store contents have old payload. executeOk_servald rhizome list '' - assert_rhizome_list file1 file2 + assert_rhizome_list file1@$SIDB1 file2@$SIDB1 } doc_AddUpdateNoAuthorWithSecret="Add new payload to authorless manifest with bundle secret" @@ -389,7 +391,7 @@ test_AddUpdateNoAuthorWithSecret() { tfw_cat --stderr # Rhizome store contents have new payload. executeOk_servald rhizome list '' - assert_rhizome_list file1_2! file2 + assert_rhizome_list file1_2@$SIDB1 file2@$SIDB1 } doc_AddUpdateAutoVersion="Add new payload to existing manifest with automatic version"