예제 #1
0
/**
 * Advance the last Component of a Name to the next possible value.
 * @param c contains a ndnb-encoded Name to be updated.
 * @returns -1 for error, otherwise the number of Components
 */
int
ndn_name_next_sibling(struct ndn_charbuf *c)
{
    int res = -1;
    struct ndn_indexbuf *ndx;
    unsigned char *lastcomp = NULL;
    size_t lastcompsize = 0;
    size_t i;
    int carry;
    struct ndn_charbuf *newcomp;

    ndx = ndn_indexbuf_create();
    if (ndx == NULL) goto Finish;
    res = ndn_name_split(c, ndx);
    if (res <= 0) {
        res = -1;
        goto Finish;
    }
    res = ndn_ref_tagged_BLOB(NDN_DTAG_Component, c->buf,
        ndx->buf[res-1], ndx->buf[res],
        (const unsigned char **)&lastcomp,
        &lastcompsize);
    if (res < 0) goto Finish;
    for (carry = 1, i = lastcompsize; carry && i > 0; i--) {
        carry = (((++lastcomp[i-1]) & 0xFF) == 0x00);
    }
    if (carry) {
        newcomp = ndn_charbuf_create();
        res |= ndn_charbuf_append_value(newcomp, 0, 1);
        res |= ndn_charbuf_append(newcomp, lastcomp, lastcompsize);
        res |= ndn_name_chop(c, ndx, ndx->n - 2);
        res |= ndn_name_append(c, newcomp->buf, newcomp->length);
        ndn_charbuf_destroy(&newcomp);
        if (res < 0) goto Finish;
    }
    res = ndx->n - 1;
Finish:
    ndn_indexbuf_destroy(&ndx);
    return(res);
}
예제 #2
0
PyObject *
KeyLocator_obj_from_ndn(PyObject *py_keylocator)
{
    struct ndn_buf_decoder decoder, *d;
    struct ndn_charbuf *keylocator;
    struct ndn_charbuf *name;
    struct ndn_pkey *pubkey;
    size_t start, stop;
    int r;
    PyObject *py_o;
    PyObject *py_KeyLocator_obj = NULL;

    keylocator = NDNObject_Get(KEY_LOCATOR, py_keylocator);

    debug("KeyLocator_from_ndn start\n");

    d = ndn_buf_decoder_start(&decoder, keylocator->buf, keylocator->length);
    assert(d); //should always succeed

    if (!ndn_buf_match_dtag(d, NDN_DTAG_KeyLocator)) {
        PyErr_SetString(g_PyExc_NDNKeyLocatorError, "The input isn't a valid"
                        " KeyLocator");
        return NULL;
    }
    ndn_buf_advance(d);

    if (ndn_buf_match_dtag(d, NDN_DTAG_KeyName)) {
        const unsigned char *bname;
        size_t bname_size;
        PyObject *py_name_obj;

        ndn_buf_advance(d);

        start = d->decoder.token_index;
        r = ndn_parse_Name(d, NULL);
        stop = d->decoder.token_index;
        if (r < 0)
            return PyErr_Format(g_PyExc_NDNKeyLocatorError, "Error finding"
                                " NDN_DTAG_Name for KeyName (decoder state: %d)",
                                d->decoder.state);

        assert(stop > start);
        bname_size = stop - start;
        bname = d->buf + start;
        /*
        		r = ndn_ref_tagged_BLOB(NDN_DTAG_Name, d->buf, start, stop, &bname,
        				&bname_size);
        		if (r < 0)
        			return PyErr_Format(g_PyExc_NDNKeyLocatorError, "Error getting"
        				" NDN_DTAG_Name BLOB for KeyName (decoder state: %d)",
        				d->decoder.state);
         */

        debug("Parse NDN_DTAG_Name inside KeyName, len=%zd\n", bname_size);

        py_o = NDNObject_New_charbuf(NAME, &name);
        if (!py_o)
            return NULL;

        r = ndn_charbuf_append(name, bname, bname_size);
        if (r < 0) {
            Py_DECREF(py_o);
            return PyErr_NoMemory();
        }

        py_name_obj = Name_obj_from_ndn(py_o);
        Py_DECREF(py_o);
        if (!py_name_obj)
            return NULL;

        py_KeyLocator_obj = PyObject_CallObject(g_type_KeyLocator, NULL);
        if (!py_KeyLocator_obj) {
            Py_DECREF(py_name_obj);
            goto error;
        }

        r = PyObject_SetAttrString(py_KeyLocator_obj, "keyName", py_name_obj);
        Py_DECREF(py_name_obj);
        JUMP_IF_NEG(r, error);

#pragma message "Parse and add digest to the keylocator"
    } else if (ndn_buf_match_dtag(d, NDN_DTAG_Key)) {
        const unsigned char *dkey;
        size_t dkey_size;
        PyObject *py_key_obj, *py_ndn_key;

        start = d->decoder.token_index;
        r = ndn_parse_required_tagged_BLOB(d, NDN_DTAG_Key, 1, -1);
        stop = d->decoder.token_index;
        if (r < 0)
            return PyErr_Format(g_PyExc_NDNKeyLocatorError, "Error finding"
                                " NDN_DTAG_Key for Key (decoder state: %d)", d->decoder.state);

        r = ndn_ref_tagged_BLOB(NDN_DTAG_Key, d->buf, start, stop, &dkey,
                                &dkey_size);
        if (r < 0)
            return PyErr_Format(g_PyExc_NDNKeyLocatorError, "Error getting"
                                " NDN_DTAG_Key BLOB for Key (decoder state: %d)",
                                d->decoder.state);

        debug("Parse NDN_DTAG_Key, len=%zd\n", dkey_size);

        pubkey = ndn_d2i_pubkey(dkey, dkey_size); // free with ndn_pubkey_free()
        if (!pubkey) {
            PyErr_SetString(g_PyExc_NDNKeyLocatorError, "Unable to parse key to"
                            " internal representation");
            return NULL;
        }
        py_ndn_key = NDNObject_New(PKEY_PUB, pubkey);
        if (!py_ndn_key) {
            ndn_pubkey_free(pubkey);
            return NULL;
        }

        py_key_obj = Key_obj_from_ndn(py_ndn_key);
        Py_DECREF(py_ndn_key);
        if (!py_key_obj)
            return NULL;

        py_KeyLocator_obj = PyObject_CallObject(g_type_KeyLocator, NULL);
        if (!py_KeyLocator_obj) {
            Py_DECREF(py_key_obj);
            goto error;
        }

        r = PyObject_SetAttrString(py_KeyLocator_obj, "key", py_key_obj);
        Py_DECREF(py_key_obj);
        JUMP_IF_NEG(r, error);
    } else if (ndn_buf_match_dtag(d, NDN_DTAG_Certificate)) {
        PyErr_SetString(PyExc_NotImplementedError, "Found certificate DTAG,"
                        " which currently is unsupported");
        return NULL;
    } else {
        PyErr_SetString(g_PyExc_NDNKeyLocatorError, "Unknown KeyLocator Type");
        return NULL;
    }

    ndn_buf_check_close(d); // we don't really check the parser, though-

    return py_KeyLocator_obj;

error:
    Py_XDECREF(py_KeyLocator_obj);
    return NULL;
}
예제 #3
0
/**
 * Load a link to the repo policy from the repoPolicy file and load the link
 * target to extract the actual policy.
 * If a policy file does not exist a new one is created, with a link to a policy
 * based either on the environment variable NDNR_GLOBAL_PREFIX or the system
 * default value of ndn:/named-data.net/ndn/Repos, plus the system defaults for
 * other fields.
 * This routine must be called after the btree code is initialized and capable
 * of returning content objects.
 * Sets the parsed_policy field of the handle to be the new policy.
 */
static int
load_policy(struct ndnr_handle *ndnr)
{
    int fd;
    ssize_t res;
    struct content_entry *content = NULL;
    const unsigned char *content_msg = NULL;
    struct ndn_parsed_ContentObject pco = {0};
    struct ndn_parsed_Link pl = {0};
    struct ndn_indexbuf *nc = NULL;
    struct ndn_charbuf *basename = NULL;
    struct ndn_charbuf *policy = NULL;
    struct ndn_charbuf *policy_cob = NULL;
    struct ndn_charbuf *policyFileName;
    const char *global_prefix;
    const unsigned char *buf = NULL;
    size_t length = 0;
    int segment = 0;
    int final = 0;
    struct ndn_buf_decoder decoder;
    struct ndn_buf_decoder *d;
    
    policyFileName = ndn_charbuf_create();
    ndn_charbuf_putf(policyFileName, "%s/repoPolicy", ndnr->directory);
    ndnr->parsed_policy = ndnr_parsed_policy_create();
    fd = open(ndn_charbuf_as_string(policyFileName), O_RDONLY);
    if (fd >= 0) {
        ndnr->policy_link_cob = ndn_charbuf_create();
        ndn_charbuf_reserve(ndnr->policy_link_cob, 4096);   // limits the size of the policy link
        ndnr->policy_link_cob->length = 0;    // clear the buffer
        res = read(fd, ndnr->policy_link_cob->buf, ndnr->policy_link_cob->limit - ndnr->policy_link_cob->length);
        close(fd);
        if (res == -1) {
            r_init_fail(ndnr, __LINE__, "Error reading repoPolicy file.", errno);
            ndn_charbuf_destroy(&ndnr->policy_link_cob);
            ndn_charbuf_destroy(&policyFileName);
            return(-1);
        }
        ndnr->policy_link_cob->length = res;
        nc = ndn_indexbuf_create();
        res = ndn_parse_ContentObject(ndnr->policy_link_cob->buf,
                                      ndnr->policy_link_cob->length, &pco, nc);
        res = ndn_ref_tagged_BLOB(NDN_DTAG_Content, ndnr->policy_link_cob->buf,
                                  pco.offset[NDN_PCO_B_Content],
                                  pco.offset[NDN_PCO_E_Content],
                                  &buf, &length);
        d = ndn_buf_decoder_start(&decoder, buf, length);
        res = ndn_parse_Link(d, &pl, NULL);
        if (res <= 0) {
            ndnr_msg(ndnr, "Policy link is malformed.");
            goto CreateNewPolicy;
        }
        basename = ndn_charbuf_create();
        ndn_charbuf_append(basename, buf + pl.offset[NDN_PL_B_Name],
                           pl.offset[NDN_PL_E_Name] - pl.offset[NDN_PL_B_Name]);
        ndnr->policy_name = ndn_charbuf_create(); // to detect writes to this name
        ndn_charbuf_append_charbuf(ndnr->policy_name, basename); // has version
        ndn_name_chop(ndnr->policy_name, NULL, -1); // get rid of version
        policy = ndn_charbuf_create();
        // if we fail to retrieve the link target, report and then create a new one
        do {
            ndn_name_append_numeric(basename, NDN_MARKER_SEQNUM, segment++);
            content = r_store_lookup_ndnb(ndnr, basename->buf, basename->length);
            if (content == NULL) {
                ndnr_debug_ndnb(ndnr, __LINE__, "policy lookup failed for", NULL,
                                basename->buf, basename->length);
                break;
            }
            ndn_name_chop(basename, NULL, -1);
            content_msg = r_store_content_base(ndnr, content);
            if (content_msg == NULL) {
                ndnr_debug_ndnb(ndnr, __LINE__, "Unable to read policy object", NULL,
                                basename->buf, basename->length);
                break;
            }
            res = ndn_parse_ContentObject(content_msg, r_store_content_size(ndnr, content), &pco, nc);
            res = ndn_ref_tagged_BLOB(NDN_DTAG_Content, content_msg,
                                      pco.offset[NDN_PCO_B_Content],
                                      pco.offset[NDN_PCO_E_Content],
                                      &buf, &length);
            ndn_charbuf_append(policy, buf, length);
            final = ndn_is_final_pco(content_msg, &pco, nc);
        } while (!final && segment < 100);
예제 #4
0
int ndn_verify_signature(const unsigned char *msg,
                     size_t size,
                     const struct ndn_parsed_ContentObject *co,
                     const struct ndn_pkey *verification_pubkey)
{
    EVP_MD_CTX verc;
    EVP_MD_CTX *ver_ctx = &verc;
    X509_SIG *digest_info = NULL;
    const unsigned char *dd = NULL;
    MP_info *merkle_path_info = NULL;
    unsigned char *root_hash = NULL;
    size_t root_hash_size;

    int res;

    const EVP_MD *digest = NULL;
    const EVP_MD *merkle_path_digest = NULL;
    
    const unsigned char *signature_bits = NULL;
    size_t signature_bits_size = 0;
    const unsigned char *witness = NULL;
    size_t witness_size = 0;
    const unsigned char *digest_algorithm = NULL;
    size_t digest_algorithm_size;
    
    EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey;

    res = ndn_ref_tagged_BLOB(NDN_DTAG_SignatureBits, msg,
                              co->offset[NDN_PCO_B_SignatureBits],
                              co->offset[NDN_PCO_E_SignatureBits],
                              &signature_bits,
                              &signature_bits_size);
    if (res < 0)
        return (-1);

    if (co->offset[NDN_PCO_B_DigestAlgorithm] == co->offset[NDN_PCO_E_DigestAlgorithm]) {
        digest_algorithm = (const unsigned char *)NDN_SIGNING_DEFAULT_DIGEST_ALGORITHM;
    }
    else {
        /* figure out what algorithm the OID represents */
        res = ndn_ref_tagged_string(NDN_DTAG_DigestAlgorithm, msg,
                                  co->offset[NDN_PCO_B_DigestAlgorithm],
                                  co->offset[NDN_PCO_E_DigestAlgorithm],
                                  &digest_algorithm,
                                  &digest_algorithm_size);
        if (res < 0)
            return (-1);
        /* NOTE: since the element closer is a 0, and the element is well formed,
         * the string will be null terminated 
         */
    }
    digest = md_from_digest_and_pkey((const char *)digest_algorithm, verification_pubkey);
    EVP_MD_CTX_init(ver_ctx);
    res = EVP_VerifyInit_ex(ver_ctx, digest, NULL);
    if (!res) {
        EVP_MD_CTX_cleanup(ver_ctx);
        return (-1);
    }
    if (co->offset[NDN_PCO_B_Witness] != co->offset[NDN_PCO_E_Witness]) {
        /* The witness is a DigestInfo, where the octet-string therein encapsulates
         * a sequence of [integer (origin 1 node#), sequence of [octet-string]]
         * where the inner octet-string is the concatenated hashes on the merkle-path
         */
        res = ndn_ref_tagged_BLOB(NDN_DTAG_Witness, msg,
                                  co->offset[NDN_PCO_B_Witness],
                                  co->offset[NDN_PCO_E_Witness],
                                  &witness,
                                  &witness_size);
        if (res < 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            return (-1);
        }

        digest_info = d2i_X509_SIG(NULL, &witness, witness_size);
        /* digest_info->algor->algorithm->{length, data}
         * digest_info->digest->{length, type, data}
         */
        /* ...2.2 is an MHT w/ SHA256 */
        ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1);
        if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) {
            fprintf(stderr, "A witness is present without an MHT OID!\n");
            EVP_MD_CTX_cleanup(ver_ctx);
            ASN1_OBJECT_free(merkle_hash_tree_oid);
            return (-1);
        }
        /* we're doing an MHT */
        ASN1_OBJECT_free(merkle_hash_tree_oid);
        merkle_path_digest = EVP_sha256();
        /* DER-encoded in the digest_info's digest ASN.1 octet string is the Merkle path info */
        dd = digest_info->digest->data;
        merkle_path_info = d2i_MP_info(NULL, &dd, digest_info->digest->length);
        X509_SIG_free(digest_info);
#ifdef DEBUG
        int x,h;
        int node = ASN1_INTEGER_get(merkle_path_info->node);
        int hash_count = sk_ASN1_OCTET_STRING_num(merkle_path_info->hashes);
        ASN1_OCTET_STRING *hash;
        fprintf(stderr, "A witness is present with an MHT OID\n");
        fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count);
        for (h = 0; h < hash_count; h++) {
            hash = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, h);
            fprintf(stderr, "     hashes[%d] len = %d data = ", h, hash->length);
            for (x = 0; x < hash->length; x++) {
                fprintf(stderr, "%02x", hash->data[x]);
            }
            fprintf(stderr, "\n");
        }
#endif
        /* In the MHT signature case, we signed/verify the root hash */
        root_hash_size = EVP_MD_size(merkle_path_digest);
        root_hash = calloc(1, root_hash_size);
        res = ndn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size);
        MP_info_free(merkle_path_info);
        if (res < 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            free(root_hash);
            return(-1);
        }
        res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size);
        free(root_hash);
        if (res == 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            return(-1);
        }
        res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
        EVP_MD_CTX_cleanup(ver_ctx);
    } else {
        /*
         * In the simple signature case, we signed/verify from the name through
         * the end of the content.
         */
        size_t signed_size = co->offset[NDN_PCO_E_Content] - co->offset[NDN_PCO_B_Name];
        res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[NDN_PCO_B_Name], signed_size);
        if (res == 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            return(-1);
        }
        res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
        EVP_MD_CTX_cleanup(ver_ctx);
    }
    return (res);
}
예제 #5
0
파일: ndnsimplecat.c 프로젝트: cawka/ndnx
/**
 * Handle the incoming content messages. Extracts the data, and
 * requests the next block in sequence if the received block was
 * not the final one.
 */
enum ndn_upcall_res
incoming_content(struct ndn_closure *selfp,
                 enum ndn_upcall_kind kind,
                 struct ndn_upcall_info *info)
{
    struct ndn_charbuf *name = NULL;
    struct ndn_charbuf *templ = NULL;
    const unsigned char *ndnb = NULL;
    size_t ndnb_size = 0;
    const unsigned char *data = NULL;
    size_t data_size = 0;
    size_t written;
    const unsigned char *ib = NULL; /* info->interest_ndnb */
    struct ndn_indexbuf *ic = NULL;
    int res;
    struct mydata *md = selfp->data;
    
    if (kind == NDN_UPCALL_FINAL) {
        if (md != NULL) {
            selfp->data = NULL;
            free(md);
            md = NULL;
        }
        return(NDN_UPCALL_RESULT_OK);
    }
    if (kind == NDN_UPCALL_INTEREST_TIMED_OUT)
        return(NDN_UPCALL_RESULT_REEXPRESS);
    if (kind == NDN_UPCALL_CONTENT_UNVERIFIED)
        return(NDN_UPCALL_RESULT_VERIFY);
    if (kind != NDN_UPCALL_CONTENT)
        return(NDN_UPCALL_RESULT_ERR);
    if (md == NULL)
        selfp->data = md = calloc(1, sizeof(*md));
    ndnb = info->content_ndnb;
    ndnb_size = info->pco->offset[NDN_PCO_E];
    ib = info->interest_ndnb;
    ic = info->interest_comps;
    res = ndn_content_get_value(ndnb, ndnb_size, info->pco, &data, &data_size);
    if (res < 0) abort();
    if (info->pco->type != NDN_CONTENT_DATA) {
        /* For us this is spam. For now, give up. */
        fprintf(stderr, "*** spammed at block %d\n", (int)selfp->intdata);
        exit(1);
    }
    
    /* OK, we will accept this block. */
    if (data_size == 0)
        *(md->done) = 1;
    else {
        written = fwrite(data, data_size, 1, stdout);
        if (written != 1)
            exit(1);
    }
    // XXX The test below should get refactored into the library
    if (info->pco->offset[NDN_PCO_B_FinalBlockID] !=
        info->pco->offset[NDN_PCO_E_FinalBlockID]) {
        const unsigned char *finalid = NULL;
        size_t finalid_size = 0;
        const unsigned char *nameid = NULL;
        size_t nameid_size = 0;
        struct ndn_indexbuf *cc = info->content_comps;
        ndn_ref_tagged_BLOB(NDN_DTAG_FinalBlockID, ndnb,
                            info->pco->offset[NDN_PCO_B_FinalBlockID],
                            info->pco->offset[NDN_PCO_E_FinalBlockID],
                            &finalid,
                            &finalid_size);
        if (cc->n < 2) abort();
        ndn_ref_tagged_BLOB(NDN_DTAG_Component, ndnb,
                            cc->buf[cc->n - 2],
                            cc->buf[cc->n - 1],
                            &nameid,
                            &nameid_size);
        if (finalid_size == nameid_size &&
              0 == memcmp(finalid, nameid, nameid_size))
            *(md->done) = 1;
    }
    
    if (*(md->done)) {
        ndn_set_run_timeout(info->h, 0);
        return(NDN_UPCALL_RESULT_OK);
    }
    
    /* Ask for the next fragment */
    name = ndn_charbuf_create();
    ndn_name_init(name);
    if (ic->n < 2) abort();
    res = ndn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
    if (res < 0) abort();
    ndn_name_append_numeric(name, NDN_MARKER_SEQNUM, ++(selfp->intdata));
    templ = make_template(md, info);
    
    res = ndn_express_interest(info->h, name, selfp, templ);
    if (res < 0) abort();
    
    ndn_charbuf_destroy(&templ);
    ndn_charbuf_destroy(&name);
    
    return(NDN_UPCALL_RESULT_OK);
}