/* * deliver_content is used to deliver a previously-buffered * ContentObject to the client. */ static enum ccn_upcall_res deliver_content(struct ccn *h, struct bulkdata *b) { struct ccn_upcall_info info = {0}; struct ccn_parsed_ContentObject obj = {0}; struct pending *p = b->first; int res; enum ccn_upcall_res ans; assert(p != NULL && p->x == b->next_expected && p->content_ccnb != NULL); info.pco = &obj; info.content_comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(p->content_ccnb, p->content_size, &obj, info.content_comps); assert(res >= 0); info.content_ccnb = p->content_ccnb; info.matched_comps = info.content_comps->n - 2; /* XXX - we have no matched interest to present */ ans = (*b->client->p)(b->client, CCN_UPCALL_CONTENT, &info); // XXX - check for refusal info.content_ccnb = NULL; free(p->content_ccnb); p->content_ccnb = NULL; p->content_size = 0; ccn_indexbuf_destroy(&info.content_comps); if (ans == CCN_UPCALL_RESULT_OK) { struct ccn_closure *old = &p->closure; if ((--(old->refcount)) == 0) { info.pco = NULL; (old->p)(old, CCN_UPCALL_FINAL, &info); } } return(ans); }
/** * Parses content object and sets content->flatname */ static int r_store_set_flatname(struct ccnr_handle *h, struct content_entry *content, struct ccn_parsed_ContentObject *pco) { int res; struct ccn_charbuf *flatname = NULL; const unsigned char *msg = NULL; size_t size; msg = r_store_content_base(h, content); size = content->size; if (msg == NULL) goto Bail; flatname = ccn_charbuf_create(); if (flatname == NULL) goto Bail; res = ccn_parse_ContentObject(msg, size, pco, NULL); if (res < 0) { ccnr_msg(h, "error parsing ContentObject - code %d", res); goto Bail; } ccn_digest_ContentObject(msg, pco); if (pco->digest_bytes != 32) goto Bail; res = ccn_flatname_from_ccnb(flatname, msg, size); if (res < 0) goto Bail; res = ccn_flatname_append_component(flatname, pco->digest, pco->digest_bytes); if (res < 0) goto Bail; content->flatname = flatname; flatname = NULL; return(0); Bail: ccn_charbuf_destroy(&flatname); return(-1); }
/** * Verify a signed interest * * params are as returned in upcall info structure * key is what should be used to verify * * returns: * -1 for parsing error * 0 for incorrect signature / unverified * 1 for proper verification * */ int verify_signed_interest(const unsigned char *ccnb, const struct ccn_indexbuf *comps, size_t num_comps, size_t start, size_t stop, struct ccn_pkey* key) { fprintf(stderr,"verifying signed interest...\n"); // What is info->interest_comps->n ? //fprintf(stderr, "Interest components %d\n", (int) info->interest_comps->n); unsigned char* comp; size_t size; int res; // Create a charbuf with the matched interest name incl nonce struct ccn_charbuf* name = ccn_charbuf_create(); ccn_name_init(name); res = ccn_name_append_components(name, ccnb, start, stop); // Last component, should be the signature res = ccn_name_comp_get(ccnb, comps, num_comps, (const unsigned char**)&comp, &size); if (memcmp(NS_SIGNATURE, comp, NS_SIGNATURE_LEN) != 0) { fprintf(stderr, "debug: Last component not tagged as a signature.\n"); return(-1); } // Parse our nameless, dataless content object that follows the namespace // and replace the name with the implicit name from the interest, so that // we can use the standard signature verification calls. Could be made // more efficient with different library calls. struct ccn_charbuf* co_with_name = ccn_charbuf_create(); unsigned char* co = &comp[NS_SIGNATURE_LEN]; replace_name(co_with_name, co, size-NS_SIGNATURE_LEN, name); //fprintf(stderr, "replace_name == %d (%s)\n", res, (res==0)?"ok":"fail"); // For now, use standard routines to verify signature struct ccn_parsed_ContentObject pco = {0}; fprintf(stderr,"verifying signed interest...2\n"); res = ccn_parse_ContentObject(co_with_name->buf, co_with_name->length, &pco, NULL); if (!res) { // Verify the signature against the authorized public key given to us, passed through to the handler res = ccn_verify_signature(co_with_name->buf, pco.offset[CCN_PCO_E], &pco, key ); } else { fprintf(stderr, "debug: Constructed content object parse failed (res==%d)\n", res); } fprintf(stderr,"verifying signed interest...3\n"); ccn_charbuf_destroy(&co_with_name); ccn_charbuf_destroy(&name); return (res); }
void ParsedContentObject::init(const unsigned char *data, size_t len) { readRaw(m_bytes, data, len); m_comps = ccn_indexbuf_create(); int res = ccn_parse_ContentObject(head (m_bytes), len, &m_pco, m_comps); if (res < 0) { boost::throw_exception(MisformedContentObjectException()); } }
int decode_message(struct ccn_charbuf *message, struct path * name_path, char *data, size_t len, const void *verkey) { struct ccn_parsed_ContentObject content; struct ccn_indexbuf *comps = ccn_indexbuf_create(); const unsigned char * content_value; size_t content_length; int res = 0; int i; memset(&content, 0x33, sizeof(content)); if (ccn_parse_ContentObject(message->buf, message->length, &content, comps) != 0) { printf("Decode failed to parse object\n"); res = -1; } if (comps->n-1 != name_path->count) { printf("Decode got wrong number of path components: %d vs. %d\n", (int)(comps->n-1), name_path->count); res = -1; } for (i=0; i<name_path->count; i++) { if (ccn_name_comp_strcmp(message->buf, comps, i, name_path->comps[i]) != 0) { printf("Decode mismatch on path component %d\n", i); res = -1; } } if (ccn_content_get_value(message->buf, message->length, &content, &content_value, &content_length) != 0) { printf("Cannot retrieve content value\n"); res = -1; } else if (content_length != len) { printf("Decode mismatch on content length %d vs. %d\n", (int)content_length, (int)len); res = -1; } else if (memcmp(content_value, data, len) != 0) { printf("Decode mismatch of content\n"); res = -1; } if (ccn_verify_signature(message->buf, message->length, &content, verkey) != 1) { printf("Signature did not verify\n"); res = -1; } ccn_indexbuf_destroy(&comps); return res; }
// replace_name() // Helper function to replace names in content objects // Could build another version that works on already parsed content objects // But as seen below it would be better to use a modified encoding call that // didn't include the name at all. // int replace_name(struct ccn_charbuf* dest, unsigned char* src, size_t src_size, struct ccn_charbuf* name) { struct ccn_parsed_ContentObject* pco = (struct ccn_parsed_ContentObject*) calloc(sizeof(struct ccn_parsed_ContentObject), 1); int res = 0; res = ccn_parse_ContentObject(src,src_size, pco, NULL); if (res < 0) { free(pco); return (res); } ccn_charbuf_append_tt(dest, CCN_DTAG_ContentObject, CCN_DTAG); ccn_charbuf_append(dest, &src[pco->offset[CCN_PCO_B_Signature]], pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]); ccn_charbuf_append_charbuf(dest, name); // Already tagged ccn_charbuf_append(dest, &src[pco->offset[CCN_PCO_B_SignedInfo]], pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]); ccnb_append_tagged_blob(dest, CCN_DTAG_Content, NULL, 0); ccn_charbuf_append_closer(dest); free(pco); return (0); }
static int parse_ContentObject(PyObject *py_content_object) { struct content_object_data *context; struct ccn_charbuf *content_object; int r; assert(CCNObject_IsValid(CONTENT_OBJECT, py_content_object)); context = PyCapsule_GetContext(py_content_object); assert(context); if (context->pco) free(context->pco); ccn_indexbuf_destroy(&context->comps); /* * no error happens between deallocation and following line, so I'm not * setting context->pco to NULL */ context->pco = calloc(1, sizeof(struct ccn_parsed_ContentObject)); JUMP_IF_NULL_MEM(context->pco, error); context->comps = ccn_indexbuf_create(); JUMP_IF_NULL_MEM(context->comps, error); content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object); r = ccn_parse_ContentObject(content_object->buf, content_object->length, context->pco, context->comps); if (r < 0) { PyErr_SetString(g_PyExc_CCNContentObjectError, "Unable to parse the" " ContentObject"); goto error; } return 0; error: if (context->pco) { free(context->pco); context->pco = NULL; } ccn_indexbuf_destroy(&context->comps); return -1; }
PUBLIC int r_store_content_field_access(struct ccnr_handle *h, struct content_entry *content, enum ccn_dtag dtag, const unsigned char **bufp, size_t *sizep) { int res = -1; const unsigned char *content_msg; struct ccn_parsed_ContentObject pco = {0}; content_msg = r_store_content_base(h, content); if (content_msg == NULL) return(-1); res = ccn_parse_ContentObject(content_msg, content->size, &pco, NULL); if (res < 0) return(-1); if (dtag == CCN_DTAG_Content) res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg, pco.offset[CCN_PCO_B_Content], pco.offset[CCN_PCO_E_Content], bufp, sizep); return(res); }
static int dissect_ccn_contentobject(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *signature_tree; proto_tree *name_tree; proto_tree *signedinfo_tree; proto_tree *content_tree; proto_item *titem; struct ccn_parsed_ContentObject co; struct ccn_parsed_ContentObject *pco = &co; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; size_t blob_size; const unsigned char *blob; int l; unsigned int i; double dt; nstime_t timestamp; int res; comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnb, ccnb_size, pco, comps); if (res < 0) return (-1); /* Signature */ l = pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]; titem = proto_tree_add_item(tree, hf_ccn_signature, tvb, pco->offset[CCN_PCO_B_Signature], l, FALSE); signature_tree = proto_item_add_subtree(titem, ett_signature); /* DigestAlgorithm */ l = pco->offset[CCN_PCO_E_DigestAlgorithm] - pco->offset[CCN_PCO_B_DigestAlgorithm]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, ccnb, pco->offset[CCN_PCO_B_DigestAlgorithm], pco->offset[CCN_PCO_E_DigestAlgorithm], &blob, &blob_size); titem = proto_tree_add_item(signature_tree, hf_ccn_signaturedigestalg, tvb, blob - ccnb, blob_size, FALSE); } /* Witness */ l = pco->offset[CCN_PCO_E_Witness] - pco->offset[CCN_PCO_B_Witness]; if (l > 0) { /* add the witness item to the signature tree */ } /* Signature bits */ l = pco->offset[CCN_PCO_E_SignatureBits] - pco->offset[CCN_PCO_B_SignatureBits]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, ccnb, pco->offset[CCN_PCO_B_SignatureBits], pco->offset[CCN_PCO_E_SignatureBits], &blob, &blob_size); titem = proto_tree_add_bytes(signature_tree, hf_ccn_signaturebits, tvb, blob - ccnb, blob_size, blob); } /* /Signature */ /* Name */ l = pco->offset[CCN_PCO_E_Name] - pco->offset[CCN_PCO_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pco->offset[CCN_PCO_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); /* Name Components */ for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* /Name */ /* SignedInfo */ l = pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]; titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_SignedInfo], l, "SignedInfo"); signedinfo_tree = proto_item_add_subtree(titem, ett_signedinfo); /* PublisherPublicKeyDigest */ l = pco->offset[CCN_PCO_E_PublisherPublicKeyDigest] - pco->offset[CCN_PCO_B_PublisherPublicKeyDigest]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, ccnb, pco->offset[CCN_PCO_B_PublisherPublicKeyDigest], pco->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); titem = proto_tree_add_bytes(signedinfo_tree, hf_ccn_publisherpublickeydigest, tvb, blob - ccnb, blob_size, blob); } /* Timestamp */ l = pco->offset[CCN_PCO_E_Timestamp] - pco->offset[CCN_PCO_B_Timestamp]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, ccnb, pco->offset[CCN_PCO_B_Timestamp], pco->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); dt = 0.0; for (i = 0; i < blob_size; i++) dt = dt * 256.0 + (double)blob[i]; dt /= 4096.0; timestamp.secs = dt; /* truncates */ timestamp.nsecs = (dt - (double) timestamp.secs) * 1000000000.0; titem = proto_tree_add_time(signedinfo_tree, hf_ccn_timestamp, tvb, blob - ccnb, blob_size, ×tamp); } /* Type */ l = pco->offset[CCN_PCO_E_Type] - pco->offset[CCN_PCO_B_Type]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Type, ccnb, pco->offset[CCN_PCO_B_Type], pco->offset[CCN_PCO_E_Type], &blob, &blob_size); titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, tvb, blob - ccnb, blob_size, pco->type); } else { titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, NULL, 0, 0, pco->type); } /* FreshnessSeconds */ l = pco->offset[CCN_PCO_E_FreshnessSeconds] - pco->offset[CCN_PCO_B_FreshnessSeconds]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds], &blob, &blob_size); i = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds]); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_freshnessseconds, tvb, blob - ccnb, blob_size, i); } /* FinalBlockID */ l = pco->offset[CCN_PCO_E_FinalBlockID] - pco->offset[CCN_PCO_B_FinalBlockID]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, pco->offset[CCN_PCO_B_FinalBlockID], pco->offset[CCN_PCO_E_FinalBlockID], &blob, &blob_size); titem = proto_tree_add_item(signedinfo_tree, hf_ccn_finalblockid, tvb, blob - ccnb, blob_size, FALSE); } /* TODO: KeyLocator */ /* /SignedInfo */ /* Content */ l = pco->offset[CCN_PCO_E_Content] - pco->offset[CCN_PCO_B_Content]; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnb, pco->offset[CCN_PCO_B_Content], pco->offset[CCN_PCO_E_Content], &blob, &blob_size); titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_Content], l, "Content: %d bytes", blob_size); if (blob_size > 0) { content_tree = proto_item_add_subtree(titem, ett_content); titem = proto_tree_add_item(content_tree, hf_ccn_contentdata, tvb, blob - ccnb, blob_size, FALSE); } return (ccnb_size); }
/** * Common interest handler */ PUBLIC enum ccn_upcall_res ccnr_answer_req(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { struct ccn_charbuf *msg = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *keylocator = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *reply_body = NULL; struct ccnr_handle *ccnr = NULL; int res = 0; int morecomps = 0; const unsigned char *final_comp = NULL; size_t final_size = 0; switch (kind) { case CCN_UPCALL_FINAL: free(selfp); return(CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST: break; case CCN_UPCALL_CONSUMED_INTEREST: return(CCN_UPCALL_RESULT_OK); default: return(CCN_UPCALL_RESULT_ERR); } ccnr = (struct ccnr_handle *)selfp->data; if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE)) ccnr_debug_ccnb(ccnr, __LINE__, "ccnr_answer_req", NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]); morecomps = selfp->intdata & MORECOMPS_MASK; if ((info->pi->answerfrom & CCN_AOK_NEW) == 0 && selfp->intdata != OP_SERVICE) return(CCN_UPCALL_RESULT_OK); if (info->matched_comps >= info->interest_comps->n) goto Bail; if ((selfp->intdata & OPER_MASK) != OP_SERVICE && info->pi->prefix_comps != info->matched_comps + morecomps) goto Bail; if (morecomps == 1) { res = ccn_name_comp_get(info->interest_ccnb, info->interest_comps, info->matched_comps, &final_comp, &final_size); if (res < 0) goto Bail; } if ((selfp->intdata & MUST_VERIFY) != 0) { struct ccn_parsed_ContentObject pco = {0}; // XXX - probably should check for message origin BEFORE verify res = ccn_parse_ContentObject(final_comp, final_size, &pco, NULL); if (res < 0) { ccnr_debug_ccnb(ccnr, __LINE__, "co_parse_failed", NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]); goto Bail; } res = ccn_verify_content(info->h, final_comp, &pco); if (res != 0) { ccnr_debug_ccnb(ccnr, __LINE__, "co_verify_failed", NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]); goto Bail; } } switch (selfp->intdata & OPER_MASK) { case OP_SERVICE: if (ccnr->service_ccnb == NULL) ccnr->service_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_LOCAL_URI, 600); if (ccn_content_matches_interest( ccnr->service_ccnb->buf, ccnr->service_ccnb->length, 1, NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi )) { ccn_put(info->h, ccnr->service_ccnb->buf, ccnr->service_ccnb->length); res = CCN_UPCALL_RESULT_INTEREST_CONSUMED; goto Finish; } // XXX this needs refactoring. if (ccnr->neighbor_ccnb == NULL) ccnr->neighbor_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_NEIGHBOR_URI, 5); if (ccn_content_matches_interest( ccnr->neighbor_ccnb->buf, ccnr->neighbor_ccnb->length, 1, NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi )) { ccn_put(info->h, ccnr->neighbor_ccnb->buf, ccnr->neighbor_ccnb->length); res = CCN_UPCALL_RESULT_INTEREST_CONSUMED; goto Finish; } if (ccn_content_matches_interest( ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length, 1, NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi )) { ccn_put(info->h, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length); res = CCN_UPCALL_RESULT_INTEREST_CONSUMED; goto Finish; } goto Bail; break; default: // No other OP_xxx are supported here goto Bail; } Bail: res = CCN_UPCALL_RESULT_ERR; Finish: ccn_charbuf_destroy(&msg); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&keylocator); ccn_charbuf_destroy(&reply_body); ccn_charbuf_destroy(&signed_info); return(res); }
int main (int argc, char *argv[]) { struct ccn_charbuf *buffer = ccn_charbuf_create(); struct ccn_charbuf *signed_info = ccn_charbuf_create(); struct ccn_skeleton_decoder dd = {0}; ssize_t res; char *outname = NULL; int fd; int result = 0; char * contents[] = {"INVITE sip:[email protected] SIP/2.0\nVia: SIP/2.0/UDP 127.0.0.1:5060;rport;branch=z9hG4bK519044721\nFrom: <sip:[email protected]>;tag=2105643453\nTo: Test User <sip:[email protected]>\nCall-ID: [email protected]\nCSeq: 20 INVITE\nContact: <sip:[email protected]:5060>\nMax-Forwards: 70\nUser-Agent: Linphone-1.7.1/eXosip\nSubject: Phone call\nExpires: 120\nAllow: INVITE, ACK, CANCEL, BYE, OPTIONS, REFER, SUBSCRIBE, NOTIFY, MESSAGE\nContent-Type: application/sdp\nContent-Length: 448\n\nv=0\no=jthornto 123456 654321 IN IP4 127.0.0.1\ns=A conversation\nc=IN IP4 127.0.0.1\nt=0 0\nm=audio 7078 RTP/AVP 111 110 0 3 8 101\na=rtpmap:111 speex/16000/1\na=rtpmap:110 speex/8000/1\na=rtpmap:0 PCMU/8000/1\na=rtpmap:3 GSM/8000/1\na=rtpmap:8 PCMA/8000/1\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-11\nm=video 9078 RTP/AVP 97 98 99\na=rtpmap:97 theora/90000\na=rtpmap:98 H263-1998/90000\na=fmtp:98 CIF=1;QCIF=1\na=rtpmap:99 MP4V-ES/90000\n", "Quaer #%2d zjduer badone", "", NULL}; char * paths[] = { "/sip/protocol/parc.com/domain/foo/principal/invite/verb/[email protected]/id", "/d/e/f", "/zero/length/content", NULL}; struct path * cur_path = NULL; struct ccn_keystore *keystore = ccn_keystore_create(); char *home = getenv("HOME"); char *keystore_suffix = "/.ccnx/.ccnx_keystore"; char *keystore_name = NULL; int i; if (argc == 3 && strcmp(argv[1], "-o") == 0) { outname = argv[2]; } else { printf("Usage: %s -o <outfilename>\n", argv[0]); exit(1); } if (home == NULL) { printf("Unable to determine home directory for keystore\n"); exit(1); } keystore_name = calloc(1, strlen(home) + strlen(keystore_suffix) + 1); strcat(keystore_name, home); strcat(keystore_name, keystore_suffix); if (0 != ccn_keystore_init(keystore, keystore_name, "Th1s1sn0t8g00dp8ssw0rd.")) { printf("Failed to initialize keystore\n"); exit(1); } printf("Creating signed_info\n"); res = ccn_signed_info_create(signed_info, /*pubkeyid*/ccn_keystore_public_key_digest(keystore), /*publisher_key_id_size*/ccn_keystore_public_key_digest_length(keystore), /*datetime*/NULL, /*type*/CCN_CONTENT_GONE, /*freshness*/ 42, /*finalblockid*/NULL, /*keylocator*/NULL); if (res < 0) { printf("Failed to create signed_info!\n"); } res = ccn_skeleton_decode(&dd, signed_info->buf, signed_info->length); if (!(res == signed_info->length && dd.state == 0)) { printf("Failed to decode signed_info! Result %d State %d\n", (int)res, dd.state); result = 1; } memset(&dd, 0, sizeof(dd)); printf("Done with signed_info\n"); printf("Encoding sample message data length %d\n", (int)strlen(contents[0])); cur_path = path_create(paths[0]); if (encode_message(buffer, cur_path, contents[0], strlen(contents[0]), signed_info, ccn_keystore_private_key(keystore))) { printf("Failed to encode message!\n"); } else { printf("Encoded sample message length is %d\n", (int)buffer->length); res = ccn_skeleton_decode(&dd, buffer->buf, buffer->length); if (!(res == buffer->length && dd.state == 0)) { printf("Failed to decode! Result %d State %d\n", (int)res, dd.state); result = 1; } if (outname != NULL) { fd = open(outname, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); if (fd == -1) perror(outname); res = write(fd, buffer->buf, buffer->length); close(fd); } if (decode_message(buffer, cur_path, contents[0], strlen(contents[0]), ccn_keystore_public_key(keystore)) != 0) { result = 1; } printf("Expect signature verification failure: "); if (buffer->length >= 20) buffer->buf[buffer->length - 20] += 1; if (decode_message(buffer, cur_path, contents[0], strlen(contents[0]), ccn_keystore_public_key(keystore)) == 0) { result = 1; } } path_destroy(&cur_path); ccn_charbuf_destroy(&buffer); printf("Done with sample message\n"); /* Now exercise as unit tests */ for (i = 0; paths[i] != NULL && contents[i] != NULL; i++) { printf("Unit test case %d\n", i); cur_path = path_create(paths[i]); buffer = ccn_charbuf_create(); if (encode_message(buffer, cur_path, contents[i], strlen(contents[i]), signed_info, ccn_keystore_private_key(keystore))) { printf("Failed encode\n"); result = 1; } else if (decode_message(buffer, cur_path, contents[i], strlen(contents[i]), ccn_keystore_public_key(keystore))) { printf("Failed decode\n"); result = 1; } path_destroy(&cur_path); ccn_charbuf_destroy(&buffer); } /* Test the uri encode / decode routines */ init_all_chars_percent_encoded(); const char *uri_tests[] = { "_+4", "ccnx:/this/is/a/test", "", "ccnx:/this/is/a/test", ".+4", "../test2?x=2", "?x=2", "ccnx:/this/is/a/test2", "_-X", "../should/error", "", "", "_+2", "/missing/scheme", "", "ccnx:/missing/scheme", ".+0", "../../../../../././#/", "#/", "ccnx:/", ".+1", all_chars_percent_encoded, "", all_chars_percent_encoded_canon, "_+1", all_chars_percent_encoded_canon, "", all_chars_percent_encoded_canon, ".+4", "ccnx:/.../.%2e./...././.....///?...", "?...", "ccnx:/.../.../..../.....", "_-X", "/%3G?bad-pecent-encode", "", "", "_-X", "/%3?bad-percent-encode", "", "", "_-X", "/%#bad-percent-encode", "", "", "_+3", "ccnx://[email protected]:42/ignore/host/part of uri", "", "ccnx:/ignore/host/part%20of%20uri", NULL, NULL, NULL, NULL }; const char **u; struct ccn_charbuf *uri_out = ccn_charbuf_create(); buffer = ccn_charbuf_create(); for (u = uri_tests; *u != NULL; u += 4, i++) { printf("Unit test case %d\n", i); if (u[0][0] != '.') buffer->length = 0; res = ccn_name_from_uri(buffer, u[1]); if (!expected_res(res, u[0][1])) { printf("Failed: ccn_name_from_uri wrong res %d\n", (int)res); result = 1; } if (res >= 0) { if (res > strlen(u[1])) { printf("Failed: ccn_name_from_uri long res %d\n", (int)res); result = 1; } else if (0 != strcmp(u[1] + res, u[2])) { printf("Failed: ccn_name_from_uri expecting leftover '%s', got '%s'\n", u[2], u[1] + res); result = 1; } uri_out->length = 0; res = ccn_uri_append(uri_out, buffer->buf, buffer->length, 1); if (!expected_res(res, u[0][2])) { printf("Failed: ccn_uri_append wrong res %d\n", (int)res); result = 1; } if (res >= 0) { if (uri_out->length != strlen(u[3])) { printf("Failed: ccn_uri_append produced wrong number of characters\n"); result = 1; } ccn_charbuf_reserve(uri_out, 1)[0] = 0; if (0 != strcmp((const char *)uri_out->buf, u[3])) { printf("Failed: ccn_uri_append produced wrong output\n"); printf("Expected: %s\n", u[3]); printf(" Actual: %s\n", (const char *)uri_out->buf); result = 1; } } } } ccn_charbuf_destroy(&buffer); ccn_charbuf_destroy(&uri_out); printf("Name marker tests\n"); do { const char *expected_uri = "ccnx:/example.com/.../%01/%FE/%01%02%03%04%05%06%07%08/%FD%10%10%10%10%1F%FF/%00%81"; const char *expected_chopped_uri = "ccnx:/example.com/.../%01/%FE"; const char *expected_bumped_uri = "ccnx:/example.com/.../%01/%FF"; const char *expected_bumped2_uri = "ccnx:/example.com/.../%01/%00%00"; printf("Unit test case %d\n", i++); buffer = ccn_charbuf_create(); uri_out = ccn_charbuf_create(); res = ccn_name_init(buffer); res |= ccn_name_append_str(buffer, "example.com"); res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0); res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 1); res |= ccn_name_append_numeric(buffer, 0xFE, 0); res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0x0102030405060708ULL); res |= ccn_name_append_numeric(buffer, CCN_MARKER_VERSION, 0x101010101FFFULL); res |= ccn_name_append_numeric(buffer, CCN_MARKER_SEQNUM, 129); res |= ccn_uri_append(uri_out, buffer->buf, buffer->length, 1); if (res < 0) { printf("Failed: name marker tests had negative res\n"); result = 1; } if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_uri)) { printf("Failed: name marker tests produced wrong output\n"); printf("Expected: %s\n", expected_uri); printf(" Actual: %s\n", (const char *)uri_out->buf); result = 1; } res = ccn_name_chop(buffer, NULL, 100); if (res != -1) { printf("Failed: ccn_name_chop did not produce error \n"); result = 1; } res = ccn_name_chop(buffer, NULL, 4); if (res != 4) { printf("Failed: ccn_name_chop got wrong length\n"); result = 1; } uri_out->length = 0; ccn_uri_append(uri_out, buffer->buf, buffer->length, 1); if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_chopped_uri)) { printf("Failed: ccn_name_chop botch\n"); printf("Expected: %s\n", expected_chopped_uri); printf(" Actual: %s\n", (const char *)uri_out->buf); result = 1; } res = ccn_name_next_sibling(buffer); if (res != 4) { printf("Failed: ccn_name_next_sibling got wrong length\n"); result = 1; } uri_out->length = 0; ccn_uri_append(uri_out, buffer->buf, buffer->length, 1); if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_bumped_uri)) { printf("Failed: ccn_name_next_sibling botch\n"); printf("Expected: %s\n", expected_bumped_uri); printf(" Actual: %s\n", (const char *)uri_out->buf); result = 1; } ccn_name_next_sibling(buffer); uri_out->length = 0; ccn_uri_append(uri_out, buffer->buf, buffer->length, 1); if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_bumped2_uri)) { printf("Failed: ccn_name_next_sibling botch\n"); printf("Expected: %s\n", expected_bumped2_uri); printf(" Actual: %s\n", (const char *)uri_out->buf); result = 1; } ccn_charbuf_destroy(&buffer); ccn_charbuf_destroy(&uri_out); } while (0); printf("Message digest tests\n"); do { printf("Unit test case %d\n", i++); struct ccn_digest *dg = ccn_digest_create(CCN_DIGEST_SHA256); if (dg == NULL) { printf("Failed: ccn_digest_create returned NULL\n"); result = 1; break; } printf("Unit test case %d\n", i++); const unsigned char expected_digest[] = { 0xb3, 0x82, 0xcd, 0xb0, 0xe9, 0x5d, 0xf7, 0x3b, 0xe7, 0xdc, 0x19, 0x81, 0x3a, 0xfd, 0xdf, 0x89, 0xfb, 0xd4, 0xd4, 0xa0, 0xdb, 0x11, 0xa6, 0xba, 0x24, 0x16, 0x5b, 0xad, 0x9d, 0x90, 0x72, 0xb0 }; unsigned char actual_digest[sizeof(expected_digest)] = {0}; const char *data = "Content-centric"; if (ccn_digest_size(dg) != sizeof(expected_digest)) { printf("Failed: wrong digest size\n"); result = 1; break; } printf("Unit test case %d\n", i++); ccn_digest_init(dg); res = ccn_digest_update(dg, data, strlen(data)); if (res != 0) printf("Warning: check res %d\n", (int)res); printf("Unit test case %d\n", i++); res = ccn_digest_final(dg, actual_digest, sizeof(expected_digest)); if (res != 0) printf("Warning: check res %d\n", (int)res); if (0 != memcmp(actual_digest, expected_digest, sizeof(expected_digest))) { printf("Failed: wrong digest\n"); result = 1; break; } } while (0); printf("Really basic PRNG test\n"); do { unsigned char r1[42]; unsigned char r2[42]; printf("Unit test case %d\n", i++); ccn_add_entropy(&i, sizeof(i), 0); /* Not much entropy, really. */ ccn_random_bytes(r1, sizeof(r1)); memcpy(r2, r1, sizeof(r2)); ccn_random_bytes(r2, sizeof(r2)); if (0 == memcmp(r1, r2, sizeof(r2))) { printf("Failed: badly broken PRNG\n"); result = 1; break; } } while (0); printf("Bloom filter tests\n"); do { unsigned char seed1[4] = "1492"; const char *a[13] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen" }; struct ccn_bloom *b1 = NULL; struct ccn_bloom *b2 = NULL; int j, k, t1, t2; unsigned short us; printf("Unit test case %d\n", i++); b1 = ccn_bloom_create(13, seed1); for (j = 0; j < 13; j++) if (ccn_bloom_match(b1, a[j], strlen(a[j]))) break; if (j < 13) { printf("Failed: \"%s\" matched empty Bloom filter\n", a[j]); result = 1; break; } printf("Unit test case %d\n", i++); for (j = 0; j < 13; j++) ccn_bloom_insert(b1, a[j], strlen(a[j])); for (j = 0; j < 13; j++) if (!ccn_bloom_match(b1, a[j], strlen(a[j]))) break; if (j < 13) { printf("Failed: \"%s\" not found when it should have been\n", a[j]); result = 1; break; } printf("Unit test case %d\n", i++); for (j = 0, k = 0; j < 13; j++) if (ccn_bloom_match(b1, a[j]+1, strlen(a[j]+1))) k++; if (k > 0) { printf("Mmm, found %d false positives\n", k); if (k > 2) { result = 1; break; } } unsigned char seed2[5] = "aqfb\0"; for (; seed2[3] <= 'f'; seed2[3]++) { printf("Unit test case %d (%4s) ", i++, seed2); b2 = ccn_bloom_create(13, seed2); for (j = 0; j < 13; j++) ccn_bloom_insert(b2, a[j], strlen(a[j])); for (j = 0, k = 0, us = ~0; us > 0; us--) { t1 = ccn_bloom_match(b1, &us, sizeof(us)); t2 = ccn_bloom_match(b2, &us, sizeof(us)); j += (t1 | t2); k += (t1 & t2); } printf("either=%d both=%d wiresize=%d\n", j, k, ccn_bloom_wiresize(b1)); if (k > 12) { printf("Failed: Bloom seeding may not be effective\n"); result = 1; } ccn_bloom_destroy(&b2); } ccn_bloom_destroy(&b1); } while (0); printf("ccn_sign_content() tests\n"); do { struct ccn *h = ccn_create(); struct ccn_charbuf *co = ccn_charbuf_create(); struct ccn_signing_params sparm = CCN_SIGNING_PARAMS_INIT; struct ccn_parsed_ContentObject pco = {0}; struct ccn_charbuf *name = ccn_charbuf_create(); printf("Unit test case %d\n", i++); ccn_name_from_uri(name, "ccnx:/test/data/%00%42"); res = ccn_sign_content(h, co, name, NULL, "DATA", 4); if (res != 0) { printf("Failed: res == %d\n", (int)res); result = 1; } sparm.template_ccnb = ccn_charbuf_create(); res = ccn_parse_ContentObject(co->buf, co->length, &pco, NULL); if (res != 0) { printf("Failed: ccn_parse_ContentObject res == %d\n", (int)res); result = 1; break; } ccn_charbuf_append(sparm.template_ccnb, co->buf + pco.offset[CCN_PCO_B_SignedInfo], pco.offset[CCN_PCO_E_SignedInfo] - pco.offset[CCN_PCO_B_SignedInfo]); sparm.sp_flags = CCN_SP_TEMPL_TIMESTAMP; printf("Unit test case %d\n", i++); res = ccn_sign_content(h, co, name, &sparm, "DATA", 4); if (res != 0) { printf("Failed: res == %d\n", (int)res); result = 1; } printf("Unit test case %d\n", i++); sparm.sp_flags = -1; res = ccn_sign_content(h, co, name, &sparm, "DATA", 4); if (res != -1) { printf("Failed: res == %d\n", (int)res); result = 1; } ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&sparm.template_ccnb); ccn_charbuf_destroy(&co); ccn_destroy(&h); } while (0); printf("link tests\n"); do { struct ccn_charbuf *l = ccn_charbuf_create(); struct ccn_charbuf *name = ccn_charbuf_create(); struct ccn_parsed_Link pl = {0}; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; struct ccn_indexbuf *comps = ccn_indexbuf_create(); printf("Unit test case %d\n", i++); ccn_name_from_uri(name, "ccnx:/test/link/name"); ccnb_append_Link(l, name, "label", NULL); d = ccn_buf_decoder_start(&decoder, l->buf, l->length); res = ccn_parse_Link(d, &pl, comps); if (res != 3 /* components in name */) { printf("Failed: ccn_parse_Link res == %d\n", (int)res); result = 1; } } while (0); exit(result); }
int unit_tests_for_signing(struct ccn *h, int *ip, int symmetric) { struct ccn_charbuf *co = ccn_charbuf_create(); struct ccn_charbuf *co2 = ccn_charbuf_create(); struct ccn_signing_params sparm = CCN_SIGNING_PARAMS_INIT; struct ccn_parsed_ContentObject pco = {0}; struct ccn_parsed_ContentObject pco2 = {0}; struct ccn_charbuf *name = ccn_charbuf_create(); int res; int result = 0; ccn_name_from_uri(name, "ccnx:/test/data/%00%42"); res = ccn_sign_content(h, co, name, NULL, "DATA", 4); if (res != 0) { printf("Failed: res == %d\n", (int)res); result = 1; } sparm.template_ccnb = ccn_charbuf_create(); res = ccn_parse_ContentObject(co->buf, co->length, &pco, NULL); if (res != 0) { printf("Failed: ccn_parse_ContentObject res == %d\n", (int)res); result = 1; goto Bail; } ccn_charbuf_append(sparm.template_ccnb, co->buf + pco.offset[CCN_PCO_B_SignedInfo], pco.offset[CCN_PCO_E_SignedInfo] - pco.offset[CCN_PCO_B_SignedInfo]); sparm.sp_flags = CCN_SP_TEMPL_TIMESTAMP; printf("Unit test case %d\n", (*ip)++); res = ccn_sign_content(h, co2, name, &sparm, "DATA", 4); if (res != 0) { printf("Failed: res == %d\n", (int)res); result = 1; } res = ccn_parse_ContentObject(co2->buf, co2->length, &pco2, NULL); if (res != 0) { printf("Failed to parse: res == %d\n", (int)res); result = 1; } printf("Unit test case %d\n", (*ip)++); sparm.sp_flags = -1; res = ccn_sign_content(h, co, name, &sparm, "DATA", 4); if (res != -1) { printf("Failed: res == %d\n", (int)res); result = 1; } /* * We can run this test with symmetric keys if the problem of being able * to store both a keystore and its associated key in the corresponding * hashtables of a handle can be solved. */ if (!symmetric) { printf("Unit test case %d\n", (*ip)++); res = ccn_verify_content(h, co->buf, &pco); if (res != 0) { printf("Failed: res == %d\n", (int)res); result = 1; } } Bail: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&sparm.template_ccnb); ccn_charbuf_destroy(&co); ccn_charbuf_destroy(&co2); return result; }
/** * Load a link to the repo policy from the repoPolicy file and load the link * target to extract the actual policy. * If a policy file does not exist a new one is created, with a link to a policy * based either on the environment variable CCNR_GLOBAL_PREFIX or the system * default value of ccnx:/parc.com/csl/ccn/Repos, plus the system defaults for * other fields. * This routine must be called after the btree code is initialized and capable * of returning content objects. * Sets the parsed_policy field of the handle to be the new policy. */ static int load_policy(struct ccnr_handle *ccnr) { int fd; ssize_t res; struct content_entry *content = NULL; const unsigned char *content_msg = NULL; struct ccn_parsed_ContentObject pco = {0}; struct ccn_parsed_Link pl = {0}; struct ccn_indexbuf *nc = NULL; struct ccn_charbuf *basename = NULL; struct ccn_charbuf *policy = NULL; struct ccn_charbuf *policy_cob = NULL; struct ccn_charbuf *policyFileName; const char *global_prefix; const unsigned char *buf = NULL; size_t length = 0; int segment = 0; int final = 0; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; policyFileName = ccn_charbuf_create(); ccn_charbuf_putf(policyFileName, "%s/repoPolicy", ccnr->directory); ccnr->parsed_policy = ccnr_parsed_policy_create(); fd = open(ccn_charbuf_as_string(policyFileName), O_RDONLY); if (fd >= 0) { ccnr->policy_link_cob = ccn_charbuf_create(); ccn_charbuf_reserve(ccnr->policy_link_cob, 4096); // limits the size of the policy link ccnr->policy_link_cob->length = 0; // clear the buffer res = read(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->limit - ccnr->policy_link_cob->length); close(fd); if (res == -1) { r_init_fail(ccnr, __LINE__, "Error reading repoPolicy file.", errno); ccn_charbuf_destroy(&ccnr->policy_link_cob); ccn_charbuf_destroy(&policyFileName); return(-1); } ccnr->policy_link_cob->length = res; nc = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length, &pco, nc); res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnr->policy_link_cob->buf, pco.offset[CCN_PCO_B_Content], pco.offset[CCN_PCO_E_Content], &buf, &length); d = ccn_buf_decoder_start(&decoder, buf, length); res = ccn_parse_Link(d, &pl, NULL); if (res <= 0) { ccnr_msg(ccnr, "Policy link is malformed."); goto CreateNewPolicy; } basename = ccn_charbuf_create(); ccn_charbuf_append(basename, buf + pl.offset[CCN_PL_B_Name], pl.offset[CCN_PL_E_Name] - pl.offset[CCN_PL_B_Name]); ccnr->policy_name = ccn_charbuf_create(); // to detect writes to this name ccn_charbuf_append_charbuf(ccnr->policy_name, basename); // has version ccn_name_chop(ccnr->policy_name, NULL, -1); // get rid of version policy = ccn_charbuf_create(); // if we fail to retrieve the link target, report and then create a new one do { ccn_name_append_numeric(basename, CCN_MARKER_SEQNUM, segment++); content = r_store_lookup_ccnb(ccnr, basename->buf, basename->length); if (content == NULL) { ccnr_debug_ccnb(ccnr, __LINE__, "policy lookup failed for", NULL, basename->buf, basename->length); break; } ccn_name_chop(basename, NULL, -1); content_msg = r_store_content_base(ccnr, content); if (content_msg == NULL) { ccnr_debug_ccnb(ccnr, __LINE__, "Unable to read policy object", NULL, basename->buf, basename->length); break; } res = ccn_parse_ContentObject(content_msg, r_store_content_size(ccnr, content), &pco, nc); res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg, pco.offset[CCN_PCO_B_Content], pco.offset[CCN_PCO_E_Content], &buf, &length); ccn_charbuf_append(policy, buf, length); final = ccn_is_final_pco(content_msg, &pco, nc); } while (!final && segment < 100);
/** * Test for a match between a ContentObject and an Interest * * @param content_object ccnb-encoded ContentObject * @param content_object_size its size in bytes * @param implicit_content_digest boolean indicating whether the * final name component is implicit (as in * the on-wire format) or explicit (as within * ccnd's content store). * @param pc Valid parse information may be provided to * speed things up. If NULL it will be * reconstructed internally. * @param interest_msg ccnb-encoded Interest * @param interest_msg_size its size in bytes * @param pi see _pc_ * * @result 1 if the ccnb-encoded content_object matches the * ccnb-encoded interest_msg, otherwise 0. */ int ccn_content_matches_interest(const unsigned char *content_object, size_t content_object_size, int implicit_content_digest, struct ccn_parsed_ContentObject *pc, const unsigned char *interest_msg, size_t interest_msg_size, const struct ccn_parsed_interest *pi) { struct ccn_parsed_ContentObject pc_store; struct ccn_parsed_interest pi_store; int res; int ncomps; int prefixstart; int prefixbytes; int namecompstart; int namecompbytes; int checkdigest = 0; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; const unsigned char *nextcomp; size_t nextcomp_size = 0; const unsigned char *comp; size_t comp_size = 0; const unsigned char *bloom; size_t bloom_size = 0; unsigned char match_any[2] = "-"; if (pc == NULL) { res = ccn_parse_ContentObject(content_object, content_object_size, &pc_store, NULL); if (res < 0) return(0); pc = &pc_store; } if (pi == NULL) { res = ccn_parse_interest(interest_msg, interest_msg_size, &pi_store, NULL); if (res < 0) return(0); pi = &pi_store; } if (!ccn_pubid_matches(content_object, pc, interest_msg, pi)) return(0); ncomps = pc->name_ncomps + (implicit_content_digest ? 1 : 0); if (ncomps < pi->prefix_comps + pi->min_suffix_comps) return(0); if (ncomps > pi->prefix_comps + pi->max_suffix_comps) return(0); prefixstart = pi->offset[CCN_PI_B_Component0]; prefixbytes = pi->offset[CCN_PI_E_LastPrefixComponent] - prefixstart; namecompstart = pc->offset[CCN_PCO_B_Component0]; namecompbytes = pc->offset[CCN_PCO_E_ComponentLast] - namecompstart; if (prefixbytes > namecompbytes) { /* * The only way for this to be a match is if the implicit * content digest name component comes into play. */ if (implicit_content_digest && pi->offset[CCN_PI_B_LastPrefixComponent] - prefixstart == namecompbytes && (pi->offset[CCN_PI_E_LastPrefixComponent] - pi->offset[CCN_PI_B_LastPrefixComponent]) == 1 + 2 + 32 + 1) { prefixbytes = namecompbytes; checkdigest = 1; } else return(0); } if (0 != memcmp(interest_msg + prefixstart, content_object + namecompstart, prefixbytes)) return(0); if (checkdigest) { /* * The Exclude by next component is not relevant in this case, * since there is no next component present. */ ccn_digest_ContentObject(content_object, pc); d = ccn_buf_decoder_start(&decoder, interest_msg + pi->offset[CCN_PI_B_LastPrefixComponent], (pi->offset[CCN_PI_E_LastPrefixComponent] - pi->offset[CCN_PI_B_LastPrefixComponent])); comp_size = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); ccn_buf_match_blob(d, &comp, &comp_size); } if (comp_size != pc->digest_bytes) abort(); if (0 != memcmp(comp, pc->digest, comp_size)) return(0); } else if (pi->offset[CCN_PI_E_Exclude] > pi->offset[CCN_PI_B_Exclude]) { if (prefixbytes < namecompbytes) { /* pick out the next component in the content object name */ d = ccn_buf_decoder_start(&decoder, content_object + (namecompstart + prefixbytes), pc->offset[CCN_PCO_E_ComponentLast] - (namecompstart + prefixbytes)); if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); ccn_buf_match_blob(d, &nextcomp, &nextcomp_size); } else return(0); } else if (!implicit_content_digest) goto exclude_checked; else if (prefixbytes == namecompbytes) { /* use the digest name as the next component */ ccn_digest_ContentObject(content_object, pc); nextcomp_size = pc->digest_bytes; nextcomp = pc->digest; } else abort(); /* bug - should have returned already */ d = ccn_buf_decoder_start(&decoder, interest_msg + pi->offset[CCN_PI_B_Exclude], pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]); if (!ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) abort(); ccn_buf_advance(d); bloom = NULL; bloom_size = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); bloom = match_any; ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_buf_check_close(d); } while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); comp_size = 0; if (ccn_buf_match_blob(d, &comp, &comp_size)) ccn_buf_advance(d); ccn_buf_check_close(d); if (comp_size > nextcomp_size) break; if (comp_size == nextcomp_size) { res = memcmp(comp, nextcomp, comp_size); if (res == 0) return(0); /* One of the explicit excludes */ if (res > 0) break; } bloom = NULL; bloom_size = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); bloom = match_any; ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_buf_check_close(d); } } /* * Now we have isolated the applicable filter (Any or Bloom or none). */ if (bloom == match_any) return(0); else if (bloom_size != 0) { const struct ccn_bloom_wire *f = ccn_bloom_validate_wire(bloom, bloom_size); /* If not a valid filter, treat like a false positive */ if (f == NULL) return(0); if (ccn_bloom_match_wire(f, nextcomp, nextcomp_size)) return(0); } exclude_checked: {} } /* * At this point the prefix matches and exclude-by-next-component is done. */ // test any other qualifiers here return(1); }