/** * * Create new face by sending out a request Interest * The actual new face instance is returned * */ static struct ccn_face_instance *create_face(struct ccn *h, struct ccn_charbuf *local_scope_template, struct ccn_charbuf *no_name, struct ccn_face_instance *face_instance) { struct ccn_charbuf *newface = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance *new_face_instance = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res = 0; /* Encode the given face instance */ newface = ccn_charbuf_create(); ccnb_append_face_instance(newface, face_instance); temp = ccn_charbuf_create(); res = ccn_sign_content(h, temp, no_name, NULL, newface->buf, newface->length); resultbuf = ccn_charbuf_create(); /* Construct the Interest name that will create the face */ name = ccn_charbuf_create(); ccn_name_init(name); ccn_name_append_str(name, "ccnx"); ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size); ccn_name_append_str(name, face_instance->action); ccn_name_append(name, temp->buf, temp->length); /* send Interest to retrieve Data that contains the newly created face */ res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); /* decode Data to get the actual face instance */ res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); ON_ERROR_CLEANUP(res); new_face_instance = ccn_face_instance_parse(ptr, length); ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return new_face_instance; cleanup: ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return NULL; }
void CcnCC_sendContent(CcnCC self, struct ccn_charbuf* name, TimeSpan expires, void* data, size_t size) { struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; if (expires >= 0) { sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expires / 1000); sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS; ccn_charbuf_append_closer(sp.template_ccnb); } struct ccn_charbuf* content = ccn_charbuf_create(); if (0 == ccn_sign_content(self->ccnh, content, name, &sp, data, size)) { ccn_put(self->ccnh, content->buf, content->length); } ccn_charbuf_destroy(&sp.template_ccnb); ccn_charbuf_destroy(&content); }
/** * should probably return a new cob, rather than reusing one. * should publish link as: * CCNRID_POLICY_URI("ccnx:/%C1.M.S.localhost/%C1.M.SRV/repository/POLICY)/%C1.M.K--pubid--/--version--/%00 * should have key locator which is the key name of the repository */ PUBLIC struct ccn_charbuf * ccnr_init_policy_link_cob(struct ccnr_handle *ccnr, struct ccn *h, struct ccn_charbuf *targetname) { struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct ccn_charbuf *name = ccn_charbuf_create(); struct ccn_charbuf *pubid = ccn_charbuf_create(); struct ccn_charbuf *pubkey = ccn_charbuf_create(); struct ccn_charbuf *keyid = ccn_charbuf_create(); struct ccn_charbuf *content = ccn_charbuf_create(); struct ccn_charbuf *cob = ccn_charbuf_create(); struct ccn_charbuf *answer = NULL; int res; res = ccn_get_public_key(h, NULL, pubid, pubkey); if (res < 0) goto Bail; if (ccn_name_from_uri(name, CCNRID_POLICY_URI) < 0) goto Bail; res |= ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1); res |= ccn_charbuf_append_string(keyid, ".M.K"); res |= ccn_charbuf_append_value(keyid, 0, 1); res |= ccn_charbuf_append_charbuf(keyid, pubid); res |= ccn_name_append(name, keyid->buf, keyid->length); res |= ccn_create_version(h, name, CCN_V_NOW, 0, 0); if (ccn_name_from_uri(name, "%00") < 0) goto Bail; sp.sp_flags |= CCN_SP_FINAL_BLOCK; sp.type = CCN_CONTENT_LINK; res |= ccnb_append_Link(content, targetname, "Repository Policy", NULL); if (res != 0) goto Bail; res |= ccn_sign_content(h, cob, name, &sp, content->buf, content->length); if (res != 0) goto Bail; answer = cob; cob = NULL; Bail: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&pubid); ccn_charbuf_destroy(&pubkey); ccn_charbuf_destroy(&keyid); ccn_charbuf_destroy(&content); ccn_charbuf_destroy(&cob); return (answer); }
enum ccn_upcall_res ccn_proxy_server_decap_interest( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { enum ccn_upcall_res upcall_res = CCN_UPCALL_RESULT_ERR; struct ccn_proxy_server* server = selfp->data; struct ccn_proxy* proxy = server->proxy; // struct ccn_proxy *proxy = (selfp->data)->proxy; int i, res; unsigned char* random = NULL; struct ccn_charbuf* request_name; struct ccn_indexbuf* request_comps; struct ccn_charbuf* signed_info; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; random = (unsigned char*)malloc(RESP_SIZE * sizeof(unsigned char)); for (i = 0; i < RESP_SIZE; i++) random[i] = rand() % 256; handled++; printf("random buffer created - creating signed object: %d\n", handled); // Create a valid, signed ContentObject request_name = NULL; request_comps = NULL; res = ccn_util_extract_name(info->interest_ccnb, info->interest_comps, &request_name, &request_comps); signed_info = ccn_charbuf_create(); sp.type = CCN_CONTENT_DATA; res = ccn_sign_content(proxy->handle, signed_info, request_name, &sp, random, RESP_SIZE); // Drop the content object into the socket (handle) to be sent back downstream res = ccn_put(proxy->handle, signed_info->buf, signed_info->length); if (res < 0) { ccn_perror(proxy->handle, NULL); printf("WTF?!?!?!\n"); } else { printf("successfully put content object in the socket\n"); } // // TODO: need to fill up random buffer and then inject it using ccn_put return(CCN_UPCALL_RESULT_OK); }
static struct ccn_charbuf * ccnr_init_service_ccnb(struct ccnr_handle *ccnr, struct ccn *h, const char *baseuri, int freshness) { struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct ccn_charbuf *name = ccn_charbuf_create(); struct ccn_charbuf *pubid = ccn_charbuf_create(); struct ccn_charbuf *pubkey = ccn_charbuf_create(); struct ccn_charbuf *keyid = ccn_charbuf_create(); struct ccn_charbuf *cob = ccn_charbuf_create(); int res; res = ccn_get_public_key(h, NULL, pubid, pubkey); if (res < 0) abort(); ccn_name_from_uri(name, baseuri); ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1); ccn_charbuf_append_string(keyid, ".M.K"); ccn_charbuf_append_value(keyid, 0, 1); ccn_charbuf_append_charbuf(keyid, pubid); ccn_name_append(name, keyid->buf, keyid->length); ccn_create_version(h, name, 0, ccnr->starttime, ccnr->starttime_usec * 1000); sp.template_ccnb = ccn_charbuf_create(); ccnb_element_begin(sp.template_ccnb, CCN_DTAG_SignedInfo); ccnb_element_begin(sp.template_ccnb, CCN_DTAG_KeyLocator); ccnb_element_begin(sp.template_ccnb, CCN_DTAG_KeyName); ccn_charbuf_append_charbuf(sp.template_ccnb, name); ccnb_element_end(sp.template_ccnb); // ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_PublisherPublicKeyDigest, // CCN_DTAG); // ccn_charbuf_append_charbuf(sp.template_ccnb, pubid); // ccnb_element_end(sp.template_ccnb); ccnb_element_end(sp.template_ccnb); ccnb_element_end(sp.template_ccnb); sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; ccn_name_from_uri(name, "%00"); sp.sp_flags |= CCN_SP_FINAL_BLOCK; sp.type = CCN_CONTENT_KEY; sp.freshness = freshness; res = ccn_sign_content(h, cob, name, &sp, pubkey->buf, pubkey->length); if (res != 0) abort(); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&pubid); ccn_charbuf_destroy(&pubkey); ccn_charbuf_destroy(&keyid); ccn_charbuf_destroy(&sp.template_ccnb); return(cob); }
static struct ccn_charbuf * seqw_next_cob(struct ccn_seqwriter *w) { struct ccn_charbuf *cob = ccn_charbuf_create(); struct ccn_charbuf *name = ccn_charbuf_create(); struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; int res; if (w->closed) sp.sp_flags |= CCN_SP_FINAL_BLOCK; ccn_charbuf_append(name, w->nv->buf, w->nv->length); ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, w->seqnum); res = ccn_sign_content(w->h, cob, name, &sp, w->buffer->buf, w->buffer->length); if (res < 0) ccn_charbuf_destroy(&cob); ccn_charbuf_destroy(&name); return(cob); }
struct ccn_charbuf* CcnH_signForwardingEntry(struct ccn* ccnh, CCNDID ccndid, struct ccn_forwarding_entry* fe) { struct ccn_charbuf* request = ccn_charbuf_create(); ccnb_append_forwarding_entry(request, fe); struct ccn_charbuf* emptyname = ccn_charbuf_create(); ccn_name_init(emptyname); struct ccn_charbuf* signed_request = ccn_charbuf_create(); ccn_sign_content(ccnh, signed_request, emptyname, NULL, request->buf, request->length); struct ccn_charbuf* reqname = ccn_charbuf_create(); ccn_name_from_uri(reqname, "ccnx:/ccnx"); ccn_name_append(reqname, ccndid, CCNDID_length); ccn_name_append_str(reqname, fe->action); ccn_name_append(reqname, signed_request->buf, signed_request->length); ccn_charbuf_destroy(&request); ccn_charbuf_destroy(&emptyname); ccn_charbuf_destroy(&signed_request); return reqname; }
static struct ccn_charbuf * ccnr_init_policy_cob(struct ccnr_handle *ccnr, struct ccn *h, struct ccn_charbuf *basename, int freshness, struct ccn_charbuf *content) { struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct ccn_charbuf *name = ccn_charbuf_create(); struct ccn_charbuf *pubid = ccn_charbuf_create(); struct ccn_charbuf *pubkey = ccn_charbuf_create(); struct ccn_charbuf *keyid = ccn_charbuf_create(); struct ccn_charbuf *tcob = ccn_charbuf_create(); struct ccn_charbuf *cob = NULL; // result int res; res = ccn_get_public_key(h, NULL, pubid, pubkey); if (res < 0) goto Leave; res = ccn_charbuf_append_charbuf(name, basename); if (ccn_name_from_uri(name, "%00") < 0) goto Leave; sp.sp_flags |= CCN_SP_FINAL_BLOCK; sp.type = CCN_CONTENT_DATA; sp.freshness = freshness; res |= ccn_sign_content(h, tcob, name, &sp, content->buf, content->length); if (res == 0) { cob = tcob; tcob = NULL; } Leave: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&pubid); ccn_charbuf_destroy(&pubkey); ccn_charbuf_destroy(&keyid); ccn_charbuf_destroy(&tcob); return (cob); }
int main(void) { int res; struct ccn *ccn= NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *result = NULL; struct ccn_closure in_interest = {.p=&incoming_interest}; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; // Parameters for creating signed content objects. char rawcontentbuf[1024] = ""; size_t content_size; // 1. Name name = ccn_charbuf_create(); res = ccn_name_from_uri(name, URI); if (res < 0) { fprintf(stderr, "bad ccn URI: %s\n", URI); exit(1); } // 2. ccn_create, and ccn_connect ccn = ccn_create(); res = ccn_connect(ccn, NULL); if (res < 0) { fprintf(stderr, "can't connect to ccnd: %d\n", res); ccn_perror(ccn, "ccn_connect"); exit(1); } // 3. Create the signed content object, set up &sp - signing params; // Extend a Name with a new version stamp if requested /*int versioned = 0; const char *postver = NULL; memcmp(postver, "%00", 3); if (versioned) { res = ccn_create_version(ccn, name, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0); if (res < 0) { fprintf(stderr, "%s: ccn_create_version() failed\n"); exit(1); } if (postver != NULL) { res = ccn_name_from_uri(name, postver); if (res < 0) { fprintf(stderr, "-V %s: invalid name suffix\n", postver); exit(0); } } } */ // Ask for a FinalBlockID if appropriate /*int setfinal = 0; if (setfinal) sp.sp_flags |= CCN_SP_FINAL_BLOCK; */ // Set content type //sp.type = content_type; // Set freshness /* The template_ccnb may contain a ccnb-encoded SignedInfo to supply selected fields from under * the direction of sp_flags. */ /*int expire = -1; if (expire >= 0) { if (sp.template_ccnb == NULL) { sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); } else if (sp.template_ccnb -> length > 0) { sp.template_ccnb -> length--; } ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expire); sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS; ccn_charbuf_append_closer(sp.template_ccnb); } */ // Set key locator, if supplied /*const char *key_uri = NULL; //key_uri = optarg; if (key_uri != NULL) { struct ccn_charbuf *c = ccn_charbuf_create(); res = ccn_name_from_uri(c, key_uri); if (res < 0) { fprintf(stderr, "%s is not a valid ccnx URI\n", key_uri); exit(1); } if (sp.template_ccnb == NULL) { sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); } else if (sp.template_ccnb -> length > 0) { sp.template_ccnb -> length--; } ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG); ccn_charbuf_append(sp.template_ccnb, c->buf, c->length); ccn_charbuf_append_closer(sp.template_ccnb); ccn_charbuf_append_closer(sp.template_ccnb); sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; ccn_charbuf_append_closer(sp.template_ccnb); ccn_charbuf_destroy(&c); } */ // Set up a handler for interest ccn_set_interest_filter(ccn, name, &in_interest); // 4. Use ccn_sign_content to create the signed content object with composed &sp, // if (force) { ccn_put; } # ccn_get means send ccn binary. For normal clients, this should be a ContentObject sent in response to an Interest. // else { ccn_set_interest_filter; ccn_run; } result = ccn_charbuf_create(); result -> length = 0; strcat(rawcontentbuf, CONTENTDATA); content_size = strlen(rawcontentbuf); //sp.sp_flags |= CCN_SP_FINAL_BLOCK; res = ccn_sign_content(ccn, result, name, &sp, rawcontentbuf, content_size); if (res < 0) { ccn_perror(ccn, "ccn_sign_content"); exit(1); } printf("Content signed, trying to send the data...\n"); res = ccn_put(ccn, result->buf, result->length); if (res < 0) { ccn_perror(ccn, "ccn_put"); printf("Failed to send content object: res = %d\n", res); exit(1); } else printf("ccn_put done, content object sent.\n"); // ccn_run serves as the event loop when timeout = -1 res = ccn_run(ccn, -1); // Loop here all the time until it is killed, then "Event loop..." printf("Event loop...\n"); if (res < 0) { ccn_perror(ccn, "ccn_run"); printf("Error: ccn_run\n"); exit(1); } ccn_destroy(&ccn); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&result); ccn_charbuf_destroy(&sp.template_ccnb); printf("ccn handle is destroyed... \n"); return 0; }
/** * * Bind a prefix to a face * */ static int register_unregister_prefix(struct ccn *h, struct ccn_charbuf *local_scope_template, struct ccn_charbuf *no_name, struct ccn_charbuf *name_prefix, struct ccn_face_instance *face_instance, int operation) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry forwarding_entry_storage = {0}; struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage; struct ccn_forwarding_entry *new_forwarding_entry; const unsigned char *ptr = NULL; size_t length = 0; int res; /* Register or unregister the prefix */ forwarding_entry->action = (operation == OP_REG) ? "prefixreg" : "unreg"; forwarding_entry->name_prefix = name_prefix; forwarding_entry->ccnd_id = face_instance->ccnd_id; forwarding_entry->ccnd_id_size = face_instance->ccnd_id_size; forwarding_entry->faceid = face_instance->faceid; forwarding_entry->flags = -1; forwarding_entry->lifetime = 2100; prefixreg = ccn_charbuf_create(); ccnb_append_forwarding_entry(prefixreg, forwarding_entry); temp = ccn_charbuf_create(); res = ccn_sign_content(h, temp, no_name, NULL, prefixreg->buf, prefixreg->length); resultbuf = ccn_charbuf_create(); /* construct Interest containing prefixreg request */ name = ccn_charbuf_create(); ccn_name_init(name); ccn_name_append_str(name, "ccnx"); ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size); ccn_name_append_str(name, (operation == OP_REG) ? "prefixreg" : "unreg"); ccn_name_append(name, temp->buf, temp->length); /* send Interest, get Data */ res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); ON_ERROR_CLEANUP(res); /* extract new forwarding entry from Data */ new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return res; cleanup: ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return -1; }
enum ccn_upcall_res andana_server_session_listener( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { int res; struct andana_server *server = selfp->data; const unsigned char * const_encrypted = NULL; unsigned char *encrypted = NULL; size_t enc_size; /* * Extract the client's randomness (aka the symmetric key it sent us. * Should be the last component of the incoming Interest. */ struct ccn_charbuf *request_name = NULL; struct ccn_indexbuf *request_comps = NULL; DEBUG_PRINT("IN %d %s\n", __LINE__, __func__); switch (kind) { case CCN_UPCALL_INTEREST: DEBUG_PRINT("%d %s received session request\n", __LINE__, __func__); break; case CCN_UPCALL_INTEREST_TIMED_OUT: DEBUG_PRINT("%d %s received session request time out\n", __LINE__, __func__); /* Fall through */ default: DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_OK); } printf("here now mk?\n"); res = ccn_util_extract_name(info->interest_ccnb, info->interest_comps, &request_name, &request_comps); if (res < 0) { DEBUG_PRINT("%d %s Failed to extract session request name\n", __LINE__, __func__); ccn_charbuf_destroy(&request_name); ccn_indexbuf_destroy(&request_comps); return(CCN_UPCALL_RESULT_ERR); } printf("passed util extract name\n"); res = ccn_name_comp_get(request_name->buf, request_comps, (unsigned int)request_comps->n - 2, &const_encrypted, &enc_size); if (res < 0) { DEBUG_PRINT("%d %s Failed to extract session creation data\n", __LINE__, __func__); ccn_charbuf_destroy(&request_name); ccn_indexbuf_destroy(&request_comps); return(CCN_UPCALL_RESULT_ERR); } encrypted = calloc(enc_size, sizeof(unsigned char)); printf("encryption size = %d\n", enc_size); if (encrypted == NULL) printf("invalid pointer return from calloc\n"); memcpy(encrypted, const_encrypted, enc_size); struct ccn_pkey *symkey = NULL; struct ccn_charbuf *decrypted = NULL; struct ccn_indexbuf *decrypted_comps = ccn_indexbuf_create(); printf("trying asymmetric decryption\n"); ccn_crypto_name_asym_decrypt(server->privkey, encrypted, &symkey, &decrypted, &decrypted_comps); // ccn_crypto_name_sym_decrypt(server->node_key, encrypted, encrypted_size, &decrypted, &decrypted_comps); /* cn_crypto_name_sym_decrypt(server->node_key, encrypted, encrypted_size, &symkey, &decrypted, &decrypted_comps); */ printf("good - now creating a session\n"); unsigned char *session_id = NULL; unsigned char *session_key = NULL; unsigned char *server_rand = NULL; /* * Create a new session id and session key using the client's randomness. * The server is also responsible for contributing randomness of its own for security. */ createSession(&session_id, &session_key, &server_rand, ccn_crypto_symkey_key(symkey), (unsigned int)ccn_crypto_symkey_bytes(symkey), ccn_crypto_symkey_key(server->node_key)); printf("Session made!\n"); /* Construct the response message using a ccn name (for convenience). */ struct ccn_charbuf *session_info = ccn_charbuf_create(); ccn_name_init(session_info); ccn_name_append(session_info, session_id, SESSIONID_LENGTH); ccn_name_append(session_info, session_key, SESSION_KEYLEN); ccn_name_append(session_info, server_rand, SESSIONRAND_LENGTH); /** * Encrypt the response message using the symmetric key * provided by the client and send it out. */ unsigned char *enc_info = NULL; ccn_crypto_content_encrypt(symkey, session_info->buf, session_info->length, &enc_info, &enc_size); struct ccn_charbuf *signed_enc_info = ccn_charbuf_create(); struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; sp.type = CCN_CONTENT_DATA; res = ccn_sign_content(server->proxy->handle, signed_enc_info, request_name, &sp, enc_info, enc_size); if (res < 0) { DEBUG_PRINT("%d %s Failed to signed session creation response\n", __LINE__, __func__); } else { res = ccn_put(server->proxy->handle, signed_enc_info->buf, signed_enc_info->length); } ccn_charbuf_destroy(&decrypted); ccn_indexbuf_destroy(&decrypted_comps); ccn_crypto_symkey_destroy(&symkey); free(session_id); free(session_key); free(server_rand); free(enc_info); ccn_charbuf_destroy(&signed_enc_info); if (res < 0) { DEBUG_PRINT("%d %s Error writing session creation response\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_ERR); } DEBUG_PRINT("OUT %d %s Created new session. Response sent\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_INTEREST_CONSUMED); }
/** * Call-back from the CCN network that something has arrived * * We get notified that a client has interests in things we are producing. * This function will do some basic checking to see what exactly the client has * an interest in, and will produce what is appropriate. * Currently the things we produce are: * \li last block - we resend the last block we have published for a given name * \li last segment - we produce a data message that only contains the latest segment number we used * * \param selfp -> a context structure we created when registering this call-back * \param kind specifies the type of call-back being processed, see the \b switch statement * \param info context information about the call-back itself; interests, data, etc. * \return a response as to how successful we were in processing the call-back * \retval CCN_UPCALL_RESULT_OK things went well * \retval CCN_UPCALL_RESULT_VERIFY need to verify the contents of what we received * \retval CCN_UPCALL_RESULT_REEXPRESS an interest timedout waiting for data, so we try again * \retval CCN_UPCALL_RESULT_ERR some error was encountered */ static enum ccn_upcall_res new_interests (struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { Gstccnxsink *me = GST_CCNXSINK (selfp->data); struct ccn_charbuf *cb; struct ccn_charbuf *sname = NULL; const unsigned char *cp1, *cp2; size_t sz1; size_t sz2; long lastSeq; struct ccn_signing_params myparams; unsigned int i; int rc; GST_DEBUG ("something has arrived!"); GST_DEBUG ("matched is: %d", info->matched_comps); // number of filter components that were matched by the interest cb = interestAsUri (info); GST_DEBUG ("as URI: %s", ccn_charbuf_as_string (cb)); ccn_charbuf_destroy (&cb); myparams = me->sp; /* Some debugging stuff */ for (i = 0; i < 10; ++i) { const unsigned char *cp; size_t sz; GST_DEBUG ("%3d: ", i); if (0 > ccn_name_comp_get (info->interest_ccnb, info->interest_comps, i, &cp, &sz)) { // fprintf(stderr, "could not get comp\n"); break; } else { // hDump( DUMP_ADDR( cp ), DUMP_SIZE( sz ) ); } } switch (kind) { case CCN_UPCALL_FINAL: GST_LOG_OBJECT (me, "CCN upcall final %p", selfp); return (0); case CCN_UPCALL_INTEREST_TIMED_OUT: if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN Interest timed out on dead closure %p", selfp); return (0); } GST_LOG_OBJECT (me, "CCN upcall reexpress -- timed out"); if (me->timeouts > 5) { GST_LOG_OBJECT (me, "CCN upcall reexpress -- too many reexpressions"); return (0); } me->timeouts++; return (CCN_UPCALL_RESULT_REEXPRESS); case CCN_UPCALL_CONTENT_UNVERIFIED: if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN unverified content on dead closure %p", selfp); return (0); } return (CCN_UPCALL_RESULT_VERIFY); case CCN_UPCALL_CONTENT: if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN content on dead closure %p", selfp); return (0); } break; case CCN_UPCALL_CONTENT_BAD: GST_LOG_OBJECT (me, "Content signature verification failed! Discarding.\n"); return (CCN_UPCALL_RESULT_ERR); case CCN_UPCALL_CONSUMED_INTEREST: GST_LOG_OBJECT (me, "Upcall consumed interest\n"); return (CCN_UPCALL_RESULT_ERR); /* no data */ /* Here is the most interesting case...when an interest arrives */ case CCN_UPCALL_INTEREST: GST_INFO ("We got an interest\n"); myparams.freshness = 1; /* meta data is old very quickly */ /* See if any meta information is sought */ for (i = 0;; ++i) { if (0 > ccn_name_comp_get (info->interest_ccnb, info->interest_comps, i, &cp1, &sz1)) { cp1 = NULL; break; } else { if (!strncmp ((const char *) cp1, "_meta_", 6)) { // OK, found meta, now which one is needed? if (0 > ccn_name_comp_get (info->interest_ccnb, info->interest_comps, i + 1, &cp2, &sz2)) { GST_LOG_OBJECT (me, "CCN interest received with invalid meta request"); cp1 = NULL; } break; } // Component not meta, keep looking } } // At this point, i is left pointing at '_meta_' or at the end of component list if (cp1) { // hDump( DUMP_ADDR(cp1), DUMP_SIZE(sz1) ); // hDump( DUMP_ADDR(cp2), DUMP_SIZE(sz2) ); if (strncmp ((const char *) cp2, ".segment", 8)) goto Exit_Interest; /* not a match */ /* publish what segment we are up to in reply to the meta request */ lastSeq = me->segment - 1; GST_INFO ("sending meta data....segment: %d", lastSeq); sname = ccn_charbuf_create (); ccn_name_init (sname); rc = ccn_name_append_components (sname, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[i + 2]); if (rc < 0) goto Error_Interest; // rc = ccn_create_version(me->ccn, sname, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0); // if (rc < 0) goto Error_Interest; me->temp->length = 0; rc = ccn_sign_content (me->ccn, me->temp, sname, &myparams, &lastSeq, sizeof (lastSeq)); // hDump(DUMP_ADDR(sname->buf), DUMP_SIZE(sname->length)); if (rc != 0) { GST_LOG_OBJECT (me, "Failed to encode ContentObject (rc == %d)\n", rc); goto Error_Interest; } GST_INFO ("sending meta data..."); // hDump(DUMP_ADDR(me->temp->buf), DUMP_SIZE(me->temp->length)); rc = ccn_put (me->ccn, me->temp->buf, me->temp->length); me->temp->length = 0; if (rc < 0) { GST_LOG_OBJECT (me, "ccn_put failed (res == %d)\n", rc); goto Error_Interest; } GST_INFO ("meta data sent"); } else goto Exit_Interest; /* do not have _meta_ */ Exit_Interest: ccn_charbuf_destroy (&sname); break; Error_Interest: ccn_charbuf_destroy (&sname); return CCN_UPCALL_RESULT_ERR; default: GST_LOG_OBJECT (me, "CCN upcall result error"); return (CCN_UPCALL_RESULT_ERR); } me->timeouts = 0; return (CCN_UPCALL_RESULT_OK); }
/** * Send out a message onto the CCNx network * * Once a data buffer is ready to be sent onto the network, there are * a few more steps involved in preparing it for thta journey. * The CCN stack dictates that all data content messages must contain * a proper name, and be signed by the sender. * \todo some day we should also encrypt the data; I don't think it is now * Much of the information we need to accomplish the message preperation is * found in the element context or as one of the parameters. * * Most of the work is dealing with changing from the internal buffer size and * the message size of the CCN network. * We chop things up as needed and send each data message out, properly named and signed. * The naming will include the timestamp as well as a segment number. * If there are some partial bytes left over, that do not fill a CCN message packet, * we retain those to be sent out on the next call to this method. * The bytes are kept in the element context as is other pertinent information. * * \param me * \param data pointer to the data buffer to send * \param size number of bytes to send in the message * \param ts timestamp to use on the outbound message * \return a GST flow return value indicating the result of our attempt * \retval GST_FLOW_OK everything went well * \retval GST_FLOW_ERROR something went wrong */ static GstFlowReturn gst_ccnxsink_send (Gstccnxsink * me, guint8 * data, guint size, /*@unused@ */ GstClockTime ts) { struct ccn_charbuf *sname; /* where we construct the name of this data message */ struct ccn_charbuf *hold; /* holds the last block published so we can properly manage memory */ struct ccn_charbuf *temp; /* where we construct the message to send */ struct ccn_charbuf *signed_info; /* signing data within the message */ gint rc; /* return status on various calls */ guint8 *xferStart; /* points into the source buffer, data, as we packetize into CCN blocks */ size_t bytesLeft; /* keeps track of how much more we have to do */ /* Initialize our local storage and allocate buffers we will need */ xferStart = data; bytesLeft = size; sname = ccn_charbuf_create (); temp = ccn_charbuf_create (); signed_info = ccn_charbuf_create (); /* Hang onto this pointer so we can release the buffer as we exit this function */ hold = me->lastPublish; /* * I am hanging onto this code for now to handle the day when we want to encode the data. * I do not know why id did not work during development, but I am sure it is close to working 8-) * In the future, feel free to purge this if we never get around to using it. * Similarly for the code block that is down below a little bit. * if( me->keystore ) { signed_info->length = 0; GST_LOG_OBJECT( me, "send - signing info\n" ); rc = ccn_signed_info_create(signed_info , ccn_keystore_public_key_digest(me->keystore) //pubkeyid , ccn_keystore_public_key_digest_length(me->keystore) //publisher_key_id_size , NULL //datetime , CCN_CONTENT_DATA //type , me->expire //freshness , NULL //finalblockid , me->keylocator); // Put the keylocator in the first block only. ccn_charbuf_destroy(&(me->keylocator)); if (rc < 0) { GST_LOG_OBJECT(me, "Failed to create signed_info (rc == %d)\n", rc); goto Trouble; } } */ if (me->partial) { /* We had some left over from the last send */ size_t extra; uintmax_t seg; /* find out how much room we have left, and copy over the bytes we have, or need to fill the block */ extra = CCN_CHUNK_SIZE - me->partial->length; if (extra > bytesLeft) extra = bytesLeft; GST_LOG_OBJECT (me, "send - had a partial left: %d\n", extra); ccn_charbuf_append (me->partial, xferStart, extra); /* Adjust count and pointer to reflect the bytes we have taken */ bytesLeft -= extra; xferStart += extra; /* Filling to the size of the CCN packet means we need to send it out */ if (me->partial->length == CCN_CHUNK_SIZE) { sname->length = 0; seg = me->segment++; /* build up a name starting with the prefix, then the sequence number */ ccn_charbuf_append (sname, me->name->buf, me->name->length); ccn_name_append_numeric (sname, CCN_MARKER_SEQNUM, seg); temp->length = 0; /* Signing via this function does a lot of work. The result is a buffer, temp, that is ready to be sent */ ccn_sign_content (me->ccn, temp, sname, &me->sp, me->partial->buf, CCN_CHUNK_SIZE); // hDump( sname->buf, sname->length ); /* * See the comment above about holding this code. * if( me->keystore ) { rc = ccn_encode_ContentObject(temp, sname, signed_info, me->partial->buf, CCN_CHUNK_SIZE, NULL, ccn_keystore_private_key(me->keystore)); if (rc != 0) { GST_LOG_OBJECT( me, "Failed to encode ContentObject (rc == %d)\n", rc); goto Trouble; } */ /* send the data message on its way */ rc = ccn_put (me->ccn, temp->buf, temp->length); if (rc < 0) { GST_LOG_OBJECT (me, "ccn_put failed (rc == %d)\n", rc); goto Trouble; } /* free the buffer we used for the partial data */ ccn_charbuf_destroy (&me->partial); me->partial = NULL; /* } else { GST_LOG_OBJECT( me, "No keystore. What should we do?\n" ); goto Trouble; } */ } } /* No left over means we can send direct out of the data buffer */ /* Now that we are done with the partial block, go and process the new data in much the same fashion */ while (bytesLeft >= CCN_CHUNK_SIZE) { uintmax_t seg; GST_LOG_OBJECT (me, "send - bytesLeft: %d\n", bytesLeft); sname->length = 0; seg = me->segment++; ccn_charbuf_append (sname, me->name->buf, me->name->length); ccn_name_append_numeric (sname, CCN_MARKER_SEQNUM, seg); GST_LOG_OBJECT (me, "send - name is ready\n"); temp->length = 0; ccn_sign_content (me->ccn, temp, sname, &me->sp, xferStart, CCN_CHUNK_SIZE); // hDump( sname->buf, sname->length ); /* if( me->keystore ) { GST_LOG_OBJECT( me, "send - encoding\n" ); rc = ccn_encode_ContentObject(temp, sname, signed_info, xferStart, CCN_CHUNK_SIZE, NULL, ccn_keystore_private_key(me->keystore)); if (rc != 0) { GST_LOG_OBJECT( me, "Failed to encode ContentObject (rc == %d)\n", rc); goto Trouble; } */ GST_LOG_OBJECT (me, "send - putting\n"); rc = ccn_put (me->ccn, temp->buf, temp->length); if (rc < 0) { GST_LOG_OBJECT (me, "ccn_put failed (rc == %d)\n", rc); goto Trouble; } /* } else { GST_LOG_OBJECT( me, "No keystore. What should we do?\n" ); goto Trouble; } */ GST_LOG_OBJECT (me, "send - adjusting buffers\n"); /* msleep(5); */ bytesLeft -= CCN_CHUNK_SIZE; xferStart += CCN_CHUNK_SIZE; } /* end of while() */ if (bytesLeft) { /* We have some left over for next time */ GST_LOG_OBJECT (me, "send - for next time: %d\n", bytesLeft); me->partial = ccn_charbuf_create (); me->partial->length = 0; ccn_charbuf_append (me->partial, xferStart, bytesLeft); } /* Do proper memory management, then return */ ccn_charbuf_destroy (&sname); me->lastPublish = temp; ccn_charbuf_destroy (&hold); ccn_charbuf_destroy (&signed_info); GST_LOG_OBJECT (me, "send - leaving length: %d\n", me->lastPublish->length); return GST_FLOW_OK; Trouble: ccn_charbuf_destroy (&sname); ccn_charbuf_destroy (&temp); ccn_charbuf_destroy (&signed_info); return GST_FLOW_ERROR; }
int main(int argc, char **argv) { struct ccn *h = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *null_name = NULL; struct ccn_charbuf *name_prefix = NULL; struct ccn_charbuf *newface = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *templ = NULL; const unsigned char *ptr = NULL; size_t length = 0; const char *arg = NULL; const char *progname = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance face_instance_storage = {0}; struct ccn_face_instance *face_instance = &face_instance_storage; struct ccn_forwarding_entry forwarding_entry_storage = {0}; struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct ccn_charbuf *keylocator_templ = NULL; struct ccn_keystore *keystore = NULL; long expire = -1; int ipproto; unsigned char ccndid_storage[32] = {0}; const unsigned char *ccndid = NULL; size_t ccndid_size = 0; int res; int opt; progname = argv[0]; while ((opt = getopt(argc, argv, "h")) != -1) { switch (opt) { case 'h': default: usage(progname); } } /* Sanity check the URI and argument count */ arg = argv[optind]; if (arg == NULL) usage(progname); name = ccn_charbuf_create(); res = ccn_name_from_uri(name, arg); if (res < 0) { fprintf(stderr, "%s: bad ccn URI: %s\n", progname, arg); exit(1); } if (argc - optind < 3 || argc - optind > 4) usage(progname); h = ccn_create(); res = ccn_connect(h, NULL); if (res < 0) { ccn_perror(h, "ccn_connect"); exit(1); } newface = ccn_charbuf_create(); temp = ccn_charbuf_create(); templ = ccn_charbuf_create(); keylocator_templ = ccn_charbuf_create(); resultbuf = ccn_charbuf_create(); name_prefix = ccn_charbuf_create(); null_name = ccn_charbuf_create(); CHKRES(ccn_name_init(null_name)); keystore = ccn_keystore_create(); /* We need to figure out our local ccnd's CCIDID */ /* Set up our Interest template to indicate scope 1 */ ccn_charbuf_reset(templ); ccnb_element_begin(templ, CCN_DTAG_Interest); ccnb_element_begin(templ, CCN_DTAG_Name); ccnb_element_end(templ); /* </Name> */ ccnb_tagged_putf(templ, CCN_DTAG_Scope, "1"); ccnb_element_end(templ); /* </Interest> */ ccn_charbuf_reset(name); CHKRES(res = ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY")); CHKRES(res = ccn_get(h, name, templ, 200, resultbuf, &pcobuf, NULL, 0)); res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid, &ccndid_size); CHKRES(res); if (ccndid_size > sizeof(ccndid_storage)) CHKRES(-1); memcpy(ccndid_storage, ccndid, ccndid_size); ccndid = ccndid_storage; face_instance->action = "newface"; face_instance->ccnd_id = ccndid; face_instance->ccnd_id_size = ccndid_size; if (strcmp(argv[optind + 1], "tcp") == 0) ipproto = 6; else if (strcmp(argv[optind + 1], "udp") == 0) ipproto = 17; else ipproto = atoi(argv[optind + 1]); face_instance->descr.ipproto = ipproto; // XXX - 6 = tcp or 17 = udp face_instance->descr.address = argv[optind + 2]; face_instance->descr.port = argv[optind + 3]; if (face_instance->descr.port == NULL) face_instance->descr.port = CCN_DEFAULT_UNICAST_PORT; face_instance->descr.mcast_ttl = -1; face_instance->lifetime = (~0U) >> 1; CHKRES(res = ccnb_append_face_instance(newface, face_instance)); temp->length = 0; CHKRES(ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"))); res = ccn_keystore_init(keystore, ccn_charbuf_as_string(temp), "Th1s1sn0t8g00dp8ssw0rd."); CHKRES(res); ccnb_element_begin(keylocator_templ, CCN_DTAG_SignedInfo); ccnb_element_begin(keylocator_templ, CCN_DTAG_KeyLocator); ccnb_element_begin(keylocator_templ, CCN_DTAG_Key); CHKRES(ccn_append_pubkey_blob(keylocator_templ, ccn_keystore_public_key(keystore))); ccnb_element_end(keylocator_templ); /* </Key> */ ccnb_element_end(keylocator_templ); /* </KeyLocator> */ ccnb_element_end(keylocator_templ); /* </SignedInfo> */ sp.template_ccnb = keylocator_templ; sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; sp.freshness = expire; ccn_charbuf_reset(temp); res = ccn_sign_content(h, temp, null_name, &sp, newface->buf, newface->length); CHKRES(res); /* Create the new face */ CHKRES(ccn_name_init(name)); CHKRES(ccn_name_append_str(name, "ccnx")); CHKRES(ccn_name_append(name, ccndid, ccndid_size)); CHKRES(ccn_name_append(name, "newface", 7)); CHKRES(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0); if (res < 0) { fprintf(stderr, "no response from face creation request\n"); exit(1); } ptr = resultbuf->buf; length = resultbuf->length; res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); CHKRES(res); face_instance = ccn_face_instance_parse(ptr, length); if (face_instance == NULL) CHKRES(res = -1); CHKRES(face_instance->faceid); /* Finally, register the prefix */ ccn_charbuf_reset(name_prefix); CHKRES(ccn_name_from_uri(name_prefix, arg)); forwarding_entry->action = "prefixreg"; forwarding_entry->name_prefix = name_prefix; forwarding_entry->ccnd_id = ccndid; forwarding_entry->ccnd_id_size = ccndid_size; forwarding_entry->faceid = face_instance->faceid; forwarding_entry->flags = -1; /* let ccnd decide */ forwarding_entry->lifetime = (~0U) >> 1; prefixreg = ccn_charbuf_create(); CHKRES(res = ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); ccn_charbuf_reset(temp); res = ccn_sign_content(h, temp, null_name, &sp, prefixreg->buf, prefixreg->length); CHKRES(res); CHKRES(ccn_name_init(name)); CHKRES(ccn_name_append_str(name, "ccnx")); CHKRES(ccn_name_append(name, ccndid, ccndid_size)); CHKRES(ccn_name_append_str(name, "prefixreg")); CHKRES(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0); if (res < 0) { fprintf(stderr, "no response from prefix registration request\n"); exit(1); } fprintf(stderr, "Prefix %s will be forwarded to face %d\n", arg, face_instance->faceid); /* We're about to exit, so don't bother to free everything. */ ccn_destroy(&h); exit(res < 0); }
enum ccn_upcall_res andana_server_decap_interest( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { enum ccn_upcall_res upcall_res = CCN_UPCALL_RESULT_ERR; struct andana_server *server = selfp->data; struct ccn_proxy *proxy = server->proxy; struct ccn_charbuf *new_interest = NULL; struct ccn_charbuf *new_name = NULL; struct ccn_charbuf *orig_name = NULL; struct ccn_indexbuf *orig_name_indexbuf = NULL; int orig_name_ncomps; char is_session = 0; struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ int res; DEBUG_PRINT("IN %d %s\n", __LINE__, __func__); switch (kind) { case CCN_UPCALL_INTEREST: DEBUG_PRINT("%d %s received interest\n", __LINE__, __func__); break; case CCN_UPCALL_INTEREST_TIMED_OUT: DEBUG_PRINT("%d %s received interest time out\n", __LINE__, __func__); /* Fall through */ default: DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_OK); } /* Extract Name from Interest */ orig_name_ncomps = ccn_util_extract_name(info->interest_ccnb, info->interest_comps, &orig_name, &orig_name_indexbuf); #ifdef PROXYDEBUG ccn_util_print_pc_fmt(orig_name->buf, orig_name->length); DEBUG_PRINT("\n"); DEBUG_PRINT("Name has %lu comps\n", orig_name_indexbuf->n-1); #endif /*Decapsulate & decrypt Interest. */ const unsigned char *const_encrypted = NULL; unsigned char *encrypted = NULL; size_t encrypted_size; if (orig_name_ncomps >= 2) { const unsigned char *session_check = NULL; size_t session_check_size; res = ccn_name_comp_get(orig_name->buf, orig_name_indexbuf, (unsigned int)server->SESSION_FLAG, &session_check, &session_check_size); if (res < 0) { DEBUG_PRINT("%d %s Error extracting session check component %lu\n", __LINE__, __func__, server->SESSION_FLAG); goto SessionFail; } else { DEBUG_PRINT("%d %s Extracted component %lu\n", __LINE__, __func__,server->SESSION_FLAG); } if (session_check_size == strlen("SESSION") && memcmp(session_check, "SESSION", session_check_size) == 0) { DEBUG_PRINT("%d %s Session identified\n", __LINE__, __func__); is_session = 1; } else { DEBUG_PRINT("%d %s Not a session\n", __LINE__, __func__); } } /* Decrypt the name (contains a new name and an Interest template) */ struct ccn_pkey *symkey = NULL; struct ccn_charbuf *decrypted = NULL; struct ccn_indexbuf *decrypted_comps = ccn_indexbuf_create(); if (is_session) { res = ccn_name_comp_get(orig_name->buf, orig_name_indexbuf, (unsigned int)server->SESSION_ENC, &const_encrypted, &encrypted_size); if (res < 0) { DEBUG_PRINT("%d %s Error extracting encrypted session component %lu\n", __LINE__, __func__, server->SESSION_ENC); goto SessionParseFail; } else { DEBUG_PRINT("%d %s Extracted encrypted session component %lu\n", __LINE__, __func__, server->SESSION_ENC); } encrypted = calloc(encrypted_size, sizeof(unsigned char)); memcpy(encrypted, const_encrypted, encrypted_size); ccn_crypto_name_sym_decrypt(server->node_key, encrypted, encrypted_size, &symkey, &decrypted, &decrypted_comps); } else { ccn_name_comp_get(orig_name->buf, orig_name_indexbuf, (unsigned int)server->ENC, &const_encrypted, &encrypted_size); encrypted = calloc(encrypted_size, sizeof(unsigned char)); memcpy(encrypted, const_encrypted, encrypted_size); ccn_crypto_name_asym_decrypt(server->privkey, encrypted, &symkey, &decrypted, &decrypted_comps); } size_t ncomps = decrypted_comps->n-1; const unsigned char *tmpl = NULL; size_t tmpl_size; res = ccn_name_comp_get(decrypted->buf, decrypted_comps, (unsigned int)ncomps - 1, &tmpl, &tmpl_size); if (res < 0) { DEBUG_PRINT("ABORT %d %s unable to retrieve component %d\n", __LINE__, __func__, (int)ncomps); goto CompExtractFail; } /* Pull timestamp component (comp 0) */ const unsigned char *ts_data = NULL; size_t ts_size; res = ccn_name_comp_get(decrypted->buf, decrypted_comps, 0, &ts_data, &ts_size); if (res < 0) { goto CompExtractFail; } struct timeval timestamp; ccn_util_extract_timestamp(ts_data, ts_size, ×tamp); struct timeval window = {.tv_sec = 1, .tv_usec = 600000}; if (ccn_util_timestamp_window(×tamp, &window) == 0) { /* Timestamp too far away, this may be a replay attack */ DEBUG_PRINT("%d %s Timestamp too distant\n", __LINE__, __func__); goto TimestampFail; } new_name = ccn_charbuf_create(); ccn_name_init(new_name); res = ccn_name_append_components(new_name, decrypted->buf, decrypted_comps->buf[1], decrypted_comps->buf[ncomps-1]); if (res < 0) { DEBUG_PRINT("ABORT %d %s unable to append components\n", __LINE__, __func__); goto AppendCompFail; } /*Construct new Interest*/ if (tmpl_size == 0) { /* Detected default template */ DEBUG_PRINT("%d %s Using default Interest template\n", __LINE__, __func__); new_interest = NULL; } else { DEBUG_PRINT("%d %s Copying Interest template\n", __LINE__, __func__); new_interest = ccn_charbuf_create(); ccn_charbuf_append(new_interest, tmpl, tmpl_size); } /*Map new name to that of the original Interest and the requested symkey */ hashtb_start(server->cname_to_pair, e); res = hashtb_seek(e, new_name->buf, new_name->length, 0); if (res == HT_NEW_ENTRY) { struct andana_server_pair *p = andana_server_pair_init(orig_name, symkey); struct andana_server_pair **loc = e->data; *loc = p; } else if (res == HT_OLD_ENTRY) { DEBUG_PRINT("Interest recording found old entry\n"); goto LookupFail; } else { DEBUG_PRINT("Error in Interest insertion\n"); goto LookupFail; } DEBUG_PRINT("%d %s starting to write new interest\n", __LINE__, __func__); res = ccn_express_interest(proxy->handle, new_name, proxy->content_handler, new_interest); DEBUG_PRINT("%d %s done to writing new interest\n", __LINE__, __func__); if(res != 0) { DEBUG_PRINT("ABORT %d %s express interest res = %d\n", __LINE__, __func__, res); goto SendFail; } upcall_res = CCN_UPCALL_RESULT_OK; SendFail: LookupFail: if (upcall_res == CCN_UPCALL_RESULT_ERR) { hashtb_delete(e); } hashtb_end(e); if (new_interest != NULL) { ccn_charbuf_destroy(&new_interest); } TimestampFail: AppendCompFail: ccn_charbuf_destroy(&new_name); CompExtractFail: ccn_charbuf_destroy(&decrypted); free(encrypted); ccn_crypto_symkey_destroy(&symkey); SessionParseFail: ccn_indexbuf_destroy(&decrypted_comps); SessionFail: ccn_charbuf_destroy(&orig_name); ccn_indexbuf_destroy(&orig_name_indexbuf); DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(upcall_res); } /** * Encapsulate and encrypt returning content objects. Encryption * uses the ephemeral symmetric key provided by the user in the original * interest (stored in a pair). * * This node will naturally sign the outgoing content object, thus providing * verifiability. */ enum ccn_upcall_res andana_server_encap_content( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { enum ccn_upcall_res upcall_res = CCN_UPCALL_RESULT_ERR; struct andana_server *server = selfp->data; struct ccn_proxy *proxy = server->proxy; struct ccn_charbuf *new_name = NULL; struct andana_server_pair **pair_ptr = NULL; struct ccn_charbuf *new_content = NULL; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ int res; DEBUG_PRINT("IN %d %s\n",__LINE__, __func__); switch (kind) { case CCN_UPCALL_CONTENT: /**< incoming verified content */ DEBUG_PRINT("%d %s Incoming verified content\n",__LINE__, __func__); break; case CCN_UPCALL_CONTENT_UNVERIFIED:/**< content that has not been verified */ DEBUG_PRINT("%d %s Incoming unverified content\n", __LINE__, __func__); break; case CCN_UPCALL_CONTENT_BAD: /**< verification failed */ DEBUG_PRINT("%d %s Incoming bad content (verification failure)\n", __LINE__, __func__); break; case CCN_UPCALL_INTEREST_TIMED_OUT:/**< interest timed out */ { DEBUG_PRINT("OUT %d %s Interest timed out\n", __LINE__, __func__); const unsigned char *name = info->interest_ccnb + info->pi->offset[CCN_PI_B_Name]; const size_t length = info->pi->offset[CCN_PI_E_Name] - info->pi->offset[CCN_PI_B_Name]; hashtb_start(server->cname_to_pair, e); hashtb_seek(e, name, length, 0); hashtb_delete(e); hashtb_end(e); return(CCN_UPCALL_RESULT_OK); } case CCN_UPCALL_FINAL:/**< handler is about to be deregistered */ DEBUG_PRINT("OUT %d %s final upcall\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST: /**< incoming interest */ case CCN_UPCALL_CONSUMED_INTEREST: /**< incoming interest, someone has answered */ default: DEBUG_PRINT("OUT %d %s upcall other kind = %d\n", __LINE__, __func__, kind); return(CCN_UPCALL_RESULT_ERR); } DEBUG_PRINT("%d %s Received content object\n", __LINE__, __func__); if (info->content_ccnb == NULL) { DEBUG_PRINT("OUT %d %s in content upcall, but no content, check kind: %d\n", __LINE__, __func__, kind); return(CCN_UPCALL_RESULT_OK); } /*Find name in Content Object*/ new_name = ccn_charbuf_create(); ccn_name_init(new_name); ccn_name_append_components(new_name, info->content_ccnb, info->content_comps->buf[0], info->content_comps->buf[info->matched_comps]); #ifdef PROXYDEBUG DEBUG_PRINT("name matches %d comps\n", info->matched_comps); ccn_util_print_pc_fmt(info->content_ccnb + info->pco->offset[CCN_PCO_B_Name], info->pco->offset[CCN_PCO_E_Name] - info->pco->offset[CCN_PCO_B_Name]); DEBUG_PRINT("\n"); #endif pair_ptr = hashtb_lookup(server->cname_to_pair, new_name->buf, new_name->length); if(pair_ptr == NULL) { /* No match for name*/ #ifdef PROXYDEBUG DEBUG_PRINT("Unsolicited content object with name: "); ccn_util_print_pc_fmt(new_name->buf, new_name->length); DEBUG_PRINT("\n"); #endif goto LookupFail; } struct ccn_charbuf *orig_name = (*pair_ptr)->name; struct ccn_pkey *symkey = (*pair_ptr)->symkey; /*Created signed info for new content object*/ unsigned char *encrypted_content = NULL; size_t encrypted_length; struct ccn_charbuf *content = ccn_charbuf_create(); ccn_charbuf_append(content, info->content_ccnb, info->pco->offset[CCN_PCO_E]); ccn_crypto_content_encrypt(symkey, content->buf, content->length, &encrypted_content, &encrypted_length); new_content = ccn_charbuf_create(); sp.type = CCN_CONTENT_DATA; res = ccn_sign_content(proxy->handle, new_content, orig_name, &sp, encrypted_content, encrypted_length); if (ccn_util_validate_content_object(new_content->buf, new_content->length) != 0) { DEBUG_PRINT("ABORT %d %s Failed to validated signed content\n", __LINE__, __func__); abort(); goto SignFail; } else { DEBUG_PRINT("OK %d %s signed content is valid\n", __LINE__, __func__); } if (res != 0) { DEBUG_PRINT("ABORT %d %s Failed to encode ContentObject (res == %d)\n", __LINE__, __func__, res); goto SignFail; } DEBUG_PRINT("%d %s starting content write\n", __LINE__, __func__); res = ccn_put(proxy->handle, new_content->buf, new_content->length); DEBUG_PRINT("%d %s done content write line\n", __LINE__, __func__); if (res < 0) { DEBUG_PRINT("ABORT %d %s ccn_put failed (res == %d)\n", __LINE__, __func__, res); goto SendFail; } DEBUG_PRINT("%d %s Reply sent\n", __LINE__, __func__); upcall_res = CCN_UPCALL_RESULT_OK; SendFail: hashtb_start(server->cname_to_pair, e); hashtb_seek(e, new_name->buf, new_name->length, 0); hashtb_delete(e); hashtb_end(e); SignFail: ccn_charbuf_destroy(&new_content); free(encrypted_content); ccn_charbuf_destroy(&content); LookupFail: ccn_charbuf_destroy(&new_name); DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(upcall_res); } /** * Clean up and destroy anonymous server object. Expect * to be called once at program close. * * @param pointer to anonymous server to be destroyed * @returns 0 (always) */ int andana_server_destroy(struct andana_server **server) { struct andana_server *s = *server; free(s->proxy->int_handler); free(s->proxy->content_handler); ccn_proxy_destroy(&(s->proxy)); ccn_crypto_pubkey_destroy(&(s->privkey)); hashtb_destroy(&(s->cname_to_pair)); free(s); return(0); }
/* does that mean the last component is the implicit digest ? */ enum ccn_upcall_res packet_handler(struct ccn_closure *selfp, enum ccn_upcall_kind upcall_kind, struct ccn_upcall_info *info) { handler_data* h_data = (handler_data*) selfp->data; // Client data returned fprintf(stderr, "\nUpcall from %s handle\n", (info->h==(*h_data->ccn_rec))? "receiver":"publisher"); ccn_set_run_timeout(info->h, 0); // Return to client faster switch(upcall_kind) { case CCN_UPCALL_FINAL: fprintf(stderr, "CCN_UPCALL_FINAL\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST_TIMED_OUT: fprintf(stderr, "CCN_UPCALL_INTEREST_TIMED_OUT\n"); (*h_data->complete) = 1; // End the main loop, some sort of problem return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT: fprintf(stderr, "CCN_UPCALL_CONTENT\n"); const unsigned char* content = NULL; size_t content_bytes = 0; ccn_ref_tagged_BLOB(CCN_DTAG_Content, info->content_ccnb, info->pco->offset[CCN_PCO_B_Content], info->pco->offset[CCN_PCO_E_Content], &content, &content_bytes); fprintf(stderr, "\tContent: %s\n", content); (*h_data->outstanding_interests)--; return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT_UNVERIFIED: fprintf(stderr, "CCN_UPCALL_CONTENT_UNVERIFIED\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT_BAD: fprintf(stderr, "CCN_UPCALL_CONTENT_BAD\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONSUMED_INTEREST: fprintf(stderr, "CCN_UPCALL_CONSUMED_INTEREST\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST: fprintf(stderr, "CCN_UPCALL_INTEREST, (matched comp == %d)\n", info->matched_comps); fprintf(stderr, " (interest comps == %zu)\n", info->interest_comps->n); int res = 0; // Corrected 20-May-2011 to support interests with additional components after prefix // if (info->interest_comps->n < 3) { // Name + signature + implicit digest, minimum fprintf(stderr, "\tnot enough components, %zu<3\n", info->interest_comps->n); } else { // Verify the interest res = verify_signed_interest(info->interest_ccnb, info->interest_comps, info->interest_comps->n-2, info->interest_comps->buf[0], info->interest_comps->buf[info->interest_comps->n-2], (*h_data->public_key)); fprintf(stderr, "\tverify_signed_interest == %d (%s)\n", res, (res==1)?"verified":"unverified"); } // Based on the results, // create and send a reply using default key & algorithm for the receiving handle // to sign the content object. // char* reply_data = (res==1) ? "OK" : "AUTH_FAIL"; // A modest content. struct ccn_charbuf* reply = ccn_charbuf_create(); struct ccn_charbuf* name = ccn_charbuf_create(); struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; ccn_name_init(name); // Don't need to create a new name, could just index into the buffer. res = ccn_name_append_components(name, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[info->interest_comps->n - 1]); ccn_sign_content(info->h, reply, name, &sp, (void*)reply_data, strlen(reply_data)+1); res = ccn_put(info->h, reply->buf, reply->length); ccn_charbuf_destroy(&reply); ccn_charbuf_destroy(&name); if (res >= 0) { fprintf (stderr, "\tReturned Content: %s\n", reply_data); return (CCN_UPCALL_RESULT_INTEREST_CONSUMED); } return (CCN_UPCALL_RESULT_OK); } return (CCN_UPCALL_RESULT_ERR); }
// creates a full structure without action, if proto == "face" only the // faceid (from cmd_host parameter) and lifetime will be filled in. struct ccn_face_instance * parse_ccn_face_instance(struct ccndc_data *self, const char *cmd_proto, const char *cmd_host, const char *cmd_port, const char *cmd_mcastttl, const char *cmd_mcastif, int freshness) { struct ccn_face_instance *entry; struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG)}; struct addrinfo mcasthints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG | AI_NUMERICHOST)}; struct addrinfo *raddrinfo = NULL; struct addrinfo *mcastifaddrinfo = NULL; char rhostnamebuf [NI_MAXHOST]; char rhostportbuf [NI_MAXSERV]; int off_address = -1, off_port = -1, off_source_address = -1; int res; int socktype; entry = calloc(1, sizeof(*entry)); if (entry == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // allocate storage for Face data entry->store = ccn_charbuf_create(); if (entry->store == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; if (cmd_proto == NULL) { ccndc_warn(__LINE__, "command error, missing address type\n"); goto ExitOnError; } if (strcasecmp(cmd_proto, "udp") == 0) { entry->descr.ipproto = IPPROTO_UDP; socktype = SOCK_DGRAM; } else if (strcasecmp(cmd_proto, "tcp") == 0) { entry->descr.ipproto = IPPROTO_TCP; socktype = SOCK_STREAM; } else if (strcasecmp(cmd_proto, "face") == 0) { errno = 0; unsigned long faceid = strtoul(cmd_host, (char **)NULL, 10); if (errno == ERANGE || errno == EINVAL || faceid > UINT_MAX || faceid == 0) { ccndc_warn(__LINE__, "command error, face number invalid or out of range '%s'\n", cmd_host); goto ExitOnError; } entry->faceid = (unsigned) faceid; entry->lifetime = freshness; return (entry); } else { ccndc_warn(__LINE__, "command error, unrecognized address type '%s'\n", cmd_proto); goto ExitOnError; } if (cmd_host == NULL) { ccndc_warn(__LINE__, "command error, missing hostname\n"); goto ExitOnError; } if (cmd_port == NULL || cmd_port[0] == 0) cmd_port = CCN_DEFAULT_UNICAST_PORT; hints.ai_socktype = socktype; res = getaddrinfo(cmd_host, cmd_port, &hints, &raddrinfo); if (res != 0 || raddrinfo == NULL) { ccndc_warn(__LINE__, "command error, getaddrinfo for host [%s] port [%s]: %s\n", cmd_host, cmd_port, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), rhostportbuf, sizeof(rhostportbuf), NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(raddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } off_port = entry->store->length; res = ccn_charbuf_append(entry->store, rhostportbuf, strlen(rhostportbuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } entry->descr.mcast_ttl = -1; if (cmd_mcastttl != NULL) { char *endptr; entry->descr.mcast_ttl = strtol(cmd_mcastttl, &endptr, 10); if ((endptr != &cmd_mcastttl[strlen(cmd_mcastttl)]) || entry->descr.mcast_ttl < 0 || entry->descr.mcast_ttl > 255) { ccndc_warn(__LINE__, "command error, invalid multicast ttl: %s\n", cmd_mcastttl); goto ExitOnError; } } if (cmd_mcastif != NULL) { res = getaddrinfo(cmd_mcastif, NULL, &mcasthints, &mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, incorrect multicat interface [%s]: " "mcastifaddr getaddrinfo: %s\n", cmd_mcastif, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(mcastifaddrinfo->ai_addr, mcastifaddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_source_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } } entry->descr.address = (const char *)(entry->store->buf + off_address); entry->descr.port = (const char *)(entry->store->buf + off_port); if (off_source_address >= 0) { entry->descr.source_address = (const char *)(entry->store->buf + off_source_address); } entry->lifetime = freshness; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } struct ccn_face_instance * parse_ccn_face_instance_from_face(struct ccndc_data *self, const char *cmd_faceid) { struct ccn_face_instance *entry = calloc(1, sizeof(*entry)); // allocate storage for Face data entry->store = ccn_charbuf_create(); // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; /* destroy a face - the URI field will hold the face number */ if (cmd_faceid == NULL) { ccndc_warn(__LINE__, "command error, missing face number for destroyface\n"); goto ExitOnError; } char *endptr; int facenumber = strtol(cmd_faceid, &endptr, 10); if ((endptr != &cmd_faceid[strlen(cmd_faceid)]) || facenumber < 0) { ccndc_warn(__LINE__, "command error invalid face number for destroyface: %d\n", facenumber); goto ExitOnError; } entry->faceid = facenumber; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // "private section /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ccndc_get_ccnd_id(struct ccndc_data *self) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"; const unsigned char *ccndid_result; int res = 0; name = ccn_charbuf_create(); if (name == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for service locator name charbuf\n"); return -1; } resultbuf = ccn_charbuf_create(); if (resultbuf == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for result charbuf"); res = -1; goto Cleanup; } res = ccn_name_from_uri(name, ccndid_uri); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse service locator URI for ccnd key"); goto Cleanup; } res = ccn_get(self->ccn_handle, name, self->local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0); if (res < 0) { ccndc_warn(__LINE__, "Unable to get key from ccnd"); goto Cleanup; } res = ccn_ref_tagged_BLOB (CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid_result, &self->ccnd_id_size); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse ccnd response for ccnd id"); goto Cleanup; } if (self->ccnd_id_size > sizeof (self->ccnd_id)) { ccndc_warn(__LINE__, "Incorrect size for ccnd id in response"); goto Cleanup; } memcpy(self->ccnd_id, ccndid_result, self->ccnd_id_size); Cleanup: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&resultbuf); return (res); } struct ccn_face_instance * ccndc_do_face_action(struct ccndc_data *self, const char *action, struct ccn_face_instance *face_instance) { struct ccn_charbuf *newface = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance *new_face_instance = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res = 0; face_instance->action = action; /* Encode the given face instance */ newface = ccn_charbuf_create(); ON_NULL_CLEANUP(newface); ON_ERROR_CLEANUP(ccnb_append_face_instance(newface, face_instance)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, newface->buf, newface->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); /* Construct the Interest name that will create the face */ name = ccn_charbuf_create(); ON_NULL_CLEANUP(name); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, face_instance->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_face_instance = ccn_face_instance_parse(ptr, length); ON_NULL_CLEANUP(new_face_instance); ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return (new_face_instance); Cleanup: ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_face_instance_destroy(&new_face_instance); return (NULL); } int ccndc_do_prefix_action(struct ccndc_data *self, const char *action, struct ccn_forwarding_entry *forwarding_entry) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry *new_forwarding_entry = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res; forwarding_entry->action = action; prefixreg = ccn_charbuf_create(); ON_NULL_CLEANUP(prefixreg); ON_ERROR_CLEANUP(ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, prefixreg->buf, prefixreg->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); name = ccn_charbuf_create(); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, forwarding_entry->ccnd_id, forwarding_entry->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, forwarding_entry->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (res); /* This is where ON_ERROR_CLEANUP sends us in case of an error * and we must free any storage we allocated before returning. */ Cleanup: ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (-1); }
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 sign_content_with_user_defined_keystore(struct ccn_charbuf *content_name, struct ccn_charbuf *resultbuf, const void *data, size_t data_size, char *keystore_path, char *keystore_passphrase, char *key_repo_name, char *site_name, char *router_name){ if ( nlsr->debugging ) printf("sign_content_with_user_defined_keystore called\n"); int res; struct ccn_charbuf * pubid_out=ccn_charbuf_create(); struct ccn_charbuf * keyname; struct ccn_keystore *keystore = NULL; keystore=ccn_keystore_create(); res=ccn_keystore_init(keystore, keystore_path,keystore_passphrase ); if ( res < 0 ){ if ( nlsr->debugging ) printf("Error in initiating keystore :(\n"); ccn_keystore_destroy(&keystore); return -1; } res=ccn_load_private_key (nlsr->ccn, keystore_path, keystore_passphrase, pubid_out); if(res < 0 ){ if ( nlsr->debugging ) printf("Error in loading keystore :( \n"); ccn_charbuf_destroy(&pubid_out); return -1; } char *baseuri=(char *)calloc(strlen(key_repo_name)+strlen(site_name)+ strlen(router_name)+strlen("/%C1.R.N.Start")+5,sizeof(char)); memcpy(baseuri,key_repo_name,strlen(key_repo_name)+1); if ( site_name[0] != '/') memcpy(baseuri+strlen(baseuri),"/",1); memcpy(baseuri+strlen(baseuri),site_name,strlen(site_name)+1); memcpy(baseuri+strlen(baseuri),"/%C1.R.N.Start",strlen("/%C1.R.N.Start")); memcpy(baseuri+strlen(baseuri),router_name,strlen(router_name)+1); baseuri[strlen(baseuri)]='\0'; keyname=ccn_charbuf_create(); if(keyname == NULL ){ ccn_charbuf_destroy(&pubid_out); free(baseuri); return -1; } ccn_name_from_uri(keyname,baseuri); if ( res < 0 ){ if ( nlsr->debugging ) printf("Bad URI format: %s\n",baseuri); ccn_charbuf_destroy(&pubid_out); ccn_charbuf_destroy(&keyname); free(baseuri); return -1; } ccn_name_append_str(keyname,"nlsr"); struct ccn_charbuf *keyid = ccn_charbuf_create(); ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1); ccn_charbuf_append_string(keyid, ".M.K"); ccn_charbuf_append_value(keyid, 0, 1); ccn_charbuf_append_charbuf(keyid, pubid_out); ccn_name_append(keyname, keyid->buf, keyid->length); struct ccn_charbuf *uri = ccn_charbuf_create(); ccn_uri_append(uri, keyname->buf, keyname->length, 0); if ( nlsr->debugging ) printf("Key Name Included when processing content: %s\n", ccn_charbuf_as_string(uri)); ccn_charbuf_destroy(&uri); struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; sp.type = CCN_CONTENT_DATA; sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG); ccn_charbuf_append(sp.template_ccnb, keyname->buf, keyname->length); ccn_charbuf_append_closer(sp.template_ccnb); // KeyName closer ccn_charbuf_append_closer(sp.template_ccnb); // KeyLocator closer ccn_charbuf_append_closer(sp.template_ccnb); // SignedInfo closer sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; sp.sp_flags |= CCN_SP_FINAL_BLOCK; sp.freshness = 60; if (pubid_out->length != sizeof(sp.pubid)){ if ( nlsr->debugging ) printf("Size of pubid and sp.pubid is not equal"); ccn_charbuf_destroy(&keyname); ccn_charbuf_destroy(&pubid_out); free(baseuri); return -1; } memcpy(sp.pubid, pubid_out->buf, pubid_out->length); res=ccn_sign_content(nlsr->ccn,resultbuf,content_name,&sp,data,data_size); if( res < 0 ){ if ( nlsr->debugging ) printf("Content signing error \n"); ccn_charbuf_destroy(&sp.template_ccnb); ccn_charbuf_destroy(&keyid); ccn_charbuf_destroy(&keyname); ccn_charbuf_destroy(&pubid_out); free(baseuri); return -1; } ccn_charbuf_destroy(&sp.template_ccnb); ccn_charbuf_destroy(&keyid); ccn_charbuf_destroy(&keyname); ccn_charbuf_destroy(&pubid_out); free(baseuri); return 0; }
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; }
static int write_slice(struct ccn *h, struct ccns_slice *slice, struct ccn_charbuf *name) { struct ccn_charbuf *content = NULL; unsigned char *cbuf = NULL; size_t clength = 0; struct ccn_charbuf *sw = NULL; struct ccn_charbuf *templ = NULL; struct ccn_charbuf *cob = NULL; struct ccn_signing_params sparm = CCN_SIGNING_PARAMS_INIT; struct ccn_closure *wc = NULL; int res; sw = ccn_charbuf_create_n(32 + name->length); if (sw == NULL) { res = -1; goto Cleanup; } ccn_charbuf_append_charbuf(sw, name); ccn_name_chop(sw, NULL, -1); // remove segment number ccn_name_from_uri(sw, "%C1.R.sw"); ccn_name_append_nonce(sw); // create and sign the content object cob = ccn_charbuf_create(); if (cob == NULL) { res = -1; goto Cleanup; } if (slice != NULL) { content = ccn_charbuf_create(); if (content == NULL) { res = -1; goto Cleanup; } res = append_slice(content, slice); if (res < 0) goto Cleanup; cbuf = content->buf; clength = content->length; } else { sparm.type = CCN_CONTENT_GONE; } sparm.sp_flags = CCN_SP_FINAL_BLOCK; res = ccn_sign_content(h, cob, name, &sparm, cbuf, clength); if (res < 0) goto Cleanup; // establish handler for interest in the slice content object wc = calloc(1, sizeof(*wc)); if (wc == NULL) { res = -1; goto Cleanup; } wc->p = &write_interest_handler; wc->data = cob; res = ccn_set_interest_filter(h, name, wc); if (res < 0) goto Cleanup; templ = make_scope1_template(); if (templ == NULL) { res = -1; goto Cleanup; } res = ccn_get(h, sw, templ, 1000, NULL, NULL, NULL, 0); if (res < 0) goto Cleanup; ccn_run(h, 1000); // give the repository a chance to fetch the data if (wc->intdata != 1) { res = -1; goto Cleanup; } res = 0; Cleanup: ccn_set_interest_filter(h, name, NULL); if (wc != NULL) free(wc); ccn_charbuf_destroy(&cob); ccn_charbuf_destroy(&content); ccn_charbuf_destroy(&sw); ccn_charbuf_destroy(&templ); return (res); }
int main(int argc, char **argv) { const char *progname = argv[0]; struct ccn *ccn = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *pname = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *extopt = NULL; long expire = -1; int versioned = 0; size_t blocksize = 8*1024; int status = 0; int res; ssize_t read_res; unsigned char *buf = NULL; enum ccn_content_type content_type = CCN_CONTENT_DATA; struct ccn_closure in_interest = {.p=&incoming_interest}; const char *postver = NULL; const char *key_uri = NULL; int force = 0; int verbose = 0; int timeout = -1; int setfinal = 0; int prefixcomps = -1; int fd; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; while ((res = getopt(argc, argv, "e:fhk:lvV:p:t:w:x:")) != -1) { switch (res) { case 'e': if (extopt == NULL) extopt = ccn_charbuf_create(); fd = open(optarg, O_RDONLY); if (fd < 0) { perror(optarg); exit(1); } for (;;) { read_res = read(fd, ccn_charbuf_reserve(extopt, 64), 64); if (read_res <= 0) break; extopt->length += read_res; } if (read_res < 0) perror(optarg); close(fd); break; case 'f': force = 1; break; case 'l': setfinal = 1; // set FinalBlockID to last comp of name break; case 'k': key_uri = optarg; break; case 'p': prefixcomps = atoi(optarg); if (prefixcomps < 0) usage(progname); break; case 'x': expire = atol(optarg); if (expire <= 0) usage(progname); break; case 'v': verbose = 1; break; case 'V': versioned = 1; postver = optarg; if (0 == memcmp(postver, "%00", 3)) setfinal = 1; break; case 'w': timeout = atol(optarg); if (timeout <= 0) usage(progname); timeout *= 1000; break; case 't': if (0 == strcasecmp(optarg, "DATA")) { content_type = CCN_CONTENT_DATA; break; } if (0 == strcasecmp(optarg, "ENCR")) { content_type = CCN_CONTENT_ENCR; break; } if (0 == strcasecmp(optarg, "GONE")) { content_type = CCN_CONTENT_GONE; break; } if (0 == strcasecmp(optarg, "KEY")) { content_type = CCN_CONTENT_KEY; break; } if (0 == strcasecmp(optarg, "LINK")) { content_type = CCN_CONTENT_LINK; break; } if (0 == strcasecmp(optarg, "NACK")) { content_type = CCN_CONTENT_NACK; break; } content_type = atoi(optarg); if (content_type > 0 && content_type <= 0xffffff) break; fprintf(stderr, "Unknown content type %s\n", optarg); /* FALLTHRU */ default: case 'h': usage(progname); break; } } argc -= optind; argv += optind; if (argv[0] == NULL) usage(progname); name = ccn_charbuf_create(); res = ccn_name_from_uri(name, argv[0]); if (res < 0) { fprintf(stderr, "%s: bad ccn URI: %s\n", progname, argv[0]); exit(1); } if (argv[1] != NULL) fprintf(stderr, "%s warning: extra arguments ignored\n", progname); /* Preserve the original prefix, in case we add versioning, * but trim it down if requested for the interest filter registration */ pname = ccn_charbuf_create(); ccn_charbuf_append(pname, name->buf, name->length); if (prefixcomps >= 0) { res = ccn_name_chop(pname, NULL, prefixcomps); if (res < 0) { fprintf(stderr, "%s: unable to trim name to %d component%s.\n", progname, prefixcomps, prefixcomps == 1 ? "" : "s"); exit(1); } } /* Connect to ccnd */ ccn = ccn_create(); if (ccn_connect(ccn, NULL) == -1) { perror("Could not connect to ccnd"); exit(1); } /* Read the actual user data from standard input */ buf = calloc(1, blocksize); read_res = read_full(0, buf, blocksize); if (read_res < 0) { perror("read"); read_res = 0; status = 1; } /* Tack on the version component if requested */ if (versioned) { res = ccn_create_version(ccn, name, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0); if (res < 0) { fprintf(stderr, "%s: ccn_create_version() failed\n", progname); exit(1); } if (postver != NULL) { res = ccn_name_from_uri(name, postver); if (res < 0) { fprintf(stderr, "-V %s: invalid name suffix\n", postver); exit(0); } } } temp = ccn_charbuf_create(); /* Ask for a FinalBlockID if appropriate. */ if (setfinal) sp.sp_flags |= CCN_SP_FINAL_BLOCK; if (res < 0) { fprintf(stderr, "Failed to create signed_info (res == %d)\n", res); exit(1); } /* Set content type */ sp.type = content_type; /* Set freshness */ if (expire >= 0) { if (sp.template_ccnb == NULL) { sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); } else if (sp.template_ccnb->length > 0) { sp.template_ccnb->length--; } ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expire); sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS; ccn_charbuf_append_closer(sp.template_ccnb); } /* Set key locator, if supplied */ if (key_uri != NULL) { struct ccn_charbuf *c = ccn_charbuf_create(); res = ccn_name_from_uri(c, key_uri); if (res < 0) { fprintf(stderr, "%s is not a valid ccnx URI\n", key_uri); exit(1); } if (sp.template_ccnb == NULL) { sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); } else if (sp.template_ccnb->length > 0) { sp.template_ccnb->length--; } ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG); ccn_charbuf_append(sp.template_ccnb, c->buf, c->length); ccn_charbuf_append_closer(sp.template_ccnb); ccn_charbuf_append_closer(sp.template_ccnb); sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; ccn_charbuf_append_closer(sp.template_ccnb); ccn_charbuf_destroy(&c); } if (extopt != NULL && extopt->length > 0) { if (sp.template_ccnb == NULL) { sp.template_ccnb = ccn_charbuf_create(); ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG); } else if (sp.template_ccnb->length > 0) { sp.template_ccnb->length--; } ccnb_append_tagged_blob(sp.template_ccnb, CCN_DTAG_ExtOpt, extopt->buf, extopt->length); sp.sp_flags |= CCN_SP_TEMPL_EXT_OPT; ccn_charbuf_append_closer(sp.template_ccnb); } /* Create the signed content object, ready to go */ temp->length = 0; res = ccn_sign_content(ccn, temp, name, &sp, buf, read_res); if (res != 0) { fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res); exit(1); } if (read_res == blocksize) { read_res = read_full(0, buf, 1); if (read_res == 1) { fprintf(stderr, "%s: warning - truncated data\n", argv[0]); status = 1; } } free(buf); buf = NULL; if (force) { /* At user request, send without waiting to see an interest */ res = ccn_put(ccn, temp->buf, temp->length); if (res < 0) { fprintf(stderr, "ccn_put failed (res == %d)\n", res); exit(1); } } else { in_interest.data = temp; /* Set up a handler for interests */ res = ccn_set_interest_filter(ccn, pname, &in_interest); if (res < 0) { fprintf(stderr, "Failed to register interest (res == %d)\n", res); exit(1); } res = ccn_run(ccn, timeout); if (in_interest.intdata == 0) { if (verbose) fprintf(stderr, "Nobody's interested\n"); exit(1); } } if (verbose) { struct ccn_charbuf *uri = ccn_charbuf_create(); uri->length = 0; ccn_uri_append(uri, name->buf, name->length, 1); printf("wrote %s\n", ccn_charbuf_as_string(uri)); ccn_charbuf_destroy(&uri); } ccn_destroy(&ccn); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&pname); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&sp.template_ccnb); ccn_charbuf_destroy(&extopt); exit(status); }