From 637ef02f30c6f25158fbfbd46970244a2ebf70e6 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Fri, 8 Jun 2012 18:25:43 +0930 Subject: [PATCH] Add _selfsigned column to "rhizome list" output Add arg1 to "rhizome list" command, so it can open the keyring Some tests in tests/rhizome fail --- commandline.c | 85 ++++++++++++++++++-- keyring.c | 30 ++++--- rhizome.c | 1 + rhizome.h | 1 + rhizome_crypto.c | 107 +++++++++++++++++-------- rhizome_database.c | 3 + serval.h | 10 ++- testdefs.sh | 1 + tests/rhizome | 195 ++++++++++++++++++++++++++++----------------- 9 files changed, 306 insertions(+), 127 deletions(-) diff --git a/commandline.c b/commandline.c index c9d65ec6..2da64b33 100644 --- a/commandline.c +++ b/commandline.c @@ -1298,6 +1298,74 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_ return ret; } +int app_rhizome_import_bundle(int argc, const char *const *argv, struct command_line_option *o) +{ + const char *filepath, *manifestpath; + cli_arg(argc, argv, o, "filepath", &filepath, NULL, ""); + cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, ""); + if (rhizome_opendb() == -1) + return -1; + rhizome_manifest *m = rhizome_new_manifest(); + if (!m) + return WHY("Out of manifests."); + int status = -1; + if (rhizome_read_manifest_file(m, manifestpath, 0) == -1) { + status = WHY("could not read manifest file"); + } else if (rhizome_manifest_verify(m) == -1) { + status = WHY("Could not verify manifest file."); + } else { + /* Add the manifest and its associated file to the Rhizome database. */ + m->dataFileName = strdup(filepath); + if (rhizome_manifest_check_file(m)) + status = WHY("file does not belong to manifest"); + else { + int ret = rhizome_manifest_check_duplicate(m, NULL); + if (ret == -1) + status = WHY("rhizome_manifest_check_duplicate() failed"); + else if (ret) { + INFO("Duplicate found in store"); + status = 1; + } else if (rhizome_add_manifest(m, 1) == -1) { // ttl = 1 + status = WHY("rhizome_add_manifest() failed"); + } else { + status = 0; + } + if (status != -1) { + const char *service = rhizome_manifest_get(m, "service", NULL, 0); + if (service) { + cli_puts("service"); + cli_delim(":"); + cli_puts(service); + cli_delim("\n"); + } + { + cli_puts("manifestid"); + cli_delim(":"); + cli_puts(alloca_tohex(m->cryptoSignPublic, RHIZOME_MANIFEST_ID_BYTES)); + cli_delim("\n"); + } + cli_puts("filehash"); + cli_delim(":"); + cli_puts(m->fileHexHash); + cli_delim("\n"); + cli_puts("filesize"); + cli_delim(":"); + cli_printf("%lld", m->fileLength); + cli_delim("\n"); + const char *name = rhizome_manifest_get(m, "name", NULL, 0); + if (name) { + cli_puts("name"); + cli_delim(":"); + cli_puts(name); + cli_delim("\n"); + } + } + } + } + rhizome_manifest_free(m); + return status; +} + int cli_manifestid(const char *arg) { return rhizome_str_is_manifest_id(arg); @@ -1387,7 +1455,8 @@ int cli_uint(const char *arg) int app_rhizome_list(int argc, const char *const *argv, struct command_line_option *o) { - const char *service, *sender_sid, *recipient_sid, *offset, *limit; + const char *pin, *service, *sender_sid, *recipient_sid, *offset, *limit; + cli_arg(argc, argv, o, "pin,pin...", &pin, NULL, ""); cli_arg(argc, argv, o, "service", &service, NULL, ""); cli_arg(argc, argv, o, "sender_sid", &sender_sid, cli_optional_sid, ""); cli_arg(argc, argv, o, "recipient_sid", &recipient_sid, cli_optional_sid, ""); @@ -1396,6 +1465,8 @@ int app_rhizome_list(int argc, const char *const *argv, struct command_line_opti /* Create the instance directory if it does not yet exist */ if (create_serval_instance_dir() == -1) return -1; + if (!(keyring = keyring_open_with_pins(pin))) + return -1; if (rhizome_opendb() == -1) return -1; return rhizome_list_manifests(service, sender_sid, recipient_sid, atoi(offset), atoi(limit)); @@ -1404,7 +1475,7 @@ int app_rhizome_list(int argc, const char *const *argv, struct command_line_opti int app_keyring_create(int argc, const char *const *argv, struct command_line_option *o) { const char *pin; - cli_arg(argc, argv, o, "pin,pin ...", &pin, NULL, ""); + cli_arg(argc, argv, o, "pin,pin...", &pin, NULL, ""); if (!keyring_open_with_pins(pin)) return -1; return 0; @@ -1413,7 +1484,7 @@ int app_keyring_create(int argc, const char *const *argv, struct command_line_op int app_keyring_list(int argc, const char *const *argv, struct command_line_option *o) { const char *pin; - cli_arg(argc, argv, o, "pin,pin ...", &pin, NULL, ""); + cli_arg(argc, argv, o, "pin,pin...", &pin, NULL, ""); keyring_file *k = keyring_open_with_pins(pin); if (!k) return -1; @@ -1470,7 +1541,7 @@ int app_keyring_set_did(int argc, const char *const *argv, struct command_line_o if (strlen(did)>31) return WHY("DID too long (31 digits max)"); if (strlen(name)>63) return WHY("Name too long (31 char max)"); - if (!(keyring = keyring_open_with_pins((char *)pin))) + if (!(keyring = keyring_open_with_pins(pin))) return -1; unsigned char packedSid[SID_SIZE]; @@ -1728,7 +1799,9 @@ command_line_option command_line_options[]={ "Compute the Rhizome hash of a file"}, {app_rhizome_add_file,{"rhizome","add","file","","","","[]","[]",NULL},CLIFLAG_STANDALONE, "Add a file to Rhizome and optionally write its manifest to the given path"}, - {app_rhizome_list,{"rhizome","list","[]","[]","[]","[]","[]",NULL},CLIFLAG_STANDALONE, + {app_rhizome_import_bundle,{"rhizome","import","bundle","","",NULL},CLIFLAG_STANDALONE, + "Import a payload/manifest pair into Rhizome"}, + {app_rhizome_list,{"rhizome","list","","[]","[]","[]","[]","[]",NULL},CLIFLAG_STANDALONE, "List all manifests and files in Rhizome"}, {app_rhizome_extract_manifest,{"rhizome","extract","manifest","","[]",NULL},CLIFLAG_STANDALONE, "Extract a manifest from Rhizome and write it to the given path"}, @@ -1736,7 +1809,7 @@ command_line_option command_line_options[]={ "Extract a file from Rhizome and write it to the given path"}, {app_keyring_create,{"keyring","create",NULL},0, "Create a new keyring file."}, - {app_keyring_list,{"keyring","list","[]",NULL},CLIFLAG_STANDALONE, + {app_keyring_list,{"keyring","list","[]",NULL},CLIFLAG_STANDALONE, "List identites in specified key ring that can be accessed using the specified PINs"}, {app_keyring_add,{"keyring","add","[]",NULL},CLIFLAG_STANDALONE, "Create a new identity in the keyring protected by the provided PIN"}, diff --git a/keyring.c b/keyring.c index b5f66015..70873534 100644 --- a/keyring.c +++ b/keyring.c @@ -1042,7 +1042,7 @@ int keyring_set_did(keyring_identity *id,char *did,char *name) return 0; } -int keyring_find_did(keyring_file *k,int *cn,int *in,int *kp,char *did) +int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did) { if (keyring_sanitise_position(k,cn,in,kp)) return 0; @@ -1069,21 +1069,31 @@ int keyring_find_did(keyring_file *k,int *cn,int *in,int *kp,char *did) return 0; } -int keyring_next_identity(keyring_file *k,int *cn,int *in,int *kp) +int keyring_identity_find_keytype(const keyring_file *k, int cn, int in, int keytype) { - if (keyring_sanitise_position(k,cn,in,kp)) return 0; + int kp; + for (kp = 0; kp < keyring->contexts[cn]->identities[in]->keypair_count; ++kp) + if (keyring->contexts[cn]->identities[in]->keypairs[kp]->type == keytype) + return kp; + return -1; +} - while(1) { - if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_CRYPTOBOX) +int keyring_next_keytype(const keyring_file *k, int *cn, int *in, int *kp, int keytype) +{ + while (!keyring_sanitise_position(k, cn, in, kp)) { + if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type == keytype) return 1; - - (*kp)++; - if (keyring_sanitise_position(k,cn,in,kp)) return 0; + ++*kp; } return 0; } -int keyring_sanitise_position(keyring_file *k,int *cn,int *in,int *kp) +int keyring_next_identity(const keyring_file *k, int *cn, int *in, int *kp) +{ + return keyring_next_keytype(k, cn, in, kp, KEYTYPE_CRYPTOBOX); +} + +int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp) { if (!k) return 1; /* Sanity check passed in position */ @@ -1314,7 +1324,7 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid) return NULL; } -int keyring_find_sid(keyring_file *k,int *cn,int *in,int *kp, const unsigned char *sid) +int keyring_find_sid(const keyring_file *k,int *cn,int *in,int *kp, const unsigned char *sid) { if (keyring_sanitise_position(k,cn,in,kp)) return 0; diff --git a/rhizome.c b/rhizome.c index ad1eceb8..b567cc27 100644 --- a/rhizome.c +++ b/rhizome.c @@ -239,6 +239,7 @@ int rhizome_manifest_check_file(rhizome_manifest *m_in) if (rhizome_hash_file(m_in,m_in->dataFileName, hexhashbuf)) return WHY("Could not hash file."); memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf); + m_in->fileHashedP = 1; /* Check that payload hash matches manifest */ const char *mhexhash = rhizome_manifest_get(m_in, "filehash", NULL, 0); diff --git a/rhizome.h b/rhizome.h index b0e80f6e..b2b7c93e 100644 --- a/rhizome.h +++ b/rhizome.h @@ -281,6 +281,7 @@ int rhizome_bk_xor(const unsigned char *authorSid, // binary unsigned char *rhizome_bundle_shared_secret(rhizome_manifest *m); int rhizome_extract_privatekey(rhizome_manifest *m, const unsigned char *authorSid); int rhizome_verify_bundle_privatekey(rhizome_manifest *m); +int rhizome_is_self_signed(rhizome_manifest *m); int rhizome_queue_ignore_manifest(rhizome_manifest *m, struct sockaddr_in *peerip,int timeout); int rhizome_ignore_manifest_check(rhizome_manifest *m, diff --git a/rhizome_crypto.c b/rhizome_crypto.c index be829d1b..644a3cd3 100644 --- a/rhizome_crypto.c +++ b/rhizome_crypto.c @@ -121,42 +121,45 @@ int rhizome_find_keypair_bytes(unsigned char *p,unsigned char *s) { } #endif +/* + Return -1 if an error occurs. + Return 0 if the author's private key is located and the XOR is performed successfully. + Return 1 if the author's identity is not in the keyring. + Return 2 if the author's identity is in the keyring but has no rhizome secret. +*/ int rhizome_bk_xor(const unsigned char *authorSid, // binary unsigned char bid[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES], unsigned char bkin[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES], unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES]) { - if (crypto_sign_edwards25519sha512batch_SECRETKEYBYTES> - crypto_hash_sha512_BYTES) + if (crypto_sign_edwards25519sha512batch_SECRETKEYBYTES > crypto_hash_sha512_BYTES) return WHY("BK needs to be longer than it can be"); - int cn=0,in=0,kp=0; - if (!keyring_find_sid(keyring,&cn,&in,&kp,authorSid)) - return WHYF("keyring_find_sid() couldn't find %s. Have you unlocked that identity?", alloca_tohex_sid(authorSid)); - for(kp=0;kpcontexts[cn]->identities[in]->keypair_count;kp++) - if (keyring->contexts[cn]->identities[in]->keypairs[kp]->type==KEYTYPE_RHIZOME) - break; - if (kp>=keyring->contexts[cn]->identities[in]->keypair_count) - return WHY("Identity has no Rhizome Secret"); + if (!keyring_find_sid(keyring,&cn,&in,&kp,authorSid)) { + if (debug & DEBUG_RHIZOME) DEBUG("identity not in keyring"); + return 1; + } + kp = keyring_identity_find_keytype(keyring, cn, in, KEYTYPE_RHIZOME); + if (kp == -1) { + if (debug & DEBUG_RHIZOME) DEBUG("identity has no Rhizome Secret"); + return 2; + } int rs_len=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key_len; - unsigned char *rs=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key; if (rs_len<16||rs_len>1024) - return WHYF("Rhizome Secret is too short or too long (length=%d)",rs_len); - + return WHYF("invalid Rhizome Secret: length=%d", rs_len); + unsigned char *rs=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key; int combined_len=rs_len+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES; unsigned char buffer[combined_len]; bcopy(&rs[0],&buffer[0],rs_len); bcopy(&bid[0],&buffer[rs_len],crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES); unsigned char hash[crypto_hash_sha512_BYTES]; crypto_hash_sha512(hash,buffer,combined_len); - int len=crypto_sign_edwards25519sha512batch_SECRETKEYBYTES; int i; for(i=0;icryptoSignPublic, - bkBytes, - m->cryptoSignSecret)) - return WHY("rhizome_bk_xor() failed"); - return rhizome_verify_bundle_privatekey(m); + switch (rhizome_bk_xor(authorSid, m->cryptoSignPublic, bkBytes, m->cryptoSignSecret)) { + case -1: + return WHY("rhizome_bk_xor() failed"); + case 0: + return rhizome_verify_bundle_privatekey(m); + default: + return WHYF("Rhizome secret for %s not found. (Have you unlocked the identity?)", alloca_tohex_sid(authorSid)); + } +} + +/* + 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. + */ +int rhizome_is_self_signed(rhizome_manifest *m) +{ + char *bk = rhizome_manifest_get(m, "BK", NULL, 0); + if (!bk) { + if (debug & DEBUG_RHIZOME) DEBUGF("missing BK field"); + return 1; + } + unsigned char bkBytes[RHIZOME_BUNDLE_KEY_BYTES]; + if (fromhexstr(bkBytes, bk, RHIZOME_BUNDLE_KEY_BYTES) == -1) + return WHYF("invalid BK field: %s", bk); + int cn = 0, in = 0, kp = 0; + for (; keyring_next_identity(keyring, &cn, &in, &kp); ++kp) { + const unsigned char *authorSid = keyring->contexts[cn]->identities[in]->keypairs[kp]->public_key; + if (debug & DEBUG_RHIZOME) DEBUGF("try identity %s", alloca_tohex(authorSid, SID_SIZE)); + int rkp = keyring_identity_find_keytype(keyring, cn, in, KEYTYPE_RHIZOME); + if (rkp != -1) { + switch (rhizome_bk_xor(authorSid, m->cryptoSignPublic, bkBytes, m->cryptoSignSecret)) { + case -1: + return WHY("rhizome_bk_xor() failed"); + case 0: + D; + if (rhizome_verify_bundle_privatekey(m)) + return 0; // bingo + break; + } + } + } + return 2; // not self signed } /* Verify the validity of the manifest's sccret key. @@ -207,20 +250,16 @@ int rhizome_verify_bundle_privatekey(rhizome_manifest *m) ge25519_scalarmult_base(&gepk, &scsk); ge25519_pack(pk, &gepk); bzero(&scsk,sizeof(scsk)); - if (memcmp(pk, m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES)) { - m->haveSecret=0; - if (1) { - char hex[17]; - rhizome_bytes_to_hex_upper(m->cryptoSignPublic, hex, 8); - WHYF(" stored public key = %s*", hex); - rhizome_bytes_to_hex_upper(pk, hex, 8); - WHYF("computed public key = %s*", hex); - } - return WHY("BID secret key decoded from BK was not valid"); - } else { - m->haveSecret=1; - return 0; + if (memcmp(pk, m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES) == 0) { + m->haveSecret = 1; + return 0; // valid } + m->haveSecret = 0; + if (1) { + DEBUGF(" stored public key = %s*", alloca_tohex(m->cryptoSignPublic, 8)); + DEBUGF("computed public key = %s*", alloca_tohex(pk, 8)); + } + return 1; // invalid #else //!ge25519 /* XXX Need to test key by signing and testing signature validity. */ /* For the time being barf so that the caller does not think we have a validated BK diff --git a/rhizome_database.c b/rhizome_database.c index 4a76d2b1..6cdbdb3f 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -663,6 +663,7 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch cli_puts("version"); cli_delim(":"); cli_puts("date"); cli_delim(":"); cli_puts("_inserttime"); cli_delim(":"); + cli_puts("_selfsigned"); cli_delim(":"); cli_puts("filesize"); cli_delim(":"); cli_puts("filehash"); cli_delim(":"); cli_puts("sender"); cli_delim(":"); @@ -714,12 +715,14 @@ 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; 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_printf("%lld", blob_filesize); cli_delim(":"); cli_puts(blob_filehash ? blob_filehash : ""); cli_delim(":"); cli_puts(blob_sender ? blob_sender : ""); cli_delim(":"); diff --git a/serval.h b/serval.h index 45ffcfbd..bb8b4824 100755 --- a/serval.h +++ b/serval.h @@ -253,10 +253,12 @@ keyring_file *keyring_open_with_pins(const char *pinlist); int keyring_enter_pin(keyring_file *k, const char *pin); int keyring_enter_pins(keyring_file *k, const char *pinlist); int keyring_set_did(keyring_identity *id,char *did,char *name); -int keyring_sanitise_position(keyring_file *k,int *cn,int *in,int *kp); -int keyring_next_identity(keyring_file *k,int *cn,int *in,int *kp); -int keyring_find_did(keyring_file *k,int *cn,int *in,int *kp,char *did); -int keyring_find_sid(keyring_file *k,int *cn,int *in,int *kp, const unsigned char *sid); +int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp); +int keyring_next_keytype(const keyring_file *k, int *cn, int *in, int *kp, int keytype); +int keyring_next_identity(const keyring_file *k,int *cn,int *in,int *kp); +int keyring_identity_find_keytype(const keyring_file *k, int cn, int in, int keytype); +int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did); +int keyring_find_sid(const keyring_file *k,int *cn,int *in,int *kp, const unsigned char *sid); unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid, unsigned char **sas_public); unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid); diff --git a/testdefs.sh b/testdefs.sh index 076d464c..c9ea52ef 100644 --- a/testdefs.sh +++ b/testdefs.sh @@ -51,6 +51,7 @@ set_instance() { # script set_instance_vars() { instance_name="${1:-default}" + echo "# set instance = $instance_name" export instance_dir="$TFWTMP/instance/$instance_name" mkdir -p "$instance_dir" export instance_servald_log="$instance_dir/servald.log" diff --git a/tests/rhizome b/tests/rhizome index f7f6a784..4104bb84 100755 --- a/tests/rhizome +++ b/tests/rhizome @@ -33,6 +33,13 @@ rexp_date='[0-9]\{1,\}' setup_servald_rhizome() { setup_servald + set_instance A + executeOk_servald config set debug.rhizome on + executeOk_servald keyring add + executeOk_servald keyring list + tfw_cat --stdout + othersid=$(replayStdout | sed -ne "1s/^\($rexp_sid\):.*\$/\1/p") + assert --message='other identity known' [ -n "$othersid" ] set_instance executeOk_servald config set debug.rhizome on executeOk_servald keyring add @@ -49,6 +56,10 @@ setup_servald_rhizome() { assert --message='identity 1 known' [ -n "$sid1" ] assert --message='identity 2 known' [ -n "$sid2" ] assert --message='identity 3 known' [ -n "$sid3" ] + assert [ $sid != $othersid ] + assert [ $sid1 != $othersid ] + assert [ $sid2 != $othersid ] + assert [ $sid3 != $othersid ] assert [ $sid != $sid1 ] assert [ $sid != $sid2 ] assert [ $sid != $sid3 ] @@ -57,14 +68,29 @@ setup_servald_rhizome() { assert [ $sid2 != $sid3 ] } +assert_manifest_complete() { + local manifest="$1" + tfw_cat -v "$manifest" + assertGrep "$manifest" "^service=$rexp_service\$" + assertGrep "$manifest" "^id=$rexp_manifestid\$" + assertGrep "$manifest" "^BK=$rexp_bundlekey\$" + assertGrep "$manifest" "^date=$rexp_date\$" + assertGrep "$manifest" "^version=$rexp_version\$" + assertGrep "$manifest" "^filehash=$rexp_filehash\$" + assertGrep "$manifest" "^filesize=$rexp_filesize\$" + if grep -q '^service=file$' "$manifest"; then + assertGrep "$manifest" "^name=" + fi +} + assert_rhizome_list() { assertStdoutLineCount '==' $(($# + 2)) - assertStdoutIs --line=1 -e '10\n' - assertStdoutIs --line=2 -e 'service:id:version:date:_inserttime:filesize:filehash:sender:recipient:name\n' + assertStdoutIs --stderr --line=1 -e '10\n' + assertStdoutIs --stderr --line=2 -e 'service:id:version:date:_inserttime:_selfsigned:filesize:filehash:sender:recipient:name\n' local filename for filename; do unpack_manifest_for_grep "$filename" - assertStdoutGrep --matches=1 "^$re_service:$re_manifestid:.*:$re_filesize:$re_filehash:$re_sender:$re_recipient:$re_name\$" + assertStdoutGrep --stderr --matches=1 "^$re_service:$re_manifestid:.*:1:$re_filesize:$re_filehash:$re_sender:$re_recipient:$re_name\$" done } @@ -72,13 +98,33 @@ assert_stdout_add_file() { [ $# -ge 1 ] || error "missing filename arg" local filename="${1}" unpack_manifest_for_grep "$filename" - assertStdoutLineCount '==' 6 assertStdoutGrep --matches=1 "^service:$re_service\$" - assertStdoutGrep --matches=1 "^name:${2:-$re_name}\$" assertStdoutGrep --matches=1 "^manifestid:$re_manifestid\$" assertStdoutGrep --matches=1 "^secret:$re_secret\$" assertStdoutGrep --matches=1 "^filehash:$re_filehash\$" assertStdoutGrep --matches=1 "^filesize:$re_filesize\$" + if [ $# -ge 2 ] || replayStdout | grep -q '^service=file$'; then + assertStdoutGrep --matches=1 "^name:${2:-$re_name}\$" + assertStdoutLineCount '==' 6 + else + assertStdoutLineCount '==' 5 + fi +} + +assert_stdout_import_bundle() { + [ $# -ge 1 ] || error "missing filename arg" + local filename="${1}" + unpack_manifest_for_grep "$filename" + assertStdoutGrep --matches=1 "^service:$re_service\$" + assertStdoutGrep --matches=1 "^manifestid:$re_manifestid\$" + assertStdoutGrep --matches=1 "^filehash:$re_filehash\$" + assertStdoutGrep --matches=1 "^filesize:$re_filesize\$" + if [ $# -ge 2 ] || replayStdout | grep -q '^service=file$'; then + assertStdoutGrep --matches=1 "^name:${2:-$re_name}\$" + assertStdoutLineCount '==' 5 + else + assertStdoutLineCount '==' 4 + fi } unpack_manifest_for_grep() { @@ -95,7 +141,7 @@ unpack_manifest_for_grep() { re_secret="$rexp_bundlesecret" re_name=$(escape_grep_basic "${filename##*/}") # If there is a manifest file that looks like it matches this payload - # file, then use its file hash to check the rhizome list output. + # 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_manifestid=$(sed -n -e '/^id=/s///p' "$filename.manifest") @@ -198,14 +244,14 @@ setup_InitialEmptyList() { setup_servald_rhizome } test_InitialEmptyList() { - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list } doc_AddNoAuthorNoManifest="Add with no author and no manifest file" setup_AddNoAuthorNoManifest() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "A test file" >file1 echo "Another test file" >file2 @@ -218,10 +264,9 @@ test_AddNoAuthorNoManifest() { doc_AddNoManifest="Add with no manifest file" setup_AddNoManifest() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "A test file" >file1 - echo "Another test file" >file2 } test_AddNoManifest() { executeOk_servald rhizome add file $sid '' file1 @@ -242,7 +287,7 @@ test_AddNoAuthor() { doc_AddNonExistManifest="Add with non-existent manifest file" setup_AddNonExistManifest() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "A test file" >file1 echo "Another test file" >file2 @@ -252,21 +297,15 @@ test_AddNonExistManifest() { executeOk_servald rhizome add file $sid '' file1 file1.manifest assert_stdout_add_file file1 assert [ -r file1.manifest ] - tfw_cat -v file1.manifest + assert_manifest_complete file1.manifest assertGrep file1.manifest '^service=file$' - assertGrep file1.manifest "^BK=$rexp_bundlekey\$" assertGrep file1.manifest '^name=file1$' - assertGrep file1.manifest "^date=$rexp_date\$" - assertGrep file1.manifest "^version=$re_version\$" - assertGrep file1.manifest "^id=$re_manifestid\$" - assertGrep file1.manifest "^filehash=$re_filehash\$" - assertGrep file1.manifest "^filesize=$re_filesize\$" } doc_AddManifest="Add with minimal manifest file" setup_AddManifest() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "A test file" >file1 echo -e 'name=wah\ndate=12345' >file1.manifest @@ -276,40 +315,32 @@ test_AddManifest() { executeOk_servald rhizome add file $sid '' file1 file1.manifest tfw_cat --stdout --stderr -v file1.manifest assert_stdout_add_file file1 wah + assert_manifest_complete file1.manifest assertGrep file1.manifest '^service=file$' - assertGrep file1.manifest "^BK=$rexp_bundlekey\$" assertGrep file1.manifest '^name=wah$' - assertGrep file1.manifest "^version=$re_version\$" assertGrep file1.manifest '^date=12345$' - assertGrep file1.manifest "^id=$re_manifestid\$" - assertGrep file1.manifest "^filehash=$re_filehash\$" - assertGrep file1.manifest "^filesize=$re_filesize\$" } doc_AddEmpty="Add with empty payload" setup_AddEmpty() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list } test_AddEmpty() { executeOk_servald rhizome add file $sid '' '' .manifest tfw_cat --stdout --stderr -v .manifest assert_stdout_add_file '' + assert_manifest_complete file1.manifest assertGrep .manifest '^service=file$' - assertGrep .manifest "^BK=$rexp_bundlekey\$" assertGrep .manifest '^name=$' - assertGrep .manifest "^version=$re_version\$" - assertGrep .manifest "^date=$rexp_date\$" - assertGrep .manifest "^id=$re_manifestid\$" - assertGrep .manifest "^filehash=$re_filehash\$" assertGrep .manifest '^filesize=0$' } doc_AddThenList="List contains one file after one add" setup_AddThenList() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "A test file" >file1 echo "Another test file" >file2 @@ -317,11 +348,11 @@ setup_AddThenList() { test_AddThenList() { # Add first file executeOk_servald rhizome add file $sid '' file1 file1.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 # Add second file executeOk_servald rhizome add file $sid '' file2 file2.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 } @@ -330,7 +361,7 @@ setup_AddThenExtractManifest() { setup_servald_rhizome echo "A test file" >file1 executeOk_servald rhizome add file $sid '' file1 file1.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 extract_manifest_id manifestid file1.manifest extract_manifest_version version file1.manifest @@ -382,7 +413,7 @@ setup_AddThenExtractFile() { echo "A test file" >file1 executeOk_servald rhizome add file $sid '' file1 file1.manifest tfw_cat --stderr - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 extract_manifest_filehash filehash file1.manifest } @@ -425,7 +456,7 @@ test_ExtractFileInvalidID() { doc_AddDuplicate="Add same manifest detects duplicate" setup_AddDuplicate() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "A test file" >file1 echo "Another test file" >file2 @@ -437,7 +468,7 @@ setup_AddDuplicate() { executeOk_servald rhizome add file $sid '' file2 file2.manifest extract_stdout_secret file2_secret # Make sure they are both in the list. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 } test_AddDuplicate() { @@ -447,7 +478,7 @@ test_AddDuplicate() { execute --exit-status=2 $servald rhizome add file $sid '' file1 file1.manifestA assert [ -s file1.manifestA ] assert_stdout_add_file file1 - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 strip_signatures file1.manifest file1.manifestA assert diff file1.manifest file1.manifestA @@ -455,7 +486,7 @@ test_AddDuplicate() { execute --exit-status=2 $servald rhizome add file $sid '' file2 file2.manifestA assert [ -s file2.manifestA ] assert_stdout_add_file file2 - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 strip_signatures file2.manifest file2.manifestA assert diff file2.manifest file2.manifestA @@ -473,7 +504,7 @@ test_AddMismatched() { assertExitStatus '!=' 0 assert cmp file1.manifest file1_2.manifest # And rhizome store should be unchanged. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 } @@ -496,7 +527,7 @@ test_AddUpdateSameVersion() { tfw_cat -v file1_2.manifest assert cmp file1_2.manifest file1_2.manifest.orig # And rhizome store should be unchanged. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 } @@ -514,7 +545,7 @@ test_AddUpdateNewVersion() { assert_stdout_add_file file1_2 file1 assert_manifest_newer file1.manifest file1_2.manifest # Rhizome store contents reflect new payload. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1_2 file2 } @@ -529,7 +560,7 @@ test_AddUpdateNoAuthor() { tfw_cat --stderr assertExitStatus '!=' 0 # Rhizome store contents have old payload. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 } @@ -542,7 +573,7 @@ test_AddUpdateNoAuthorWithSecret() { executeOk_servald rhizome add file $sid '' file1_2 file1_2.manifest "$file1_secret" tfw_cat --stderr # Rhizome store contents have new payload. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1_2 file2 } @@ -558,7 +589,7 @@ test_AddUpdateAutoVersion() { executeOk_servald rhizome add file $sid '' file1_2 file1_2.manifest assert_manifest_newer file1.manifest file1_2.manifest # Rhizome store contents reflect new payload. - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1_2 file2 } @@ -581,7 +612,7 @@ setup_AddMeshMSCreate() { } test_AddMeshMSCreate() { executeOk_servald rhizome add file $sid '' file1 file1.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 extract_manifest_filehash filehash file1.manifest executeOk_servald rhizome extract file $filehash file1x @@ -596,7 +627,7 @@ setup_AddMeshMSGrow() { } test_AddMeshMSGrow() { executeOk_servald rhizome add file $sid '' file1 file1.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 extract_manifest_id id file1.manifest extract_manifest_filehash filehash file1.manifest @@ -607,7 +638,7 @@ test_AddMeshMSGrow() { echo -e "id=$id\nBK=$bk\nservice=MeshMS1\nsender=$sid\nrecipient=$sid1" >file1.manifest echo "Message$m" >>file1 executeOk_servald rhizome add file $sid '' file1 file1.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 extract_manifest_id idx file1.manifest extract_manifest_filehash filehashx file1.manifest @@ -638,7 +669,7 @@ test_AddMeshMSMissingSender() { doc_AddMeshMSMissingRecipient="Add MeshMS without recipient fails" setup_AddMeshMSMissingRecipient() { setup_servald_rhizome - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list echo "Message1" >file1 echo -e "service=MeshMS1\nsender=$sid" >file1.manifest @@ -648,15 +679,17 @@ test_AddMeshMSMissingRecipient() { assertExitStatus '!=' 0 } -doc_AddMeshMSMissingSender="Add MeshMS without author uses sender" -setup_AddMeshMSMissingSender() { +doc_AddMeshMSMissingAuthor="Add MeshMS without author uses sender" +setup_AddMeshMSMissingAuthor() { setup_servald_rhizome echo "Message1" >file1 echo -e "service=MeshMS1\nsender=$sid\nrecipient=$sid1" >file1.manifest } -test_AddMeshMSMissingSender() { +test_AddMeshMSMissingAuthor() { executeOk_servald rhizome add file '' '' file1 file1.manifest - executeOk_servald rhizome list + assert_stdout_add_file file1 + assert_manifest_complete file1.manifest + executeOk_servald rhizome list '' assert_rhizome_list file1 } @@ -675,38 +708,54 @@ setup_ListMeshMSFilter() { executeOk_servald rhizome add file '' '' file2 file2.manifest executeOk_servald rhizome add file '' '' file3 file3.manifest executeOk_servald rhizome add file '' '' file4 file4.manifest - executeOk_servald rhizome list + executeOk_servald rhizome list '' assert_rhizome_list file1 file2 file3 file4 } test_ListMeshMSFilter() { - executeOk_servald rhizome list file + executeOk_servald rhizome list '' file assert_rhizome_list - executeOk_servald rhizome list MeshMS1 + executeOk_servald rhizome list '' MeshMS1 assert_rhizome_list file1 file2 file3 file4 - executeOk_servald rhizome list '' $sid - assert_rhizome_list file1 file2 file3 - executeOk_servald rhizome list '' $sid1 - assert_rhizome_list file4 - executeOk_servald rhizome list '' $sid2 - assert_rhizome_list - executeOk_servald rhizome list '' $sid3 - assert_rhizome_list executeOk_servald rhizome list '' '' $sid - assert_rhizome_list + assert_rhizome_list file1 file2 file3 executeOk_servald rhizome list '' '' $sid1 - assert_rhizome_list file1 + assert_rhizome_list file4 executeOk_servald rhizome list '' '' $sid2 - assert_rhizome_list file2 file4 - executeOk_servald rhizome list file '' $sid2 assert_rhizome_list executeOk_servald rhizome list '' '' $sid3 - assert_rhizome_list file3 - executeOk_servald rhizome list '' $sid $sid3 - assert_rhizome_list file3 - executeOk_servald rhizome list '' $sid1 $sid3 assert_rhizome_list - executeOk_servald rhizome list '' $sid1 $sid2 + executeOk_servald rhizome list '' '' '' $sid + assert_rhizome_list + executeOk_servald rhizome list '' '' '' $sid1 + assert_rhizome_list file1 + executeOk_servald rhizome list '' '' '' $sid2 + assert_rhizome_list file2 file4 + executeOk_servald rhizome list '' file '' $sid2 + assert_rhizome_list + executeOk_servald rhizome list '' '' '' $sid3 + assert_rhizome_list file3 + executeOk_servald rhizome list '' '' $sid $sid3 + assert_rhizome_list file3 + executeOk_servald rhizome list '' '' $sid1 $sid3 + assert_rhizome_list + executeOk_servald rhizome list '' '' $sid1 $sid2 assert_rhizome_list file4 } +doc_ImportForeignBundle="Can import a bundle created by another instance" +setup_ImportForeignBundle() { + setup_servald_rhizome + set_instance A + echo "Hello from A" >fileA + executeOk_servald rhizome add file $othersid '' fileA fileA.manifest + assert_stdout_add_file fileA + set_instance +} +test_ImportForeignBundle() { + executeOk_servald rhizome import bundle fileA fileA.manifest + assert_stdout_import_bundle fileA + executeOk_servald rhizome list '' + assert_rhizome_list fileA +} + runTests "$@"