mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 05:07:56 +00:00
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.
This commit is contained in:
parent
1de2bc8f23
commit
3678522872
@ -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,12 +1072,9 @@ 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)
|
||||
{
|
||||
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;
|
||||
@ -1082,7 +1084,7 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
|
||||
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.");
|
||||
|
11
rhizome.c
11
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 <filename>" 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;
|
||||
|
@ -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);
|
||||
|
@ -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 <andrew@servalproject.com>
|
||||
*/
|
||||
int rhizome_is_self_signed(rhizome_manifest *m)
|
||||
{
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user