mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-23 15:02:27 +00:00
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:
parent
e213a9eae8
commit
04cc05d6e1
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
117
rhizome_bundle.c
117
rhizome_bundle.c
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user