From 68bf04f69d13b5f1ac8295c464e6a231ddc57415 Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Thu, 1 Aug 2013 11:37:35 +0930 Subject: [PATCH] Change manifest service to MeshMS2 --- meshms.c | 4 +- rhizome.c | 59 +++---------- rhizome.h | 17 ++-- rhizome_bundle.c | 164 +++++++++++++++++++---------------- rhizome_database.c | 207 +++++++++++++++------------------------------ rhizome_fetch.c | 2 +- tests/all | 1 + 7 files changed, 183 insertions(+), 271 deletions(-) diff --git a/meshms.c b/meshms.c index 7e19436b..c2cb16cf 100644 --- a/meshms.c +++ b/meshms.c @@ -119,7 +119,7 @@ static int get_database_conversations(const sid_t *my_sid, const sid_t *their_si sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id, version, filesize, tail, sender, recipient " "FROM manifests " - "WHERE service = 'MeshMS1' " + "WHERE service = '"RHIZOME_SERVICE_MESHMS2"' " "AND (sender=?1 or recipient=?1) " "AND (sender=?2 or recipient=?2)"); if (!statement) @@ -197,7 +197,7 @@ static int create_ply(const sid_t *my_sid, struct conversations *conv, rhizome_m m->journalTail = 0; const char *my_sidhex = alloca_tohex_sid(my_sid->binary); const char *their_sidhex = alloca_tohex_sid(conv->them.binary); - rhizome_manifest_set(m, "service", RHIZOME_SERVICE_MESHMS); + rhizome_manifest_set(m, "service", RHIZOME_SERVICE_MESHMS2); rhizome_manifest_set(m, "sender", my_sidhex); rhizome_manifest_set(m, "recipient", their_sidhex); rhizome_manifest_set_ll(m, "tail", m->journalTail); diff --git a/rhizome.c b/rhizome.c index 363f0cbd..a5dd419d 100644 --- a/rhizome.c +++ b/rhizome.c @@ -137,36 +137,22 @@ int rhizome_bundle_import_files(rhizome_manifest *m, const char *manifest_path, // This feels like a hack... m->manifest_bytes=m->manifest_all_bytes; + /* Do we already have this manifest or newer? */ + int64_t dbVersion = -1; + const char *id=rhizome_manifest_get(m, "id", NULL, 0); + if (sqlite_exec_int64(&dbVersion, "SELECT version FROM MANIFESTS WHERE id='%s';", id) == -1) + return WHY("Select failure"); + + if (dbVersion>=m->version) + return 2; + int status = rhizome_import_file(m, filepath); if (status<0) return status; - status = rhizome_manifest_check_duplicate(m, NULL, 0); - if (status) - return status; - return rhizome_add_manifest(m, 1); } -/* Import a bundle from a finalised manifest struct. The dataFileName element must give the path - of a readable file containing the payload unless the payload is null (zero length). The logic is - all in rhizome_add_manifest(). This function just wraps that function and manages object buffers - and lifetimes. -*/ - -int rhizome_bundle_import(rhizome_manifest *m, int ttl) -{ - if (config.debug.rhizome) - DEBUGF("(m=%p, ttl=%d)", m, ttl); - int ret = rhizome_manifest_check_duplicate(m, NULL, 0); - if (ret == 0) { - ret = rhizome_add_manifest(m, ttl); - if (ret == -1) - WHY("rhizome_add_manifest() failed"); - } - return ret; -} - int rhizome_manifest_check_sanity(rhizome_manifest *m_in) { /* Ensure manifest meets basic sanity checks. */ @@ -188,7 +174,8 @@ int rhizome_manifest_check_sanity(rhizome_manifest *m_in) const char *name = rhizome_manifest_get(m_in, "name", NULL, 0); if (name == NULL) return WHY("Manifest missing 'name' field"); - } else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) { + } else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0 + || strcasecmp(service, RHIZOME_SERVICE_MESHMS2) == 0) { if (sender == NULL || !sender[0]) return WHY("MeshMS Manifest missing 'sender' field"); if (!str_is_subscriber_id(sender)) @@ -254,30 +241,6 @@ int rhizome_manifest_bind_id(rhizome_manifest *m_in) return 0; } -/* Check if a manifest is already stored for the same payload with the same details. - This catches the case of "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 check_author) -{ - if (config.debug.rhizome) DEBUG("Checking for duplicate"); - if (m_out) *m_out = NULL; - rhizome_manifest *dupm = NULL; - if (rhizome_find_duplicate(m_in, &dupm, check_author) == -1) - return WHY("Errors encountered searching for duplicate manifest"); - if (dupm) { - /* If the caller wants the duplicate manifest, it must be finalised, otherwise discarded. */ - if (m_out) { - *m_out = dupm; - } - else - rhizome_manifest_free(dupm); - if (config.debug.rhizome) DEBUG("Found a duplicate"); - return 2; - } - if (config.debug.rhizome) DEBUG("No duplicate found"); - return 0; -} - int rhizome_add_manifest(rhizome_manifest *m_in,int ttl) { if (config.debug.rhizome) diff --git a/rhizome.h b/rhizome.h index 404a3738..e8caec0f 100644 --- a/rhizome.h +++ b/rhizome.h @@ -108,6 +108,8 @@ typedef struct rhizome_manifest { except the creator. */ unsigned char cryptoSignPublic[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES]; unsigned char cryptoSignSecret[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES]; + /* Whether we have the secret for this manifest on hand */ + int haveSecret; int var_count; char *vars[MAX_MANIFEST_VARS]; @@ -121,7 +123,13 @@ typedef struct rhizome_manifest { */ unsigned char signatureTypes[MAX_MANIFEST_VARS]; - int errors; /* if non-zero, then manifest should not be trusted */ + // errors only involve the correctness of fields that are mandatory for + // proper operation of the transport and storage layer + int errors; + // a warning indicates that the manifest cannot be perfectly understood by this version of rhizome + // during add, the manifest should not be finalised and imported + // during extract an error should be displayed. + int warnings; time_ms_t inserttime; /* Set non-zero after variables have been packed and @@ -149,8 +157,6 @@ typedef struct rhizome_manifest { unsigned char payloadKey[RHIZOME_CRYPT_KEY_BYTES]; unsigned char payloadNonce[crypto_stream_xsalsa20_NONCEBYTES]; - /* Whether we have the secret for this manifest on hand */ - int haveSecret; /* Whether the manifest contains a signature that corresponds to the manifest id (ie public key) */ int selfSigned; @@ -174,6 +180,7 @@ typedef struct rhizome_manifest { */ #define RHIZOME_SERVICE_FILE "file" #define RHIZOME_SERVICE_MESHMS "MeshMS1" +#define RHIZOME_SERVICE_MESHMS2 "MeshMS2" extern int64_t rhizome_space; extern unsigned short rhizome_http_server_port; @@ -259,12 +266,10 @@ int rhizome_manifest_add_group(rhizome_manifest *m,char *groupid); int rhizome_clean_payload(const char *fileidhex); int rhizome_store_file(rhizome_manifest *m,const unsigned char *key); int rhizome_bundle_import_files(rhizome_manifest *m, const char *manifest_path, const char *filepath); -int rhizome_bundle_import(rhizome_manifest *m, int ttl); int rhizome_fill_manifest(rhizome_manifest *m, const char *filepath, const sid_t *authorSid, rhizome_bk_t *bsk); int rhizome_manifest_verify(rhizome_manifest *m); int rhizome_manifest_check_sanity(rhizome_manifest *m_in); -int rhizome_manifest_check_duplicate(rhizome_manifest *m_in,rhizome_manifest **m_out, int check_author); int rhizome_manifest_bind_id(rhizome_manifest *m_in); int rhizome_manifest_finalise(rhizome_manifest *m, rhizome_manifest **mout); @@ -321,7 +326,7 @@ int _sqlite_vexec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, st double rhizome_manifest_get_double(rhizome_manifest *m,char *var,double default_value); int rhizome_manifest_extract_signature(rhizome_manifest *m,int *ofs); int rhizome_update_file_priority(const char *fileid); -int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, int check_author); +int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found); int rhizome_manifest_to_bar(rhizome_manifest *m,unsigned char *bar); int64_t rhizome_bar_version(const unsigned char *bar); uint64_t rhizome_bar_bidprefix_ll(unsigned char *bar); diff --git a/rhizome_bundle.c b/rhizome_bundle.c index afcaba8b..b174846e 100644 --- a/rhizome_bundle.c +++ b/rhizome_bundle.c @@ -84,29 +84,22 @@ int rhizome_manifest_verify(rhizome_manifest *m) else return 0; } -int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferP) +int read_whole_file(const char *filename, unsigned char *buffer, int buffer_size) +{ + FILE *f = fopen(filename, "r"); + if (f == NULL) + return WHYF("Could not open file %s for reading", filename); + int ret = fread(buffer, 1, buffer_size, f); + if (ret == -1) + ret = WHY_perror("fread"); + if (fclose(f) == EOF) + ret = WHY_perror("fclose"); + return ret; +} + +int rhizome_manifest_parse(rhizome_manifest *m) { IN(); - if (bufferP>MAX_MANIFEST_BYTES) RETURN(WHY("Buffer too big")); - if (!m) RETURN(WHY("Null manifest")); - - if (bufferP) { - m->manifest_bytes=bufferP; - memcpy(m->manifestdata, filename, m->manifest_bytes); - } else { - FILE *f = fopen(filename, "r"); - if (f == NULL) - RETURN(WHYF("Could not open manifest file %s for reading.", filename)); - m->manifest_bytes = fread(m->manifestdata, 1, MAX_MANIFEST_BYTES, f); - int ret = 0; - if (m->manifest_bytes == -1) - ret = WHY_perror("fread"); - if (fclose(f) == EOF) - ret = WHY_perror("fclose"); - if (ret == -1) - RETURN(-1); - } - m->manifest_all_bytes=m->manifest_bytes; m->var_count=0; m->journalTail=-1; @@ -118,6 +111,7 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu int have_date = 0; int have_filesize = 0; int have_filehash = 0; + int ofs = 0; while (ofs < m->manifest_bytes && m->manifestdata[ofs]) { char line[1024]; @@ -143,9 +137,7 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu p = strchr(line, '='); if (p == NULL || p == line) { m->errors++; - WARNF(bufferP ? "Malformed manifest line in buffer %p: %s" - : "Malformed manifest line in file %s: %s", - filename, alloca_toprint(80, line, linelen)); + WARNF("Malformed manifest line: %s", alloca_toprint(80, line, linelen)); } else { *p++ = '\0'; char *var = line; @@ -161,6 +153,9 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu } else { m->vars[m->var_count] = strdup(var); m->values[m->var_count] = strdup(value); + + // if any of these fields are not well formed, the manifest is invalid and cannot be imported + if (strcasecmp(var, "id") == 0) { have_id = 1; if (fromhexstr(m->cryptoSignPublic, value, RHIZOME_MANIFEST_ID_BYTES) == -1) { @@ -182,15 +177,6 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu str_toupper_inplace(m->values[m->var_count]); strcpy(m->fileHexHash, m->values[m->var_count]); } - } else if (strcasecmp(var, "BK") == 0) { - if (!rhizome_str_is_bundle_key(value)) { - if (config.debug.rejecteddata) - WARNF("Invalid BK: %s", value); - m->errors++; - } else { - /* Force to upper case to avoid case sensitive comparison problems later. */ - str_toupper_inplace(m->values[m->var_count]); - } } else if (strcasecmp(var, "filesize") == 0) { have_filesize = 1; char *ep = value; @@ -202,14 +188,6 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu } else { m->fileLength = filesize; } - } else if (strcasecmp(var, "service") == 0) { - have_service = 1; - if ( strcasecmp(value, RHIZOME_SERVICE_FILE) == 0 - || strcasecmp(value, RHIZOME_SERVICE_MESHMS) == 0) { - } else { - INFOF("Unsupported service: %s", value); - // This is not an error... older rhizome nodes must carry newer manifests. - } } else if (strcasecmp(var, "version") == 0) { have_version = 1; char *ep = value; @@ -221,6 +199,40 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu } else { m->version = version; } + + // since rhizome *MUST* be able to carry future manifest versions + // if any of these fields are not well formed, the manifest can still be imported and exported + // but the bundle should not be added or exported + + } else if (strcasecmp(var, "tail") == 0) { + char *ep = value; + long long tail = strtoll(value, &ep, 10); + if (ep == value || *ep || tail < 0) { + if (config.debug.rejecteddata) + WARNF("Invalid tail: %s", value); + m->warnings++; + } else { + m->journalTail = tail; + } + } else if (strcasecmp(var, "BK") == 0) { + if (!rhizome_str_is_bundle_key(value)) { + if (config.debug.rejecteddata) + WARNF("Invalid BK: %s", value); + m->warnings++; + } else { + /* Force to upper case to avoid case sensitive comparison problems later. */ + str_toupper_inplace(m->values[m->var_count]); + } + } else if (strcasecmp(var, "service") == 0) { + have_service = 1; + if ( strcasecmp(value, RHIZOME_SERVICE_FILE) == 0 + || strcasecmp(value, RHIZOME_SERVICE_MESHMS) == 0 + || strcasecmp(value, RHIZOME_SERVICE_MESHMS2) == 0) { + } else { + if (config.debug.rejecteddata) + WARNF("Unsupported service: %s", value); + m->warnings++; + } } else if (strcasecmp(var, "date") == 0) { have_date = 1; char *ep = value; @@ -228,14 +240,14 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu if (ep == value || *ep || date < 0) { if (config.debug.rejecteddata) WARNF("Invalid date: %s", value); - m->errors++; + m->warnings++; } // TODO: store date in manifest struct } else if (strcasecmp(var, "sender") == 0 || strcasecmp(var, "recipient") == 0) { if (!str_is_subscriber_id(value)) { if (config.debug.rejecteddata) WARNF("Invalid %s: %s", var, value); - m->errors++; + m->warnings++; } else { /* Force to upper case to avoid case sensitive comparison problems later. */ str_toupper_inplace(m->values[m->var_count]); @@ -244,30 +256,18 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu if (value[0] == '\0') { if (config.debug.rejecteddata) WARN("Empty name"); - m->errors++; + m->warnings++; } - // TODO: complain if service is not MeshMS } else if (strcasecmp(var, "crypt") == 0) { if (!(strcmp(value, "0") == 0 || strcmp(value, "1") == 0)) { if (config.debug.rejecteddata) WARNF("Invalid crypt: %s", value); - m->errors++; + m->warnings++; } else { m->payloadEncryption = atoi(value); } - } else if (strcasecmp(var, "tail") == 0) { - char *ep = value; - long long tail = strtoll(value, &ep, 10); - if (ep == value || *ep || tail < 0) { - if (config.debug.rejecteddata) - WARNF("Invalid tail: %s", value); - m->errors++; - } else { - m->journalTail = tail; - } } else { - INFOF("Unsupported field: %s=%s", var, value); - // This is not an error... older rhizome nodes must carry newer manifests. + // An unknown field is not an error... older rhizome nodes must carry newer manifests. } m->var_count++; } @@ -281,11 +281,7 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu int end_of_text=ofs; m->manifest_bytes = end_of_text; - if (!have_service) { - if (config.debug.rejecteddata) - WARNF("Missing service field"); - m->errors++; - } + // verify that all required fields are consistent. if (!have_id) { if (config.debug.rejecteddata) WARNF("Missing manifest id field"); @@ -296,11 +292,6 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu WARNF("Missing version field"); m->errors++; } - if (!have_date) { - if (config.debug.rejecteddata) - WARNF("Missing date field"); - m->errors++; - } if (!have_filesize) { if (config.debug.rejecteddata) WARNF("Missing filesize field"); @@ -317,9 +308,21 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu m->errors++; } + // warn if expected fields are missing + if (!have_service) { + if (config.debug.rejecteddata) + WARNF("Missing service field"); + m->warnings++; + } + if (!have_date) { + if (config.debug.rejecteddata) + WARNF("Missing date field"); + m->warnings++; + } + // TODO Determine group membership here. - if (m->errors) { + if (m->errors || m->warnings) { if (config.debug.rejecteddata) dump("manifest body",m->manifestdata,m->manifest_bytes); } @@ -328,6 +331,24 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu OUT(); } +int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferP) +{ + if (!m) + return WHY("Null manifest"); + if (bufferP>sizeof(m->manifestdata)) + return WHY("Buffer too big"); + + if (bufferP) { + m->manifest_bytes=bufferP; + memcpy(m->manifestdata, filename, m->manifest_bytes); + } else { + m->manifest_bytes = read_whole_file(filename, m->manifestdata, sizeof(m->manifestdata)); + if (m->manifest_bytes == -1) + return -1; + } + return rhizome_manifest_parse(m); +} + int rhizome_hash_file(rhizome_manifest *m,const char *filename,char *hash_out) { /* Gnarf! NaCl's crypto_hash() function needs the whole file passed in in one @@ -680,11 +701,8 @@ int rhizome_manifest_finalise(rhizome_manifest *m, rhizome_manifest **mout) // if a manifest was supplied with an ID, don't bother to check for a duplicate. // we only want to filter out added files with no existing manifest. if (m->haveSecret==NEW_BUNDLE_ID){ - if (rhizome_manifest_check_duplicate(m, mout, 1) == 2) { - /* duplicate found -- verify it so that we can write it out later */ - rhizome_manifest_verify(*mout); + if (rhizome_find_duplicate(m, mout)==1) RETURN(2); - } } *mout=m; diff --git a/rhizome_database.c b/rhizome_database.c index e54b5485..4e4ec7a3 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -1232,171 +1232,96 @@ int rhizome_update_file_priority(const char *fileid) @author Andrew Bettison */ -int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found, int check_author) +int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found) { - // TODO, add service, name, sender & recipient to manifests table so we can simply query them. - const char *service = rhizome_manifest_get(m, "service", NULL, 0); - const char *name = NULL; - const char *sender = NULL; - const char *recipient = NULL; - if (service == NULL) { + if (service == NULL) return WHY("Manifest has no service"); - } else if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) { - name = rhizome_manifest_get(m, "name", NULL, 0); - if (!name) return WHY("Manifest has no name"); - } else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) { - sender = rhizome_manifest_get(m, "sender", NULL, 0); - recipient = rhizome_manifest_get(m, "recipient", NULL, 0); - if (!sender) return WHY("Manifest has no sender"); - if (!recipient) return WHY("Manifest has no recipient"); - } else { - return WHYF("Unsupported service '%s'", service); - } + + const char *name = rhizome_manifest_get(m, "name", NULL, 0); + const char *sender = rhizome_manifest_get(m, "sender", NULL, 0); + const char *recipient = rhizome_manifest_get(m, "recipient", NULL, 0); + char sqlcmd[1024]; strbuf b = strbuf_local(sqlcmd, sizeof sqlcmd); - strbuf_puts(b, "SELECT id, manifest, version, author FROM manifests WHERE "); - if (m->fileLength != 0) { - strbuf_puts(b, "filehash = ?"); - } else - strbuf_puts(b, "filesize = 0"); + strbuf_puts(b, "SELECT id, manifest, author FROM manifests WHERE filesize = ? AND service = ?"); + + if (m->fileLength != 0) + strbuf_puts(b, " AND filehash = ?"); + if (name) + strbuf_puts(b, " AND name = ?"); + if (sender) + strbuf_puts(b, " AND sender = ?"); + if (recipient) + strbuf_puts(b, " AND recipient = ?"); + if (strbuf_overrun(b)) return WHYF("SQL command too long: %s", strbuf_str(b)); + int ret = 0; sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; sqlite3_stmt *statement = sqlite_prepare(&retry, "%s", strbuf_str(b)); if (!statement) return -1; + int field = 1; - char filehash[RHIZOME_FILEHASH_STRLEN + 1]; - if (m->fileLength != 0) { - strncpy(filehash, m->fileHexHash, sizeof filehash); - str_toupper_inplace(filehash); - if (config.debug.rhizome) - DEBUGF("filehash=\"%s\"", filehash); - sqlite3_bind_text(statement, field++, filehash, -1, SQLITE_STATIC); - } + sqlite3_bind_int(statement, field++, m->fileLength); + sqlite3_bind_text(statement, field++, service, -1, SQLITE_STATIC); + + if (m->fileLength != 0) + sqlite3_bind_text(statement, field++, m->fileHexHash, -1, SQLITE_STATIC); + if (name) + sqlite3_bind_text(statement, field++, name, -1, SQLITE_STATIC); + if (sender) + sqlite3_bind_text(statement, field++, sender, -1, SQLITE_STATIC); + if (recipient) + sqlite3_bind_text(statement, field++, recipient, -1, SQLITE_STATIC); + int rows = 0; while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) { ++rows; - if (config.debug.rhizome) DEBUGF("Row %d", rows); - 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; - } - const char *q_manifestid = (const char *) sqlite3_column_text(statement, 0); - size_t manifestidsize = sqlite3_column_bytes(statement, 0); // must call after sqlite3_column_text() - unsigned char manifest_id[RHIZOME_MANIFEST_ID_BYTES]; - if ( manifestidsize != crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES * 2 - || fromhexstr(manifest_id, q_manifestid, RHIZOME_MANIFEST_ID_BYTES) == -1 - ) { - ret = WHYF("Malformed manifest.id from query: %s", q_manifestid); - break; - } - const char *manifestblob = (char *) sqlite3_column_blob(statement, 1); - size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob() - int64_t q_version = sqlite3_column_int64(statement, 2); - const char *q_author = (const char *) sqlite3_column_text(statement, 3); - + if (config.debug.rhizome) + DEBUGF("Row %d", rows); + rhizome_manifest *blob_m = rhizome_new_manifest(); if (blob_m == NULL) { ret = WHY("Out of manifests"); break; } + + const unsigned char *q_manifestid = sqlite3_column_text(statement, 0); + + const char *manifestblob = (char *) sqlite3_column_blob(statement, 1); + size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob() if (rhizome_read_manifest_file(blob_m, manifestblob, manifestblobsize) == -1) { WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid); - } else if (rhizome_manifest_verify(blob_m)) { - WARNF("MANIFESTS row id=%s fails verification -- skipped", q_manifestid); - } else { - const char *blob_service = rhizome_manifest_get(blob_m, "service", NULL, 0); - const char *blob_id = rhizome_manifest_get(blob_m, "id", NULL, 0); - int64_t blob_version = rhizome_manifest_get_ll(blob_m, "version"); - const char *blob_filehash = rhizome_manifest_get(blob_m, "filehash", NULL, 0); - int64_t blob_filesize = rhizome_manifest_get_ll(blob_m, "filesize"); - if (config.debug.rhizome) - DEBUGF("Consider manifest.service=%s manifest.id=%s manifest.version=%"PRId64, blob_service, q_manifestid, blob_version); - if (q_author) { - if (config.debug.rhizome) - strbuf_sprintf(b, " .author=%s", q_author); - stowSid(blob_m->author, 0, q_author); - } - - /* Perform consistency checks, because we're paranoid. */ - int inconsistent = 0; - if (blob_id && strcasecmp(blob_id, q_manifestid)) { - WARNF("MANIFESTS row id=%s has inconsistent blob with id=%s -- skipped", q_manifestid, blob_id); - ++inconsistent; - } - if (blob_version != q_version) { - WARNF("MANIFESTS row id=%s has inconsistent blob: manifests.version=%"PRId64", blob.version=%"PRId64" -- skipped", - q_manifestid, q_version, blob_version); - ++inconsistent; - } - if (blob_filesize != -1 && blob_filesize != m->fileLength) { - WARNF("MANIFESTS row id=%s has inconsistent blob: known file size %"PRId64", blob.filesize=%"PRId64" -- skipped", - q_manifestid, m->fileLength, blob_filesize); - ++inconsistent; - } - if (m->fileLength != 0) { - if (!blob_filehash && strcasecmp(blob_filehash, m->fileHexHash)) { - WARNF("MANIFESTS row id=%s has inconsistent blob: manifests.filehash=%s, blob.filehash=%s -- skipped", - q_manifestid, m->fileHexHash, blob_filehash); - ++inconsistent; - } - } else { - if (blob_filehash) { - WARNF("MANIFESTS row id=%s has inconsistent blob: blob.filehash should be absent -- skipped", - q_manifestid); - ++inconsistent; - } - } - if (blob_service == NULL) { - WARNF("MANIFESTS row id=%s has blob with no 'service' -- skipped", q_manifestid); - ++inconsistent; - } - if (!inconsistent) { - strbuf b = strbuf_alloca(1024); - if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) { - const char *blob_name = rhizome_manifest_get(blob_m, "name", NULL, 0); - if (blob_name && !strcmp(blob_name, name)) { - if (config.debug.rhizome) - strbuf_sprintf(b, " name=\"%s\"", blob_name); - }else - ++inconsistent; - } 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)) { - if (config.debug.rhizome) - strbuf_sprintf(b, " sender=%s recipient=%s", blob_sender, blob_recipient); - }else - ++inconsistent; - } - } - - if ((!inconsistent) && check_author) { - // check that we can re-author this manifest - if (rhizome_extract_privatekey(blob_m, NULL)) - ++inconsistent; - } - - if (!inconsistent) { - *found = blob_m; - if (config.debug.rhizome) - DEBUGF("Found duplicate payload: service=%s%s version=%"PRIu64" hexhash=%s", - blob_service, strbuf_str(b), blob_m->version, blob_m->fileHexHash - ); - ret = 1; - break; - } + goto next; } + + if (rhizome_manifest_verify(blob_m)) { + WARNF("MANIFESTS row id=%s fails verification -- skipped", q_manifestid); + goto next; + } + + const char *q_author = (const char *) sqlite3_column_text(statement, 2); + if (q_author) { + if (config.debug.rhizome) + strbuf_sprintf(b, " .author=%s", q_author); + stowSid(blob_m->author, 0, q_author); + } + + // check that we can re-author this manifest + if (rhizome_extract_privatekey(blob_m, NULL)){ + goto next; + } + + *found = blob_m; + if (config.debug.rhizome) + DEBUGF("Found duplicate payload, %s", q_manifestid); + ret = 1; + break; + +next: if (blob_m) rhizome_manifest_free(blob_m); } diff --git a/rhizome_fetch.c b/rhizome_fetch.c index 50c6f55f..0bf3d20a 100644 --- a/rhizome_fetch.c +++ b/rhizome_fetch.c @@ -396,7 +396,7 @@ static int rhizome_import_received_bundle(struct rhizome_manifest *m) m->manifest_bytes, m->sig_count,(long long)m->fileLength); dump("manifest", m->manifestdata, m->manifest_all_bytes); } - return rhizome_bundle_import(m, m->ttl - 1 /* TTL */); + return rhizome_add_manifest(m, m->ttl - 1 /* TTL */); } static int schedule_fetch(struct rhizome_fetch_slot *slot) diff --git a/tests/all b/tests/all index a4ee0fec..ceff6d58 100755 --- a/tests/all +++ b/tests/all @@ -29,6 +29,7 @@ includeTests dnahelper includeTests dnaprotocol includeTests rhizomeops includeTests rhizomeprotocol +includeTests meshms includeTests directory_service runTests "$@"