refactored manifest verification into a separate function

that is called only when needed, and marks a manifest as finalised
if the verifcation fails.  reading a manifest now never sets
finalised flag, as either _finalise() or _verify() must be called.
This commit is contained in:
gardners 2012-05-26 09:24:47 +09:30
parent e213a9eae8
commit 04cc05d6e1
7 changed files with 91 additions and 60 deletions

View File

@ -1153,7 +1153,10 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
return WHY("Manifest struct could not be allocated -- not added to rhizome");
if (manifestpath[0] && access(manifestpath, R_OK) == 0) {
if (debug & DEBUG_RHIZOME) DEBUGF("reading manifest from %s", manifestpath);
if (rhizome_read_manifest_file(m, manifestpath, 0, 0) == -1) { // no verify
/* Don't verify the manifest, because it will fail if it is incomplete.
This is okay, because we fill in any missing bits and sanity check before
trying to write it out. */
if (rhizome_read_manifest_file(m, manifestpath, 0) == -1) {
rhizome_manifest_free(m);
return WHY("Manifest file could not be loaded -- not added to rhizome");
}
@ -1210,7 +1213,8 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
int ret=0;
if (rhizome_manifest_check_duplicate(m,&mout)==2)
{
/* duplicate */
/* 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 */

View File

@ -53,9 +53,12 @@ int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out,
m = rhizome_new_manifest();
if (!m)
return WHY("Out of manifests.");
if (rhizome_read_manifest_file(m, manifestname, 0 /* file not buffer */, RHIZOME_VERIFY) == -1) {
if (rhizome_read_manifest_file(m, manifestname, 0 /* file not buffer */) == -1) {
rhizome_manifest_free(m);
return WHY("Could not read manifest file.");
} else if (rhizome_manifest_verify(m)) {
rhizome_manifest_free(m);
return WHY("Could not verify manifest file.");
}
} else {
if (debug&DEBUG_RHIZOMESYNC)

View File

@ -200,7 +200,7 @@ int rhizome_write_manifest_file(rhizome_manifest *m, const char *filename);
int rhizome_manifest_selfsign(rhizome_manifest *m);
int rhizome_drop_stored_file(char *id,int maximum_priority);
int rhizome_manifest_priority(char *id);
int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferPAndSize, int flags);
int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferPAndSize);
int rhizome_hash_file(rhizome_manifest *m, const char *filename,char *hash_out);
char *rhizome_manifest_get(const rhizome_manifest *m, const char *var, char *out, int maxlen);
long long rhizome_manifest_get_ll(rhizome_manifest *m, const char *var);

View File

@ -21,7 +21,71 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "rhizome.h"
#include <stdlib.h>
int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferP, int flags)
int rhizome_manifest_verify(rhizome_manifest *m)
{
int end_of_text=0;
/* find end of manifest body and start of signatures */
while(m->manifestdata[end_of_text]&&end_of_text<m->manifest_all_bytes)
end_of_text++;
end_of_text++; /* include null byte in body for verification purposes */
/* Calculate hash of the text part of the file, as we need to couple this with
each signature block to */
crypto_hash_sha512(m->manifesthash,m->manifestdata,end_of_text);
/* Read signature blocks from file. */
int ofs=end_of_text;
while(ofs<m->manifest_all_bytes) {
if (debug & DEBUG_RHIZOME) DEBUGF("ofs=0x%x, m->manifest_bytes=0x%x", ofs,m->manifest_all_bytes);
if (rhizome_manifest_extract_signature(m,&ofs)) break;
}
if (m->sig_count==0) {
m->errors++;
}
/* Make sure that id variable is correct */
{
char *id=rhizome_manifest_get(m,"id",NULL,0);
if (!id) {
WARN("Manifest lacks 'id' field");
m->errors++;
}
else {
unsigned char manifest_bytes[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
rhizome_hex_to_bytes(id,manifest_bytes,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
if ((m->sig_count==0)||
memcmp(&m->signatories[0][0],manifest_bytes,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES))
{
if (debug&DEBUG_RHIZOME) {
if (m->sig_count>0) {
DEBUGF("Manifest id variable does not match first signature block (signature key is %s)",
/* XXX bit of a hack that relies on SIDs and signing public keys being the same length */
overlay_render_sid(&m->signatories[0][0])
);
} else {
DEBUG("Manifest has no signature blocks, but should have self-signature block");
}
}
m->errors++;
m->selfSigned=0;
} else m->selfSigned=1;
}
}
/* Mark as finalised, as it is all read and intact,
unless of course it has errors, or is lacking a self-signature. */
if (!m->errors) m->finalised=1;
else WHY("Verified a manifest that has errors, so marking as not finalised");
if (m->errors) return WHY("Manifest verification failed");
else return 0;
}
int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferP)
{
if (bufferP>MAX_MANIFEST_BYTES) return WHY("Buffer too big");
if (!m) return WHY("Null manifest");
@ -97,55 +161,8 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu
/* Remember where the text ends */
int end_of_text=ofs;
if (flags&RHIZOME_VERIFY) {
/* Calculate hash of the text part of the file, as we need to couple this with
each signature block to */
crypto_hash_sha512(m->manifesthash,m->manifestdata,end_of_text);
/* Read signature blocks from file. */
while(ofs<m->manifest_bytes) {
if (debug & DEBUG_RHIZOME) DEBUGF("ofs=0x%x, m->manifest_bytes=0x%x", ofs,m->manifest_bytes);
rhizome_manifest_extract_signature(m,&ofs);
}
if (m->sig_count==0) {
m->errors++;
}
/* Make sure that id variable is correct */
{
char *id=rhizome_manifest_get(m,"id",NULL,0);
if (!id) {
WARN("Manifest lacks 'id' field");
m->errors++;
}
else {
unsigned char manifest_bytes[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
rhizome_hex_to_bytes(id,manifest_bytes,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
if ((m->sig_count==0)||
memcmp(&m->signatories[0][0],manifest_bytes,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES))
{
if (debug&DEBUG_RHIZOME) {
if (m->sig_count>0) {
DEBUGF("Manifest id variable does not match first signature block (signature key is %s)",
/* XXX bit of a hack that relies on SIDs and signing public keys being the same length */
overlay_render_sid(&m->signatories[0][0])
);
} else {
DEBUG("Manifest has no signature blocks, but should have self-signature block");
}
}
m->errors++;
m->selfSigned=0;
} else m->selfSigned=1;
}
}
if (debug&DEBUG_RHIZOME)
DEBUG("Group membership determination not implemented (see which signatories are groups? what about manifests signed by groups we don't yet know about?)");
}
if (debug&DEBUG_RHIZOME)
DEBUG("Group membership determination not implemented (see which signatories are groups? what about manifests signed by groups we don't yet know about?)");
m->manifest_bytes=end_of_text;

View File

@ -238,7 +238,7 @@ int rhizome_manifest_extract_signature(rhizome_manifest *m,int *ofs)
unsigned char publicKey[256];
if (!m) return WHY("NULL pointer passed in as manifest");
if ((*ofs)>=m->manifest_bytes) return 0;
if ((*ofs)>=m->manifest_all_bytes) return 0;
int len=m->manifestdata[*ofs];
if (!len) {

View File

@ -647,7 +647,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);
if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize, 0) == -1) {
if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize) == -1) {
WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid);
} else {
long long blob_version = rhizome_manifest_get_ll(m, "version");
@ -962,8 +962,10 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
ret = WHY("Out of manifests");
break;
}
if (rhizome_read_manifest_file(blob_m, manifestblob, manifestblobsize, 0) == -1) {
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(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);
@ -1084,7 +1086,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
if (m == NULL) {
WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid);
ret = WHY("Out of manifests");
} else if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize, 0) == -1) {
} else if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize) == -1) {
WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid);
ret = WHY("Invalid manifest blob from database");
} else {

View File

@ -339,7 +339,8 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
WHY("Out of manifests");
return 0;
}
if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs], manifest_length, RHIZOME_DONTVERIFY) == -1) {
if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs],
manifest_length) == -1) {
WHY("Error importing manifest body");
rhizome_manifest_free(m);
return 0;
@ -399,10 +400,14 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
Now reread the manifest, this time verifying signatures */
if ((m = rhizome_new_manifest()) == NULL)
WHY("Out of manifests");
else if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs], manifest_length, RHIZOME_VERIFY) == -1) {
else if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs], manifest_length) == -1) {
WHY("Error importing manifest body");
rhizome_manifest_free(m);
m = NULL;
} else if (rhizome_manifest_verify(m)) {
WHY("Error verifying manifest body when importing");
rhizome_manifest_free(m);
m = NULL;
} else if (m->errors) {
if (debug&DEBUG_RHIZOME) DEBUGF("Verifying manifest %s revealed errors -- not storing.", manifest_id);
rhizome_queue_ignore_manifest(m,(struct sockaddr_in*)f->recvaddr,60000);