Refactor Rhizome manifest validation

New function returns text describing the failed validation
This commit is contained in:
Andrew Bettison 2014-07-10 05:19:38 +09:30
parent 1ac67de0e9
commit 61023287b1
2 changed files with 53 additions and 65 deletions

View File

@ -108,7 +108,7 @@ typedef struct rhizome_manifest
unsigned char *signatories[MAX_MANIFEST_VARS]; unsigned char *signatories[MAX_MANIFEST_VARS];
uint8_t signatureTypes[MAX_MANIFEST_VARS]; uint8_t signatureTypes[MAX_MANIFEST_VARS];
/* Set to non-zero if a manifest has been parsed that cannot be fully /* Set to non-NULL if a manifest has been parsed that cannot be fully
* understood by this version of Rhizome (probably from a future or a very * understood by this version of Rhizome (probably from a future or a very
* old past version of Rhizome). During add (local injection), the manifest * old past version of Rhizome). During add (local injection), the manifest
* should not be imported. During extract (local decode) a warning or error * should not be imported. During extract (local decode) a warning or error
@ -116,7 +116,7 @@ typedef struct rhizome_manifest
* transported, imported and exported normally, as long as their signature is * transported, imported and exported normally, as long as their signature is
* valid. * valid.
*/ */
unsigned short malformed; const char *malformed;
/* Set non-zero after variables have been packed and signature blocks /* Set non-zero after variables have been packed and signature blocks
* appended. All fields below may not be valid until the manifest has been * appended. All fields below may not be valid until the manifest has been
@ -381,6 +381,7 @@ int rhizome_write_manifest_file(rhizome_manifest *m, const char *filename, char
int rhizome_manifest_selfsign(rhizome_manifest *m); int rhizome_manifest_selfsign(rhizome_manifest *m);
int rhizome_read_manifest_from_file(rhizome_manifest *m, const char *filename); int rhizome_read_manifest_from_file(rhizome_manifest *m, const char *filename);
int rhizome_manifest_validate(rhizome_manifest *m); int rhizome_manifest_validate(rhizome_manifest *m);
const char *rhizome_manifest_validate_reason(rhizome_manifest *m);
int rhizome_manifest_parse(rhizome_manifest *m); int rhizome_manifest_parse(rhizome_manifest *m);
int rhizome_manifest_verify(rhizome_manifest *m); int rhizome_manifest_verify(rhizome_manifest *m);

View File

@ -427,7 +427,7 @@ static void rhizome_manifest_clear(rhizome_manifest *m)
free(m->signatories[m->sig_count]); free(m->signatories[m->sig_count]);
m->signatories[m->sig_count] = NULL; m->signatories[m->sig_count] = NULL;
} }
m->malformed = 0; m->malformed = NULL;
m->has_id = 0; m->has_id = 0;
m->has_filehash = 0; m->has_filehash = 0;
m->is_journal = 0; m->is_journal = 0;
@ -542,7 +542,7 @@ int rhizome_manifest_parse(rhizome_manifest *m)
assert(m->manifest_body_bytes == 0); assert(m->manifest_body_bytes == 0);
assert(m->var_count == 0); assert(m->var_count == 0);
assert(!m->finalised); assert(!m->finalised);
assert(!m->malformed); assert(m->malformed == NULL);
assert(!m->has_id); assert(!m->has_id);
assert(!m->has_filehash); assert(!m->has_filehash);
assert(!m->is_journal); assert(!m->is_journal);
@ -742,11 +742,11 @@ int rhizome_manifest_parse(rhizome_manifest *m)
reason = "invalid"; reason = "invalid";
break; break;
case FIELD_UNKNOWN: case FIELD_UNKNOWN:
++m->malformed; m->malformed = "Unsupported field";
reason = "unsupported"; reason = "unsupported";
break; break;
case FIELD_MALFORMED: case FIELD_MALFORMED:
++m->malformed; m->malformed = "Invalid field";
reason = "invalid"; reason = "invalid";
break; break;
default: default:
@ -778,75 +778,62 @@ int rhizome_manifest_parse(rhizome_manifest *m)
/* If all essential (transport) fields are present and well formed then sets the m->finalised field /* If all essential (transport) fields are present and well formed then sets the m->finalised field
* and returns 1, otherwise returns 0. * and returns 1, otherwise returns 0.
* *
* Increments m->malformed if any non-essential fields are missing or invalid. It is up to the * Sets m->malformed if any non-essential fields are missing or invalid. It is up to the caller to
* caller to check the m->malformed field and decide whether or not to process a malformed manifest. * check m->malformed and decide whether or not to process a malformed manifest.
* *
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
*/ */
int rhizome_manifest_validate(rhizome_manifest *m) int rhizome_manifest_validate(rhizome_manifest *m)
{ {
int ret = 1; return rhizome_manifest_validate_reason(m) == NULL ? 1 : 0;
if (!m->has_id) { }
if (config.debug.rhizome_manifest)
DEBUG("Missing 'id' field"); /* If all essential (transport) fields are present and well formed then sets the m->finalised field
ret = 0; * and returns NULL, otherwise returns a pointer to a static string (not malloc(3)ed) describing the
} * problem.
if (m->version == 0) { *
if (config.debug.rhizome_manifest) * If any non-essential fields are missing or invalid, then sets m->malformed to point to a static
DEBUG("Missing 'version' field"); * string describing the problem. It is up to the caller to check m->malformed and decide whether
ret = 0; * or not to process a malformed manifest.
} *
if (m->filesize == RHIZOME_SIZE_UNSET) { * @author Andrew Bettison <andrew@servalproject.com>
if (config.debug.rhizome_manifest) */
DEBUG("Missing 'filesize' field"); const char *rhizome_manifest_validate_reason(rhizome_manifest *m)
ret = 0; {
} else if (m->filesize == 0 && m->has_filehash) { const char *reason = NULL;
if (config.debug.rhizome_manifest) if (!m->has_id)
DEBUG("Spurious 'filehash' field"); reason = "Missing 'id' field";
ret = 0; else if (m->version == 0)
} else if (m->filesize != 0 && !m->has_filehash) { reason = "Missing 'version' field";
if (config.debug.rhizome_manifest) else if (m->filesize == RHIZOME_SIZE_UNSET)
DEBUG("Missing 'filehash' field"); reason = "Missing 'filesize' field";
ret = 0; else if (m->filesize == 0 && m->has_filehash)
} reason = "Spurious 'filehash' field";
// Warn if expected fields are missing or invalid else if (m->filesize != 0 && !m->has_filehash)
if (m->service == NULL) { reason = "Missing 'filehash' field";
if (config.debug.rhizome_manifest) if (reason && config.debug.rhizome_manifest)
DEBUG("Missing 'service' field"); DEBUG(reason);
++m->malformed; if (m->service == NULL)
} m->malformed = "Missing 'service' field";
else if (strcmp(m->service, RHIZOME_SERVICE_FILE) == 0) { else if (strcmp(m->service, RHIZOME_SERVICE_FILE) == 0) {
if (m->name == NULL) { if (m->name == NULL)
if (config.debug.rhizome_manifest) m->malformed = "Manifest with service='" RHIZOME_SERVICE_FILE "' missing 'name' field";
DEBUG("Manifest with service='" RHIZOME_SERVICE_FILE "' missing 'name' field");
++m->malformed;
}
} else if (strcmp(m->service, RHIZOME_SERVICE_MESHMS) == 0 } else if (strcmp(m->service, RHIZOME_SERVICE_MESHMS) == 0
|| strcmp(m->service, RHIZOME_SERVICE_MESHMS2) == 0 || strcmp(m->service, RHIZOME_SERVICE_MESHMS2) == 0
) { ) {
if (!m->has_sender) { if (!m->has_recipient)
if (config.debug.rhizome_manifest) m->malformed = "Manifest missing 'recipient' field";
DEBUGF("Manifest with service='%s' missing 'sender' field", m->service); else if (!m->has_sender)
++m->malformed; m->malformed = "Manifest missing 'sender' field";
} }
if (!m->has_recipient) { else if (!rhizome_str_is_manifest_service(m->service))
if (config.debug.rhizome_manifest) m->malformed = "Manifest invalid 'service' field";
DEBUGF("Manifest with service='%s' missing 'recipient' field", m->service); else if (!m->has_date)
++m->malformed; m->malformed = "Missing 'date' field";
} if (m->malformed && config.debug.rhizome_manifest)
} DEBUG(m->malformed);
else if (!rhizome_str_is_manifest_service(m->service)) { m->finalised = (reason == NULL);
if (config.debug.rhizome_manifest) return reason;
DEBUGF("Manifest invalid 'service' field %s", alloca_str_toprint(m->service));
++m->malformed;
}
if (!m->has_date) {
if (config.debug.rhizome_manifest)
DEBUG("Missing 'date' field");
++m->malformed;
}
m->finalised = ret;
return ret;
} }
int rhizome_read_manifest_from_file(rhizome_manifest *m, const char *filename) int rhizome_read_manifest_from_file(rhizome_manifest *m, const char *filename)