00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <arpa/inet.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <poll.h>
00024 #include <signal.h>
00025 #include <stdint.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/socket.h>
00030 #include <sys/stat.h>
00031 #include <sys/time.h>
00032 #include <sys/types.h>
00033 #include <sys/un.h>
00034 #include <unistd.h>
00035
00036 #include <ccn/ccn.h>
00037 #include <ccn/ccn_private.h>
00038 #include <ccn/ccnd.h>
00039 #include <ccn/charbuf.h>
00040 #include <ccn/coding.h>
00041 #include <ccn/digest.h>
00042 #include <ccn/hashtb.h>
00043 #include <ccn/reg_mgmt.h>
00044 #include <ccn/signing.h>
00045 #include <ccn/keystore.h>
00046 #include <ccn/uri.h>
00047
00048 struct ccn {
00049 int sock;
00050 size_t outbufindex;
00051 struct ccn_charbuf *interestbuf;
00052 struct ccn_charbuf *inbuf;
00053 struct ccn_charbuf *outbuf;
00054 struct ccn_charbuf *ccndid;
00055 struct hashtb *interests_by_prefix;
00056 struct hashtb *interest_filters;
00057 struct ccn_skeleton_decoder decoder;
00058 struct ccn_indexbuf *scratch_indexbuf;
00059 struct hashtb *keys;
00060 struct hashtb *keystores;
00061 struct ccn_charbuf *default_pubid;
00062 struct timeval now;
00063 int timeout;
00064 int refresh_us;
00065 int err;
00066 int errline;
00067 int verbose_error;
00068 int tap;
00069 int running;
00070 int defer_verification;
00071 };
00072
00073 struct expressed_interest;
00074 struct ccn_reg_closure;
00075
00076 struct interests_by_prefix {
00077 struct expressed_interest *list;
00078 };
00079
00080 struct expressed_interest {
00081 int magic;
00082 struct timeval lasttime;
00083 struct ccn_closure *action;
00084 unsigned char *interest_msg;
00085 size_t size;
00086 int target;
00087 int outstanding;
00088 int lifetime_us;
00089 struct ccn_charbuf *wanted_pub;
00090 struct expressed_interest *next;
00091 };
00092
00093 struct interest_filter {
00094 struct ccn_closure *action;
00095 struct ccn_reg_closure *ccn_reg_closure;
00096 struct timeval expiry;
00097 int flags;
00098 };
00099 #define CCN_FORW_WAITING_CCNDID (1<<30)
00100
00101 struct ccn_reg_closure {
00102 struct ccn_closure action;
00103 struct interest_filter *interest_filter;
00104 };
00105
00106 #define NOTE_ERR(h, e) (h->err = (e), h->errline = __LINE__, ccn_note_err(h))
00107 #define NOTE_ERRNO(h) NOTE_ERR(h, errno)
00108
00109 #define THIS_CANNOT_HAPPEN(h) \
00110 do { NOTE_ERR(h, -73); ccn_perror(h, "Can't happen");} while (0)
00111
00112 #define XXX \
00113 do { NOTE_ERR(h, -76); ccn_perror(h, "Please write some more code here"); } while (0)
00114
00115 static void ccn_refresh_interest(struct ccn *, struct expressed_interest *);
00116 static void ccn_initiate_prefix_reg(struct ccn *,
00117 const void *, size_t,
00118 struct interest_filter *);
00119 static void finalize_pkey(struct hashtb_enumerator *e);
00120 static void finalize_keystore(struct hashtb_enumerator *e);
00121 static int ccn_pushout(struct ccn *h);
00122
00123 static int
00124 tv_earlier(const struct timeval *a, const struct timeval *b)
00125 {
00126 if (a->tv_sec > b->tv_sec)
00127 return(0);
00128 if (a->tv_sec < b->tv_sec)
00129 return(1);
00130 return(a->tv_usec < b->tv_usec);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 void
00141 ccn_perror(struct ccn *h, const char *s)
00142 {
00143 const char *dlm = ": ";
00144 if (s == NULL) {
00145 if (h->err > 0)
00146 s = strerror(h->err);
00147 else
00148 dlm = s = "";
00149 }
00150
00151 fprintf(stderr, "ccn_client.c:%d[%d] - error %d%s%s\n",
00152 h->errline, (int)getpid(), h->err, dlm, s);
00153 }
00154
00155 static int
00156 ccn_note_err(struct ccn *h)
00157 {
00158 if (h->verbose_error)
00159 ccn_perror(h, NULL);
00160 return(-1);
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 int
00170 ccn_seterror(struct ccn *h, int error_code)
00171 {
00172 if (h == NULL)
00173 return(-1);
00174 h->err = error_code;
00175 h->errline = 0;
00176 if (error_code != 0)
00177 ccn_note_err(h);
00178 return(-1);
00179 }
00180
00181
00182
00183
00184
00185
00186 int
00187 ccn_geterror(struct ccn *h)
00188 {
00189 if (h == NULL)
00190 return(0);
00191 return(h->err);
00192 }
00193
00194 static struct ccn_indexbuf *
00195 ccn_indexbuf_obtain(struct ccn *h)
00196 {
00197 struct ccn_indexbuf *c = h->scratch_indexbuf;
00198 if (c == NULL)
00199 return(ccn_indexbuf_create());
00200 h->scratch_indexbuf = NULL;
00201 c->n = 0;
00202 return(c);
00203 }
00204
00205 static void
00206 ccn_indexbuf_release(struct ccn *h, struct ccn_indexbuf *c)
00207 {
00208 c->n = 0;
00209 if (h->scratch_indexbuf == NULL)
00210 h->scratch_indexbuf = c;
00211 else
00212 ccn_indexbuf_destroy(&c);
00213 }
00214
00215 static void
00216 ccn_replace_handler(struct ccn *h,
00217 struct ccn_closure **dstp,
00218 struct ccn_closure *src)
00219 {
00220 struct ccn_closure *old = *dstp;
00221 if (src == old)
00222 return;
00223 if (src != NULL)
00224 src->refcount++;
00225 *dstp = src;
00226 if (old != NULL && (--(old->refcount)) == 0) {
00227 struct ccn_upcall_info info = { 0 };
00228 info.h = h;
00229 (old->p)(old, CCN_UPCALL_FINAL, &info);
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 struct ccn *
00240 ccn_create(void)
00241 {
00242 struct ccn *h;
00243 const char *s;
00244 struct hashtb_param param = {0};
00245
00246 h = calloc(1, sizeof(*h));
00247 if (h == NULL)
00248 return(h);
00249 param.finalize_data = h;
00250 h->sock = -1;
00251 h->interestbuf = ccn_charbuf_create();
00252 param.finalize = &finalize_pkey;
00253 h->keys = hashtb_create(sizeof(struct ccn_pkey *), ¶m);
00254 param.finalize = &finalize_keystore;
00255 h->keystores = hashtb_create(sizeof(struct ccn_keystore *), ¶m);
00256 s = getenv("CCN_DEBUG");
00257 h->verbose_error = (s != NULL && s[0] != 0);
00258 s = getenv("CCN_TAP");
00259 if (s != NULL && s[0] != 0) {
00260 char tap_name[255];
00261 struct timeval tv;
00262 gettimeofday(&tv, NULL);
00263 if (snprintf(tap_name, 255, "%s-%d-%d-%d", s, (int)getpid(),
00264 (int)tv.tv_sec, (int)tv.tv_usec) >= 255) {
00265 fprintf(stderr, "CCN_TAP path is too long: %s\n", s);
00266 } else {
00267 h->tap = open(tap_name, O_WRONLY|O_APPEND|O_CREAT, S_IRWXU);
00268 if (h->tap == -1) {
00269 NOTE_ERRNO(h);
00270 ccn_perror(h, "Unable to open CCN_TAP file");
00271 }
00272 else
00273 fprintf(stderr, "CCN_TAP writing to %s\n", tap_name);
00274 }
00275 } else
00276 h->tap = -1;
00277 h->defer_verification = 0;
00278 return(h);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 int
00302 ccn_defer_verification(struct ccn *h, int defer)
00303 {
00304 int old;
00305
00306 if (h == NULL || defer > 1 || defer < -1)
00307 return(-1);
00308 old = h->defer_verification;
00309 if (defer >= 0)
00310 h->defer_verification = defer;
00311 return(old);
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 int
00322 ccn_connect(struct ccn *h, const char *name)
00323 {
00324 struct sockaddr_un addr = {0};
00325 int res;
00326 if (h == NULL)
00327 return(-1);
00328 h->err = 0;
00329 if (h->sock != -1)
00330 return(NOTE_ERR(h, EINVAL));
00331 addr.sun_family = AF_UNIX;
00332 if (name == NULL || name[0] == 0)
00333 ccn_setup_sockaddr_un(NULL, &addr);
00334 else {
00335 addr.sun_family = AF_UNIX;
00336 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
00337 }
00338 h->sock = socket(AF_UNIX, SOCK_STREAM, 0);
00339 if (h->sock == -1)
00340 return(NOTE_ERRNO(h));
00341 res = connect(h->sock, (struct sockaddr *)&addr, sizeof(addr));
00342 if (res == -1)
00343 return(NOTE_ERRNO(h));
00344 res = fcntl(h->sock, F_SETFL, O_NONBLOCK);
00345 if (res == -1)
00346 return(NOTE_ERRNO(h));
00347 return(h->sock);
00348 }
00349
00350 int
00351 ccn_get_connection_fd(struct ccn *h)
00352 {
00353 return(h->sock);
00354 }
00355
00356 int
00357 ccn_disconnect(struct ccn *h)
00358 {
00359 int res;
00360 res = ccn_pushout(h);
00361 if (res == 1) {
00362 res = fcntl(h->sock, F_SETFL, 0);
00363 if (res == 0)
00364 ccn_pushout(h);
00365 }
00366 ccn_charbuf_destroy(&h->inbuf);
00367 ccn_charbuf_destroy(&h->outbuf);
00368 res = close(h->sock);
00369 h->sock = -1;
00370 if (res == -1)
00371 return(NOTE_ERRNO(h));
00372 return(0);
00373 }
00374
00375 static void
00376 ccn_gripe(struct expressed_interest *i)
00377 {
00378 fprintf(stderr, "BOTCH - (struct expressed_interest *)%p has bad magic value\n", (void *)i);
00379 }
00380
00381 static void
00382 replace_interest_msg(struct expressed_interest *interest,
00383 struct ccn_charbuf *cb)
00384 {
00385 if (interest->magic != 0x7059e5f4) {
00386 ccn_gripe(interest);
00387 return;
00388 }
00389 if (interest->interest_msg != NULL)
00390 free(interest->interest_msg);
00391 interest->interest_msg = NULL;
00392 interest->size = 0;
00393 if (cb != NULL && cb->length > 0) {
00394 interest->interest_msg = calloc(1, cb->length);
00395 if (interest->interest_msg != NULL) {
00396 memcpy(interest->interest_msg, cb->buf, cb->length);
00397 interest->size = cb->length;
00398 }
00399 }
00400 }
00401
00402 static struct expressed_interest *
00403 ccn_destroy_interest(struct ccn *h, struct expressed_interest *i)
00404 {
00405 struct expressed_interest *ans = i->next;
00406 if (i->magic != 0x7059e5f4) {
00407 ccn_gripe(i);
00408 return(NULL);
00409 }
00410 ccn_replace_handler(h, &(i->action), NULL);
00411 replace_interest_msg(i, NULL);
00412 ccn_charbuf_destroy(&i->wanted_pub);
00413 i->magic = -1;
00414 free(i);
00415 return(ans);
00416 }
00417
00418 void
00419 ccn_check_interests(struct expressed_interest *list)
00420 {
00421 struct expressed_interest *ie;
00422 for (ie = list; ie != NULL; ie = ie->next) {
00423 if (ie->magic != 0x7059e5f4) {
00424 ccn_gripe(ie);
00425 abort();
00426 }
00427 }
00428 }
00429
00430 void
00431 ccn_clean_interests_by_prefix(struct ccn *h, struct interests_by_prefix *entry)
00432 {
00433 struct expressed_interest *ie;
00434 struct expressed_interest *next;
00435 struct expressed_interest **ip;
00436 ccn_check_interests(entry->list);
00437 ip = &(entry->list);
00438 for (ie = entry->list; ie != NULL; ie = next) {
00439 next = ie->next;
00440 if (ie->action == NULL)
00441 ccn_destroy_interest(h, ie);
00442 else {
00443 (*ip) = ie;
00444 ip = &(ie->next);
00445 }
00446 }
00447 (*ip) = NULL;
00448 ccn_check_interests(entry->list);
00449 }
00450
00451 void
00452 ccn_destroy(struct ccn **hp)
00453 {
00454 struct hashtb_enumerator ee;
00455 struct hashtb_enumerator *e = ⅇ
00456 struct ccn *h = *hp;
00457 if (h == NULL)
00458 return;
00459 ccn_disconnect(h);
00460 if (h->interests_by_prefix != NULL) {
00461 for (hashtb_start(h->interests_by_prefix, e); e->data != NULL; hashtb_next(e)) {
00462 struct interests_by_prefix *entry = e->data;
00463 while (entry->list != NULL)
00464 entry->list = ccn_destroy_interest(h, entry->list);
00465 }
00466 hashtb_end(e);
00467 hashtb_destroy(&(h->interests_by_prefix));
00468 }
00469 if (h->interest_filters != NULL) {
00470 for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
00471 struct interest_filter *i = e->data;
00472 ccn_replace_handler(h, &(i->action), NULL);
00473 }
00474 hashtb_end(e);
00475 hashtb_destroy(&(h->interest_filters));
00476 }
00477 hashtb_destroy(&(h->keys));
00478 hashtb_destroy(&(h->keystores));
00479 ccn_charbuf_destroy(&h->interestbuf);
00480 ccn_indexbuf_destroy(&h->scratch_indexbuf);
00481 ccn_charbuf_destroy(&h->default_pubid);
00482 if (h->tap != -1)
00483 close(h->tap);
00484 free(h);
00485 *hp = NULL;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495 static int
00496 ccn_check_namebuf(struct ccn *h, struct ccn_charbuf *namebuf, int prefix_comps,
00497 int omit_possible_digest)
00498 {
00499 struct ccn_buf_decoder decoder;
00500 struct ccn_buf_decoder *d;
00501 int i = 0;
00502 int ans = 0;
00503 int prev_ans = 0;
00504 if (namebuf == NULL || namebuf->length < 2)
00505 return(-1);
00506 d = ccn_buf_decoder_start(&decoder, namebuf->buf, namebuf->length);
00507 if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00508 ccn_buf_advance(d);
00509 prev_ans = ans = d->decoder.token_index;
00510 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00511 ccn_buf_advance(d);
00512 if (ccn_buf_match_blob(d, NULL, NULL)) {
00513 ccn_buf_advance(d);
00514 }
00515 ccn_buf_check_close(d);
00516 i += 1;
00517 if (prefix_comps < 0 || i <= prefix_comps) {
00518 prev_ans = ans;
00519 ans = d->decoder.token_index;
00520 }
00521 }
00522 ccn_buf_check_close(d);
00523 }
00524 if (d->decoder.state < 0 || ans < prefix_comps)
00525 return(-1);
00526 if (omit_possible_digest && ans == prev_ans + 36 && ans == namebuf->length - 1)
00527 return(prev_ans);
00528 return(ans);
00529 }
00530
00531 static void
00532 ccn_construct_interest(struct ccn *h,
00533 struct ccn_charbuf *name_prefix,
00534 struct ccn_charbuf *interest_template,
00535 struct expressed_interest *dest)
00536 {
00537 struct ccn_charbuf *c = h->interestbuf;
00538 size_t start;
00539 size_t size;
00540 int res;
00541
00542 dest->lifetime_us = CCN_INTEREST_LIFETIME_MICROSEC;
00543 c->length = 0;
00544 ccn_charbuf_append_tt(c, CCN_DTAG_Interest, CCN_DTAG);
00545 ccn_charbuf_append(c, name_prefix->buf, name_prefix->length);
00546 res = 0;
00547 if (interest_template != NULL) {
00548 struct ccn_parsed_interest pi = { 0 };
00549 res = ccn_parse_interest(interest_template->buf,
00550 interest_template->length, &pi, NULL);
00551 if (res >= 0) {
00552 intmax_t lifetime = ccn_interest_lifetime(interest_template->buf, &pi);
00553
00554 if (lifetime < 1 || lifetime > (30 << 12))
00555 NOTE_ERR(h, EINVAL);
00556 else
00557 dest->lifetime_us = (lifetime * 1000000) >> 12;
00558 start = pi.offset[CCN_PI_E_Name];
00559 size = pi.offset[CCN_PI_B_Nonce] - start;
00560 ccn_charbuf_append(c, interest_template->buf + start, size);
00561 start = pi.offset[CCN_PI_B_OTHER];
00562 size = pi.offset[CCN_PI_E_OTHER] - start;
00563 if (size != 0)
00564 ccn_charbuf_append(c, interest_template->buf + start, size);
00565 }
00566 else
00567 NOTE_ERR(h, EINVAL);
00568 }
00569 ccn_charbuf_append_closer(c);
00570 replace_interest_msg(dest, (res >= 0 ? c : NULL));
00571 }
00572
00573 int
00574 ccn_express_interest(struct ccn *h,
00575 struct ccn_charbuf *namebuf,
00576 struct ccn_closure *action,
00577 struct ccn_charbuf *interest_template)
00578 {
00579 struct hashtb_enumerator ee;
00580 struct hashtb_enumerator *e = ⅇ
00581 int res;
00582 int prefixend;
00583 struct expressed_interest *interest = NULL;
00584 struct interests_by_prefix *entry = NULL;
00585 if (h->interests_by_prefix == NULL) {
00586 h->interests_by_prefix = hashtb_create(sizeof(struct interests_by_prefix), NULL);
00587 if (h->interests_by_prefix == NULL)
00588 return(NOTE_ERRNO(h));
00589 }
00590 prefixend = ccn_check_namebuf(h, namebuf, -1, 1);
00591 if (prefixend < 0)
00592 return(prefixend);
00593
00594
00595
00596
00597 hashtb_start(h->interests_by_prefix, e);
00598 res = hashtb_seek(e, namebuf->buf + 1, prefixend - 1, 0);
00599 entry = e->data;
00600 if (entry == NULL) {
00601 NOTE_ERRNO(h);
00602 hashtb_end(e);
00603 return(res);
00604 }
00605 if (res == HT_NEW_ENTRY)
00606 entry->list = NULL;
00607 interest = calloc(1, sizeof(*interest));
00608 if (interest == NULL) {
00609 NOTE_ERRNO(h);
00610 hashtb_end(e);
00611 return(-1);
00612 }
00613 interest->magic = 0x7059e5f4;
00614 ccn_construct_interest(h, namebuf, interest_template, interest);
00615 if (interest->interest_msg == NULL) {
00616 free(interest);
00617 hashtb_end(e);
00618 return(-1);
00619 }
00620 ccn_replace_handler(h, &(interest->action), action);
00621 interest->target = 1;
00622 interest->next = entry->list;
00623 entry->list = interest;
00624 hashtb_end(e);
00625
00626 ccn_refresh_interest(h, interest);
00627 return(0);
00628 }
00629
00630 static void
00631 finalize_interest_filter(struct hashtb_enumerator *e)
00632 {
00633 struct interest_filter *i = e->data;
00634 if (i->ccn_reg_closure != NULL) {
00635 i->ccn_reg_closure->interest_filter = NULL;
00636 i->ccn_reg_closure = NULL;
00637 }
00638 }
00639
00640 int
00641 ccn_set_interest_filter_with_flags(struct ccn *h, struct ccn_charbuf *namebuf,
00642 struct ccn_closure *action, int forw_flags)
00643 {
00644 struct hashtb_enumerator ee;
00645 struct hashtb_enumerator *e = ⅇ
00646 int res;
00647 struct interest_filter *entry;
00648 if (h->interest_filters == NULL) {
00649 struct hashtb_param param = {0};
00650 param.finalize = &finalize_interest_filter;
00651 h->interest_filters = hashtb_create(sizeof(struct interest_filter), ¶m);
00652 if (h->interest_filters == NULL)
00653 return(NOTE_ERRNO(h));
00654 }
00655 res = ccn_check_namebuf(h, namebuf, -1, 0);
00656 if (res < 0)
00657 return(res);
00658 hashtb_start(h->interest_filters, e);
00659 res = hashtb_seek(e, namebuf->buf + 1, namebuf->length - 2, 0);
00660 if (res >= 0) {
00661 entry = e->data;
00662 entry->flags = forw_flags;
00663 ccn_replace_handler(h, &(entry->action), action);
00664 if (action == NULL)
00665 hashtb_delete(e);
00666 }
00667 hashtb_end(e);
00668 return(res);
00669 }
00670
00671 int
00672 ccn_set_interest_filter(struct ccn *h, struct ccn_charbuf *namebuf,
00673 struct ccn_closure *action)
00674 {
00675 int forw_flags = CCN_FORW_ACTIVE | CCN_FORW_CHILD_INHERIT;
00676 return(ccn_set_interest_filter_with_flags(h, namebuf, action, forw_flags));
00677 }
00678
00679 static int
00680 ccn_pushout(struct ccn *h)
00681 {
00682 ssize_t res;
00683 size_t size;
00684 if (h->outbuf != NULL && h->outbufindex < h->outbuf->length) {
00685 if (h->sock < 0)
00686 return(1);
00687 size = h->outbuf->length - h->outbufindex;
00688 res = write(h->sock, h->outbuf->buf + h->outbufindex, size);
00689 if (res == size) {
00690 h->outbuf->length = h->outbufindex = 0;
00691 return(0);
00692 }
00693 if (res == -1)
00694 return ((errno == EAGAIN) ? 1 : NOTE_ERRNO(h));
00695 h->outbufindex += res;
00696 return(1);
00697 }
00698 return(0);
00699 }
00700
00701 int
00702 ccn_put(struct ccn *h, const void *p, size_t length)
00703 {
00704 struct ccn_skeleton_decoder dd = {0};
00705 ssize_t res;
00706 if (h == NULL)
00707 return(-1);
00708 if (p == NULL || length == 0)
00709 return(NOTE_ERR(h, EINVAL));
00710 res = ccn_skeleton_decode(&dd, p, length);
00711 if (!(res == length && dd.state == 0))
00712 return(NOTE_ERR(h, EINVAL));
00713 if (h->tap != -1) {
00714 res = write(h->tap, p, length);
00715 if (res == -1) {
00716 NOTE_ERRNO(h);
00717 (void)close(h->tap);
00718 h->tap = -1;
00719 }
00720 }
00721 if (h->outbuf != NULL && h->outbufindex < h->outbuf->length) {
00722
00723 ccn_charbuf_append(h->outbuf, p, length);
00724 return (ccn_pushout(h));
00725 }
00726 if (h->sock == -1)
00727 res = 0;
00728 else
00729 res = write(h->sock, p, length);
00730 if (res == length)
00731 return(0);
00732 if (res == -1) {
00733 if (errno != EAGAIN)
00734 return(NOTE_ERRNO(h));
00735 res = 0;
00736 }
00737 if (h->outbuf == NULL) {
00738 h->outbuf = ccn_charbuf_create();
00739 h->outbufindex = 0;
00740 }
00741 ccn_charbuf_append(h->outbuf, ((const unsigned char *)p)+res, length-res);
00742 return(1);
00743 }
00744
00745 int
00746 ccn_output_is_pending(struct ccn *h)
00747 {
00748 return(h != NULL && h->outbuf != NULL && h->outbufindex < h->outbuf->length);
00749 }
00750
00751 struct ccn_charbuf *
00752 ccn_grab_buffered_output(struct ccn *h)
00753 {
00754 if (ccn_output_is_pending(h) && h->outbufindex == 0) {
00755 struct ccn_charbuf *ans = h->outbuf;
00756 h->outbuf = NULL;
00757 return(ans);
00758 }
00759 return(NULL);
00760 }
00761
00762 static void
00763 ccn_refresh_interest(struct ccn *h, struct expressed_interest *interest)
00764 {
00765 int res;
00766 if (interest->magic != 0x7059e5f4) {
00767 ccn_gripe(interest);
00768 return;
00769 }
00770 if (interest->outstanding < interest->target) {
00771 res = ccn_put(h, interest->interest_msg, interest->size);
00772 if (res >= 0) {
00773 interest->outstanding += 1;
00774 if (h->now.tv_sec == 0)
00775 gettimeofday(&h->now, NULL);
00776 interest->lasttime = h->now;
00777 }
00778 }
00779 }
00780
00781 static int
00782 ccn_get_content_type(const unsigned char *ccnb,
00783 const struct ccn_parsed_ContentObject *pco)
00784 {
00785 enum ccn_content_type type = pco->type;
00786 (void)ccnb;
00787 switch (type) {
00788 case CCN_CONTENT_DATA:
00789 case CCN_CONTENT_ENCR:
00790 case CCN_CONTENT_GONE:
00791 case CCN_CONTENT_KEY:
00792 case CCN_CONTENT_LINK:
00793 case CCN_CONTENT_NACK:
00794 return (type);
00795 default:
00796 return (-1);
00797 }
00798 }
00799
00800
00801
00802
00803 static void
00804 ccn_digest_Content(const unsigned char *content_object,
00805 struct ccn_parsed_ContentObject *pc,
00806 unsigned char *digest,
00807 size_t digest_bytes)
00808 {
00809 int res;
00810 struct ccn_digest *d = NULL;
00811 const unsigned char *content = NULL;
00812 size_t content_bytes = 0;
00813
00814 if (pc->magic < 20080000) abort();
00815 if (digest_bytes == sizeof(digest))
00816 return;
00817 d = ccn_digest_create(CCN_DIGEST_SHA256);
00818 ccn_digest_init(d);
00819 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_object,
00820 pc->offset[CCN_PCO_B_Content],
00821 pc->offset[CCN_PCO_E_Content],
00822 &content, &content_bytes);
00823 if (res < 0) abort();
00824 res = ccn_digest_update(d, content, content_bytes);
00825 if (res < 0) abort();
00826 res = ccn_digest_final(d, digest, digest_bytes);
00827 if (res < 0) abort();
00828 ccn_digest_destroy(&d);
00829 }
00830
00831 static int
00832 ccn_cache_key(struct ccn *h,
00833 const unsigned char *ccnb, size_t size,
00834 struct ccn_parsed_ContentObject *pco)
00835 {
00836 int type;
00837 struct ccn_pkey **entry;
00838 struct hashtb_enumerator ee;
00839 struct hashtb_enumerator *e = ⅇ
00840 int res;
00841 unsigned char digest[32];
00842
00843 type = ccn_get_content_type(ccnb, pco);
00844 if (type != CCN_CONTENT_KEY) {
00845 return (0);
00846 }
00847
00848 ccn_digest_Content(ccnb, pco, digest, sizeof(digest));
00849
00850 hashtb_start(h->keys, e);
00851 res = hashtb_seek(e, (void *)digest, sizeof(digest), 0);
00852 if (res < 0) {
00853 hashtb_end(e);
00854 return(NOTE_ERRNO(h));
00855 }
00856 entry = e->data;
00857 if (res == HT_NEW_ENTRY) {
00858 struct ccn_pkey *pkey;
00859 const unsigned char *data = NULL;
00860 size_t data_size = 0;
00861
00862 res = ccn_content_get_value(ccnb, size, pco, &data, &data_size);
00863 if (res < 0) {
00864 hashtb_delete(e);
00865 hashtb_end(e);
00866 return(NOTE_ERRNO(h));
00867 }
00868 pkey = ccn_d2i_pubkey(data, data_size);
00869 if (pkey == NULL) {
00870 hashtb_delete(e);
00871 hashtb_end(e);
00872 return(NOTE_ERRNO(h));
00873 }
00874 *entry = pkey;
00875 }
00876 hashtb_end(e);
00877 return (0);
00878 }
00879
00880 static void
00881 finalize_pkey(struct hashtb_enumerator *e)
00882 {
00883 struct ccn_pkey **entry = e->data;
00884 if (*entry != NULL)
00885 ccn_pubkey_free(*entry);
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 static int
00899 ccn_locate_key(struct ccn *h,
00900 const unsigned char *msg,
00901 struct ccn_parsed_ContentObject *pco,
00902 struct ccn_pkey **pubkey)
00903 {
00904 int res;
00905 const unsigned char *pkeyid;
00906 size_t pkeyid_size;
00907 struct ccn_pkey **entry;
00908 struct ccn_buf_decoder decoder;
00909 struct ccn_buf_decoder *d;
00910
00911 if (h->keys == NULL) {
00912 return (NOTE_ERR(h, EINVAL));
00913 }
00914
00915 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, msg,
00916 pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
00917 pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
00918 &pkeyid, &pkeyid_size);
00919 if (res < 0)
00920 return (NOTE_ERR(h, res));
00921 entry = hashtb_lookup(h->keys, pkeyid, pkeyid_size);
00922 if (entry != NULL) {
00923 *pubkey = *entry;
00924 return (0);
00925 }
00926
00927 if (pco->offset[CCN_PCO_B_KeyLocator] == pco->offset[CCN_PCO_E_KeyLocator])
00928 return (-1);
00929
00930 d = ccn_buf_decoder_start(&decoder, msg + pco->offset[CCN_PCO_B_Key_Certificate_KeyName],
00931 pco->offset[CCN_PCO_E_Key_Certificate_KeyName] -
00932 pco->offset[CCN_PCO_B_Key_Certificate_KeyName]);
00933 if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) {
00934 return(1);
00935 }
00936 else if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
00937 const unsigned char *dkey;
00938 size_t dkey_size;
00939 struct ccn_digest *digest = NULL;
00940 unsigned char *key_digest = NULL;
00941 size_t key_digest_size;
00942 struct hashtb_enumerator ee;
00943 struct hashtb_enumerator *e = ⅇ
00944
00945 res = ccn_ref_tagged_BLOB(CCN_DTAG_Key, msg,
00946 pco->offset[CCN_PCO_B_Key_Certificate_KeyName],
00947 pco->offset[CCN_PCO_E_Key_Certificate_KeyName],
00948 &dkey, &dkey_size);
00949 *pubkey = ccn_d2i_pubkey(dkey, dkey_size);
00950 digest = ccn_digest_create(CCN_DIGEST_SHA256);
00951 ccn_digest_init(digest);
00952 key_digest_size = ccn_digest_size(digest);
00953 key_digest = calloc(1, key_digest_size);
00954 if (key_digest == NULL) abort();
00955 res = ccn_digest_update(digest, dkey, dkey_size);
00956 if (res < 0) abort();
00957 res = ccn_digest_final(digest, key_digest, key_digest_size);
00958 if (res < 0) abort();
00959 ccn_digest_destroy(&digest);
00960 hashtb_start(h->keys, e);
00961 res = hashtb_seek(e, (void *)key_digest, key_digest_size, 0);
00962 free(key_digest);
00963 key_digest = NULL;
00964 if (res < 0) {
00965 hashtb_end(e);
00966 return(NOTE_ERRNO(h));
00967 }
00968 entry = e->data;
00969 if (res == HT_NEW_ENTRY) {
00970 *entry = *pubkey;
00971 }
00972 else
00973 THIS_CANNOT_HAPPEN(h);
00974 hashtb_end(e);
00975 return (0);
00976 }
00977 else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
00978 XXX;
00979 }
00980
00981 return (-1);
00982 }
00983
00984
00985
00986
00987
00988
00989 static int
00990 ccn_append_link_name(struct ccn_charbuf *name, const unsigned char *data, size_t data_size)
00991 {
00992 struct ccn_buf_decoder decoder;
00993 struct ccn_buf_decoder *d;
00994 size_t start = 0;
00995 size_t end = 0;
00996
00997 d = ccn_buf_decoder_start(&decoder, data, data_size);
00998 if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
00999 ccn_buf_advance(d);
01000 start = d->decoder.token_index;
01001 ccn_parse_Name(d, NULL);
01002 end = d->decoder.token_index;
01003 ccn_buf_check_close(d);
01004 if (d->decoder.state < 0)
01005 return (d->decoder.state);
01006 ccn_charbuf_append(name, data + start, end - start);
01007 return(0);
01008 }
01009 return(-1);
01010 }
01011
01012
01013
01014
01015
01016
01017
01018 static enum ccn_upcall_res
01019 handle_key(struct ccn_closure *selfp,
01020 enum ccn_upcall_kind kind,
01021 struct ccn_upcall_info *info)
01022 {
01023 struct ccn *h = info->h;
01024 (void)h;
01025 int type = 0;
01026 const unsigned char *msg = NULL;
01027 const unsigned char *data = NULL;
01028 size_t size;
01029 size_t data_size;
01030 int res;
01031 struct ccn_charbuf *name = NULL;
01032 struct ccn_charbuf *templ = NULL;
01033
01034 switch(kind) {
01035 case CCN_UPCALL_FINAL:
01036 free(selfp);
01037 return(CCN_UPCALL_RESULT_OK);
01038 case CCN_UPCALL_INTEREST_TIMED_OUT:
01039
01040 return(CCN_UPCALL_RESULT_OK);
01041 case CCN_UPCALL_CONTENT_UNVERIFIED:
01042
01043 case CCN_UPCALL_CONTENT_KEYMISSING:
01044 case CCN_UPCALL_CONTENT_RAW:
01045 case CCN_UPCALL_CONTENT:
01046 type = ccn_get_content_type(msg, info->pco);
01047 if (type == CCN_CONTENT_KEY)
01048 return(CCN_UPCALL_RESULT_OK);
01049 if (type == CCN_CONTENT_LINK) {
01050
01051
01052 if (selfp->intdata <= 0)
01053 return(NOTE_ERR(h, ELOOP));
01054 selfp->intdata -= 1;
01055 msg = info->content_ccnb;
01056 size = info->pco->offset[CCN_PCO_E];
01057 res = ccn_content_get_value(info->content_ccnb, size, info->pco,
01058 &data, &data_size);
01059 if (res < 0)
01060 return (CCN_UPCALL_RESULT_ERR);
01061 templ = ccn_charbuf_create();
01062 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01063 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
01064 ccn_charbuf_append_closer(templ);
01065 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01066 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01067 ccn_charbuf_append_closer(templ);
01068 name = ccn_charbuf_create();
01069 res = ccn_append_link_name(name, data, data_size);
01070 if (res < 0) {
01071 NOTE_ERR(h, EINVAL);
01072 res = CCN_UPCALL_RESULT_ERR;
01073 }
01074 else
01075 res = ccn_express_interest(h, name, selfp, templ);
01076 ccn_charbuf_destroy(&name);
01077 ccn_charbuf_destroy(&templ);
01078 return(res);
01079 }
01080 return (CCN_UPCALL_RESULT_ERR);
01081 default:
01082 return (CCN_UPCALL_RESULT_ERR);
01083 }
01084 }
01085
01086
01087
01088
01089
01090 #ifndef CCN_MAX_KEY_LINK_CHAIN
01091 #define CCN_MAX_KEY_LINK_CHAIN 7
01092 #endif
01093
01094 static int
01095 ccn_initiate_key_fetch(struct ccn *h,
01096 unsigned char *msg,
01097 struct ccn_parsed_ContentObject *pco,
01098 struct expressed_interest *trigger_interest)
01099 {
01100
01101
01102
01103
01104
01105 int res;
01106 int namelen;
01107 struct ccn_charbuf *key_name = NULL;
01108 struct ccn_closure *key_closure = NULL;
01109 const unsigned char *pkeyid = NULL;
01110 size_t pkeyid_size = 0;
01111 struct ccn_charbuf *templ = NULL;
01112
01113 if (trigger_interest != NULL) {
01114
01115 if (trigger_interest->wanted_pub == NULL)
01116 trigger_interest->wanted_pub = ccn_charbuf_create();
01117 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, msg,
01118 pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
01119 pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
01120 &pkeyid, &pkeyid_size);
01121 if (trigger_interest->wanted_pub != NULL && res >= 0) {
01122 trigger_interest->wanted_pub->length = 0;
01123 ccn_charbuf_append(trigger_interest->wanted_pub, pkeyid, pkeyid_size);
01124 }
01125 trigger_interest->target = 0;
01126 }
01127
01128 namelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01129 pco->offset[CCN_PCO_B_KeyName_Name]);
01130
01131
01132
01133
01134 if (namelen == 0)
01135 return(-1);
01136 key_closure = calloc(1, sizeof(*key_closure));
01137 if (key_closure == NULL)
01138 return (NOTE_ERRNO(h));
01139 key_closure->p = &handle_key;
01140 key_closure->intdata = CCN_MAX_KEY_LINK_CHAIN;
01141
01142 key_name = ccn_charbuf_create();
01143 res = ccn_charbuf_append(key_name,
01144 msg + pco->offset[CCN_PCO_B_KeyName_Name],
01145 namelen);
01146 templ = ccn_charbuf_create();
01147 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01148 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
01149 ccn_charbuf_append_closer(templ);
01150 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01151 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01152 if (pco->offset[CCN_PCO_B_KeyName_Pub] < pco->offset[CCN_PCO_E_KeyName_Pub]) {
01153 ccn_charbuf_append(templ,
01154 msg + pco->offset[CCN_PCO_B_KeyName_Pub],
01155 (pco->offset[CCN_PCO_E_KeyName_Pub] -
01156 pco->offset[CCN_PCO_B_KeyName_Pub]));
01157 }
01158 ccn_charbuf_append_closer(templ);
01159 res = ccn_express_interest(h, key_name, key_closure, templ);
01160 ccn_charbuf_destroy(&key_name);
01161 ccn_charbuf_destroy(&templ);
01162 return(res);
01163 }
01164
01165
01166
01167
01168
01169 static void
01170 ccn_check_pub_arrival(struct ccn *h, struct expressed_interest *interest)
01171 {
01172 struct ccn_charbuf *want = interest->wanted_pub;
01173 if (want == NULL)
01174 return;
01175 if (hashtb_lookup(h->keys, want->buf, want->length) != NULL) {
01176 ccn_charbuf_destroy(&interest->wanted_pub);
01177 interest->target = 1;
01178 ccn_refresh_interest(h, interest);
01179 }
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 void
01191 ccn_dispatch_message(struct ccn *h, unsigned char *msg, size_t size)
01192 {
01193 struct ccn_parsed_interest pi = {0};
01194 struct ccn_upcall_info info = {0};
01195 int i;
01196 int res;
01197 enum ccn_upcall_res ures;
01198
01199 h->running++;
01200 info.h = h;
01201 info.pi = π
01202 info.interest_comps = ccn_indexbuf_obtain(h);
01203 res = ccn_parse_interest(msg, size, &pi, info.interest_comps);
01204 if (res >= 0) {
01205
01206 enum ccn_upcall_kind upcall_kind = CCN_UPCALL_INTEREST;
01207 info.interest_ccnb = msg;
01208 if (h->interest_filters != NULL && info.interest_comps->n > 0) {
01209 struct ccn_indexbuf *comps = info.interest_comps;
01210 size_t keystart = comps->buf[0];
01211 unsigned char *key = msg + keystart;
01212 struct interest_filter *entry;
01213 for (i = comps->n - 1; i >= 0; i--) {
01214 entry = hashtb_lookup(h->interest_filters, key, comps->buf[i] - keystart);
01215 if (entry != NULL) {
01216 info.matched_comps = i;
01217 ures = (entry->action->p)(entry->action, upcall_kind, &info);
01218 if (ures == CCN_UPCALL_RESULT_INTEREST_CONSUMED)
01219 upcall_kind = CCN_UPCALL_CONSUMED_INTEREST;
01220 }
01221 }
01222 }
01223 }
01224 else {
01225
01226 struct ccn_parsed_ContentObject obj = {0};
01227 info.pco = &obj;
01228 info.content_comps = ccn_indexbuf_create();
01229 res = ccn_parse_ContentObject(msg, size, &obj, info.content_comps);
01230 if (res >= 0) {
01231 info.content_ccnb = msg;
01232 if (h->interests_by_prefix != NULL) {
01233 struct ccn_indexbuf *comps = info.content_comps;
01234 size_t keystart = comps->buf[0];
01235 unsigned char *key = msg + keystart;
01236 struct expressed_interest *interest = NULL;
01237 struct interests_by_prefix *entry = NULL;
01238 for (i = comps->n - 1; i >= 0; i--) {
01239 entry = hashtb_lookup(h->interests_by_prefix, key, comps->buf[i] - keystart);
01240 if (entry != NULL) {
01241 for (interest = entry->list; interest != NULL; interest = interest->next) {
01242 if (interest->magic != 0x7059e5f4) {
01243 ccn_gripe(interest);
01244 }
01245 if (interest->target > 0 && interest->outstanding > 0) {
01246 res = ccn_parse_interest(interest->interest_msg,
01247 interest->size,
01248 info.pi,
01249 info.interest_comps);
01250 if (res >= 0 &&
01251 ccn_content_matches_interest(msg, size,
01252 1, info.pco,
01253 interest->interest_msg,
01254 interest->size,
01255 info.pi)) {
01256 enum ccn_upcall_kind upcall_kind = CCN_UPCALL_CONTENT;
01257 struct ccn_pkey *pubkey = NULL;
01258 int type = ccn_get_content_type(msg, info.pco);
01259 if (type == CCN_CONTENT_KEY)
01260 res = ccn_cache_key(h, msg, size, info.pco);
01261 res = ccn_locate_key(h, msg, info.pco, &pubkey);
01262 if (h->defer_verification) {
01263 if (res == 0)
01264 upcall_kind = CCN_UPCALL_CONTENT_RAW;
01265 else
01266 upcall_kind = CCN_UPCALL_CONTENT_KEYMISSING;
01267 }
01268 else if (res == 0) {
01269
01270 res = ccn_verify_signature(msg, size, info.pco, pubkey);
01271 upcall_kind = (res == 1) ? CCN_UPCALL_CONTENT : CCN_UPCALL_CONTENT_BAD;
01272 } else
01273 upcall_kind = CCN_UPCALL_CONTENT_UNVERIFIED;
01274 interest->outstanding -= 1;
01275 info.interest_ccnb = interest->interest_msg;
01276 info.matched_comps = i;
01277 ures = (interest->action->p)(interest->action,
01278 upcall_kind,
01279 &info);
01280 if (interest->magic != 0x7059e5f4)
01281 ccn_gripe(interest);
01282 if (ures == CCN_UPCALL_RESULT_REEXPRESS)
01283 ccn_refresh_interest(h, interest);
01284 else if ((ures == CCN_UPCALL_RESULT_VERIFY ||
01285 ures == CCN_UPCALL_RESULT_FETCHKEY) &&
01286 (upcall_kind == CCN_UPCALL_CONTENT_UNVERIFIED ||
01287 upcall_kind == CCN_UPCALL_CONTENT_KEYMISSING)) {
01288 ccn_initiate_key_fetch(h, msg, info.pco, interest);
01289 }
01290 else if (ures == CCN_UPCALL_RESULT_VERIFY &&
01291 upcall_kind == CCN_UPCALL_CONTENT_RAW) {
01292
01293 abort();
01294 }
01295 else {
01296 interest->target = 0;
01297 replace_interest_msg(interest, NULL);
01298 ccn_replace_handler(h, &(interest->action), NULL);
01299 }
01300 }
01301 }
01302 }
01303 }
01304 }
01305 }
01306 }
01307 }
01308 ccn_indexbuf_release(h, info.interest_comps);
01309 ccn_indexbuf_destroy(&info.content_comps);
01310 h->running--;
01311 }
01312
01313 static int
01314 ccn_process_input(struct ccn *h)
01315 {
01316 ssize_t res;
01317 ssize_t msgstart;
01318 unsigned char *buf;
01319 struct ccn_skeleton_decoder *d = &h->decoder;
01320 struct ccn_charbuf *inbuf = h->inbuf;
01321 if (inbuf == NULL)
01322 h->inbuf = inbuf = ccn_charbuf_create();
01323 if (inbuf->length == 0)
01324 memset(d, 0, sizeof(*d));
01325 buf = ccn_charbuf_reserve(inbuf, 8800);
01326 res = read(h->sock, buf, inbuf->limit - inbuf->length);
01327 if (res == 0) {
01328 ccn_disconnect(h);
01329 return(-1);
01330 }
01331 if (res == -1) {
01332 if (errno == EAGAIN)
01333 res = 0;
01334 else
01335 return(NOTE_ERRNO(h));
01336 }
01337 inbuf->length += res;
01338 msgstart = 0;
01339 ccn_skeleton_decode(d, buf, res);
01340 while (d->state == 0) {
01341 ccn_dispatch_message(h, inbuf->buf + msgstart,
01342 d->index - msgstart);
01343 msgstart = d->index;
01344 if (msgstart == inbuf->length) {
01345 inbuf->length = 0;
01346 return(0);
01347 }
01348 ccn_skeleton_decode(d, inbuf->buf + d->index,
01349 inbuf->length - d->index);
01350 }
01351 if (msgstart < inbuf->length && msgstart > 0) {
01352
01353 memmove(inbuf->buf, inbuf->buf + msgstart,
01354 inbuf->length - msgstart);
01355 inbuf->length -= msgstart;
01356 d->index -= msgstart;
01357 }
01358 return(0);
01359 }
01360
01361 static void
01362 ccn_update_refresh_us(struct ccn *h, struct timeval *tv)
01363 {
01364 int delta;
01365 if (tv->tv_sec < h->now.tv_sec)
01366 return;
01367 if (tv->tv_sec > h->now.tv_sec + CCN_INTEREST_LIFETIME_SEC)
01368 return;
01369 delta = (tv->tv_sec - h->now.tv_sec)*1000000 +
01370 (tv->tv_usec - h->now.tv_usec);
01371 if (delta < 0)
01372 delta = 0;
01373 if (delta < h->refresh_us)
01374 h->refresh_us = delta;
01375 }
01376
01377 static void
01378 ccn_age_interest(struct ccn *h,
01379 struct expressed_interest *interest,
01380 const unsigned char *key, size_t keysize)
01381 {
01382 struct ccn_parsed_interest pi = {0};
01383 struct ccn_upcall_info info = {0};
01384 int delta;
01385 int res;
01386 enum ccn_upcall_res ures;
01387 int firstcall;
01388 if (interest->magic != 0x7059e5f4)
01389 ccn_gripe(interest);
01390 info.h = h;
01391 info.pi = π
01392 firstcall = (interest->lasttime.tv_sec == 0);
01393 if (interest->lasttime.tv_sec + 30 < h->now.tv_sec) {
01394
01395 interest->outstanding = 0;
01396 interest->lasttime = h->now;
01397 interest->lasttime.tv_sec -= 30;
01398 }
01399 delta = (h->now.tv_sec - interest->lasttime.tv_sec)*1000000 +
01400 (h->now.tv_usec - interest->lasttime.tv_usec);
01401 if (delta >= interest->lifetime_us) {
01402 interest->outstanding = 0;
01403 delta = 0;
01404 }
01405 else if (delta < 0)
01406 delta = 0;
01407 if (interest->lifetime_us - delta < h->refresh_us)
01408 h->refresh_us = interest->lifetime_us - delta;
01409 interest->lasttime = h->now;
01410 while (delta > interest->lasttime.tv_usec) {
01411 delta -= 1000000;
01412 interest->lasttime.tv_sec -= 1;
01413 }
01414 interest->lasttime.tv_usec -= delta;
01415 if (interest->target > 0 && interest->outstanding == 0) {
01416 ures = CCN_UPCALL_RESULT_REEXPRESS;
01417 if (!firstcall) {
01418 info.interest_ccnb = interest->interest_msg;
01419 info.interest_comps = ccn_indexbuf_obtain(h);
01420 res = ccn_parse_interest(interest->interest_msg,
01421 interest->size,
01422 info.pi,
01423 info.interest_comps);
01424 if (res >= 0) {
01425 ures = (interest->action->p)(interest->action,
01426 CCN_UPCALL_INTEREST_TIMED_OUT,
01427 &info);
01428 if (interest->magic != 0x7059e5f4)
01429 ccn_gripe(interest);
01430 }
01431 else {
01432 int i;
01433 fprintf(stderr, "URP!! interest has been corrupted ccn_client.c:%d\n", __LINE__);
01434 for (i = 0; i < 120; i++)
01435 sleep(1);
01436 ures = CCN_UPCALL_RESULT_ERR;
01437 }
01438 ccn_indexbuf_release(h, info.interest_comps);
01439 }
01440 if (ures == CCN_UPCALL_RESULT_REEXPRESS)
01441 ccn_refresh_interest(h, interest);
01442 else
01443 interest->target = 0;
01444 }
01445 }
01446
01447 static void
01448 ccn_clean_all_interests(struct ccn *h)
01449 {
01450 struct hashtb_enumerator ee;
01451 struct hashtb_enumerator *e = ⅇ
01452 struct interests_by_prefix *entry;
01453 for (hashtb_start(h->interests_by_prefix, e); e->data != NULL;) {
01454 entry = e->data;
01455 ccn_clean_interests_by_prefix(h, entry);
01456 if (entry->list == NULL)
01457 hashtb_delete(e);
01458 else
01459 hashtb_next(e);
01460 }
01461 hashtb_end(e);
01462 }
01463
01464 static void
01465 ccn_notify_ccndid_changed(struct ccn *h)
01466 {
01467 struct hashtb_enumerator ee;
01468 struct hashtb_enumerator *e = ⅇ
01469 if (h->interest_filters != NULL) {
01470 for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
01471 struct interest_filter *i = e->data;
01472 if ((i->flags & CCN_FORW_WAITING_CCNDID) != 0) {
01473 i->expiry = h->now;
01474 i->flags &= ~CCN_FORW_WAITING_CCNDID;
01475 }
01476 }
01477 hashtb_end(e);
01478 }
01479 }
01480
01481
01482
01483
01484
01485
01486
01487
01488 int
01489 ccn_process_scheduled_operations(struct ccn *h)
01490 {
01491 struct hashtb_enumerator ee;
01492 struct hashtb_enumerator *e = ⅇ
01493 struct interests_by_prefix *entry;
01494 struct expressed_interest *ie;
01495 int need_clean = 0;
01496 h->refresh_us = 5 * CCN_INTEREST_LIFETIME_MICROSEC;
01497 gettimeofday(&h->now, NULL);
01498 if (ccn_output_is_pending(h))
01499 return(h->refresh_us);
01500 h->running++;
01501 if (h->interest_filters != NULL) {
01502 for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
01503 struct interest_filter *i = e->data;
01504 if (tv_earlier(&i->expiry, &h->now)) {
01505
01506 ccn_initiate_prefix_reg(h, e->key, e->keysize, i);
01507 }
01508 else
01509 ccn_update_refresh_us(h, &i->expiry);
01510 }
01511 hashtb_end(e);
01512 }
01513 if (h->interests_by_prefix != NULL) {
01514 for (hashtb_start(h->interests_by_prefix, e); e->data != NULL; hashtb_next(e)) {
01515 entry = e->data;
01516 ccn_check_interests(entry->list);
01517 if (entry->list == NULL)
01518 need_clean = 1;
01519 else {
01520 for (ie = entry->list; ie != NULL; ie = ie->next) {
01521 ccn_check_pub_arrival(h, ie);
01522 if (ie->target != 0)
01523 ccn_age_interest(h, ie, e->key, e->keysize);
01524 if (ie->target == 0 && ie->wanted_pub == NULL) {
01525 ccn_replace_handler(h, &(ie->action), NULL);
01526 replace_interest_msg(ie, NULL);
01527 need_clean = 1;
01528 }
01529 }
01530 }
01531 }
01532 hashtb_end(e);
01533 if (need_clean)
01534 ccn_clean_all_interests(h);
01535 }
01536 h->running--;
01537 return(h->refresh_us);
01538 }
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 int
01550 ccn_set_run_timeout(struct ccn *h, int timeout)
01551 {
01552 int ans = h->timeout;
01553 h->timeout = timeout;
01554 return(ans);
01555 }
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 int
01566 ccn_run(struct ccn *h, int timeout)
01567 {
01568 struct timeval start;
01569 struct pollfd fds[1];
01570 int microsec;
01571 int millisec;
01572 int res = -1;
01573 if (h->running != 0)
01574 return(NOTE_ERR(h, EBUSY));
01575 memset(fds, 0, sizeof(fds));
01576 memset(&start, 0, sizeof(start));
01577 h->timeout = timeout;
01578 for (;;) {
01579 if (h->sock == -1) {
01580 res = -1;
01581 break;
01582 }
01583 microsec = ccn_process_scheduled_operations(h);
01584 timeout = h->timeout;
01585 if (start.tv_sec == 0)
01586 start = h->now;
01587 else if (timeout >= 0) {
01588 millisec = (h->now.tv_sec - start.tv_sec) *1000 +
01589 (h->now.tv_usec - start.tv_usec)/1000;
01590 if (millisec >= timeout) {
01591 res = 0;
01592 break;
01593 }
01594 }
01595 fds[0].fd = h->sock;
01596 fds[0].events = POLLIN;
01597 if (ccn_output_is_pending(h))
01598 fds[0].events |= POLLOUT;
01599 millisec = microsec / 1000;
01600 if (timeout >= 0 && timeout < millisec)
01601 millisec = timeout;
01602 res = poll(fds, 1, millisec);
01603 if (res < 0 && errno != EINTR) {
01604 res = NOTE_ERRNO(h);
01605 break;
01606 }
01607 if (res > 0) {
01608 if ((fds[0].revents | POLLOUT) != 0)
01609 ccn_pushout(h);
01610 if ((fds[0].revents | POLLIN) != 0)
01611 ccn_process_input(h);
01612 }
01613 if (h->err == ENOTCONN)
01614 ccn_disconnect(h);
01615 if (h->timeout == 0)
01616 break;
01617 }
01618 if (h->running != 0)
01619 abort();
01620 return((res < 0) ? res : 0);
01621 }
01622
01623
01624 struct simple_get_data {
01625 struct ccn_closure closure;
01626 struct ccn_charbuf *resultbuf;
01627 struct ccn_parsed_ContentObject *pcobuf;
01628 struct ccn_indexbuf *compsbuf;
01629 int flags;
01630 int res;
01631 };
01632
01633 static enum ccn_upcall_res
01634 handle_simple_incoming_content(
01635 struct ccn_closure *selfp,
01636 enum ccn_upcall_kind kind,
01637 struct ccn_upcall_info *info)
01638 {
01639 struct simple_get_data *md = selfp->data;
01640 struct ccn *h = info->h;
01641
01642 if (kind == CCN_UPCALL_FINAL) {
01643 if (selfp != &md->closure)
01644 abort();
01645 free(md);
01646 return(CCN_UPCALL_RESULT_OK);
01647 }
01648 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
01649 return(selfp->intdata ? CCN_UPCALL_RESULT_REEXPRESS : CCN_UPCALL_RESULT_OK);
01650 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) {
01651 if ((md->flags & CCN_GET_NOKEYWAIT) == 0)
01652 return(CCN_UPCALL_RESULT_VERIFY);
01653 }
01654 if (kind == CCN_UPCALL_CONTENT_KEYMISSING) {
01655 if ((md->flags & CCN_GET_NOKEYWAIT) == 0)
01656 return(CCN_UPCALL_RESULT_FETCHKEY);
01657 }
01658 else if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_RAW)
01659 return(CCN_UPCALL_RESULT_ERR);
01660 if (md->resultbuf != NULL) {
01661 md->resultbuf->length = 0;
01662 ccn_charbuf_append(md->resultbuf,
01663 info->content_ccnb, info->pco->offset[CCN_PCO_E]);
01664 }
01665 if (md->pcobuf != NULL)
01666 memcpy(md->pcobuf, info->pco, sizeof(*md->pcobuf));
01667 if (md->compsbuf != NULL) {
01668 md->compsbuf->n = 0;
01669 ccn_indexbuf_append(md->compsbuf,
01670 info->content_comps->buf, info->content_comps->n);
01671 }
01672 md->res = 0;
01673 ccn_set_run_timeout(h, 0);
01674 return(CCN_UPCALL_RESULT_OK);
01675 }
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696 int
01697 ccn_get(struct ccn *h,
01698 struct ccn_charbuf *name,
01699 struct ccn_charbuf *interest_template,
01700 int timeout_ms,
01701 struct ccn_charbuf *resultbuf,
01702 struct ccn_parsed_ContentObject *pcobuf,
01703 struct ccn_indexbuf *compsbuf,
01704 int flags)
01705 {
01706 struct ccn *orig_h = h;
01707 struct hashtb *saved_keys = NULL;
01708 int res;
01709 struct simple_get_data *md;
01710
01711 if ((flags & ~((int)CCN_GET_NOKEYWAIT)) != 0)
01712 return(-1);
01713 if (h == NULL || h->running) {
01714 h = ccn_create();
01715 if (h == NULL)
01716 return(-1);
01717 if (orig_h != NULL) {
01718 saved_keys = h->keys;
01719 h->keys = orig_h->keys;
01720 }
01721 res = ccn_connect(h, NULL);
01722 if (res < 0) {
01723 ccn_destroy(&h);
01724 return(-1);
01725 }
01726 }
01727 md = calloc(1, sizeof(*md));
01728 md->resultbuf = resultbuf;
01729 md->pcobuf = pcobuf;
01730 md->compsbuf = compsbuf;
01731 md->flags = flags;
01732 md->res = -1;
01733 md->closure.p = &handle_simple_incoming_content;
01734 md->closure.data = md;
01735 md->closure.intdata = 1;
01736 md->closure.refcount = 1;
01737 res = ccn_express_interest(h, name, &md->closure, interest_template);
01738 if (res >= 0)
01739 res = ccn_run(h, timeout_ms);
01740 if (res >= 0)
01741 res = md->res;
01742 md->resultbuf = NULL;
01743 md->pcobuf = NULL;
01744 md->compsbuf = NULL;
01745 md->closure.intdata = 0;
01746 md->closure.refcount--;
01747 if (md->closure.refcount == 0)
01748 free(md);
01749 if (h != orig_h) {
01750 if (saved_keys != NULL)
01751 h->keys = saved_keys;
01752 ccn_destroy(&h);
01753 }
01754 return(res);
01755 }
01756
01757 static enum ccn_upcall_res
01758 handle_ccndid_response(struct ccn_closure *selfp,
01759 enum ccn_upcall_kind kind,
01760 struct ccn_upcall_info *info)
01761 {
01762 int res;
01763 const unsigned char *ccndid = NULL;
01764 size_t size = 0;
01765 struct ccn *h = info->h;
01766
01767 if (kind == CCN_UPCALL_FINAL) {
01768 free(selfp);
01769 return(CCN_UPCALL_RESULT_OK);
01770 }
01771 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
01772 return(CCN_UPCALL_RESULT_VERIFY);
01773 if (kind == CCN_UPCALL_CONTENT_KEYMISSING)
01774 return(CCN_UPCALL_RESULT_FETCHKEY);
01775 if (kind == CCN_UPCALL_CONTENT_RAW) {
01776 if (ccn_verify_content(h, info->content_ccnb, info->pco) == 0)
01777 kind = CCN_UPCALL_CONTENT;
01778 }
01779 if (kind != CCN_UPCALL_CONTENT) {
01780 NOTE_ERR(h, -1000 - kind);
01781 return(CCN_UPCALL_RESULT_ERR);
01782 }
01783 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
01784 info->content_ccnb,
01785 info->pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
01786 info->pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
01787 &ccndid,
01788 &size);
01789 if (res < 0) {
01790 NOTE_ERR(h, -1);
01791 return(CCN_UPCALL_RESULT_ERR);
01792 }
01793 if (h->ccndid == NULL) {
01794 h->ccndid = ccn_charbuf_create();
01795 if (h->ccndid == NULL)
01796 return(NOTE_ERRNO(h));
01797 }
01798 h->ccndid->length = 0;
01799 ccn_charbuf_append(h->ccndid, ccndid, size);
01800 ccn_notify_ccndid_changed(h);
01801 return(CCN_UPCALL_RESULT_OK);
01802 }
01803
01804 static void
01805 ccn_initiate_ccndid_fetch(struct ccn *h)
01806 {
01807 struct ccn_charbuf *name = NULL;
01808 struct ccn_closure *action = NULL;
01809
01810 name = ccn_charbuf_create();
01811 ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY");
01812 action = calloc(1, sizeof(*action));
01813 action->p = &handle_ccndid_response;
01814 ccn_express_interest(h, name, action, NULL);
01815 ccn_charbuf_destroy(&name);
01816 }
01817
01818 static enum ccn_upcall_res
01819 handle_prefix_reg_reply(
01820 struct ccn_closure *selfp,
01821 enum ccn_upcall_kind kind,
01822 struct ccn_upcall_info *info)
01823 {
01824 struct ccn_reg_closure *md = selfp->data;
01825 struct ccn *h = info->h;
01826 int lifetime = 10;
01827 struct ccn_forwarding_entry *fe = NULL;
01828 int res;
01829 const unsigned char *fe_ccnb = NULL;
01830 size_t fe_ccnb_size = 0;
01831
01832 if (kind == CCN_UPCALL_FINAL) {
01833
01834 if (selfp != &md->action)
01835 abort();
01836 if (md->interest_filter != NULL)
01837 md->interest_filter->ccn_reg_closure = NULL;
01838 selfp->data = NULL;
01839 free(md);
01840 return(CCN_UPCALL_RESULT_OK);
01841 }
01842 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
01843 return(CCN_UPCALL_RESULT_REEXPRESS);
01844 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
01845 return(CCN_UPCALL_RESULT_VERIFY);
01846 if (kind == CCN_UPCALL_CONTENT_KEYMISSING)
01847 return(CCN_UPCALL_RESULT_FETCHKEY);
01848 if (kind == CCN_UPCALL_CONTENT_RAW) {
01849 if (ccn_verify_content(h, info->content_ccnb, info->pco) == 0)
01850 kind = CCN_UPCALL_CONTENT;
01851 }
01852 if (kind != CCN_UPCALL_CONTENT) {
01853 NOTE_ERR(h, -1000 - kind);
01854 return(CCN_UPCALL_RESULT_ERR);
01855 }
01856 res = ccn_content_get_value(info->content_ccnb,
01857 info->pco->offset[CCN_PCO_E],
01858 info->pco,
01859 &fe_ccnb, &fe_ccnb_size);
01860 if (res == 0)
01861 fe = ccn_forwarding_entry_parse(fe_ccnb, fe_ccnb_size);
01862 if (fe == NULL) {
01863 XXX;
01864 lifetime = 30;
01865 }
01866 else
01867 lifetime = fe->lifetime;
01868 if (lifetime < 0)
01869 lifetime = 0;
01870 else if (lifetime > 3600)
01871 lifetime = 3600;
01872 if (md->interest_filter != NULL) {
01873 md->interest_filter->expiry = h->now;
01874 md->interest_filter->expiry.tv_sec += lifetime;
01875 }
01876 ccn_forwarding_entry_destroy(&fe);
01877 return(CCN_UPCALL_RESULT_OK);
01878 }
01879
01880 static void
01881 ccn_initiate_prefix_reg(struct ccn *h,
01882 const void *prefix, size_t prefix_size,
01883 struct interest_filter *i)
01884 {
01885 struct ccn_reg_closure *p = NULL;
01886 struct ccn_charbuf *reqname = NULL;
01887 struct ccn_charbuf *templ = NULL;
01888 struct ccn_forwarding_entry fe_store = { 0 };
01889 struct ccn_forwarding_entry *fe = &fe_store;
01890 struct ccn_charbuf *reg_request = NULL;
01891 struct ccn_charbuf *signed_reg_request = NULL;
01892 struct ccn_charbuf *empty = NULL;
01893
01894 i->expiry = h->now;
01895 i->expiry.tv_sec += 60;
01896
01897 if (h->sock == -1)
01898 return;
01899
01900 if (h->ccndid == NULL) {
01901 ccn_initiate_ccndid_fetch(h);
01902 i->flags |= CCN_FORW_WAITING_CCNDID;
01903 return;
01904 }
01905 if (i->ccn_reg_closure != NULL)
01906 return;
01907 p = calloc(1, sizeof(*p));
01908 if (p == NULL) {
01909 NOTE_ERRNO(h);
01910 return;
01911 }
01912 p->action.data = p;
01913 p->action.p = &handle_prefix_reg_reply;
01914 p->interest_filter = i;
01915 i->ccn_reg_closure = p;
01916 reqname = ccn_charbuf_create();
01917 ccn_name_from_uri(reqname, "ccnx:/ccnx");
01918 ccn_name_append(reqname, h->ccndid->buf, h->ccndid->length);
01919 ccn_name_append_str(reqname, "selfreg");
01920 fe->action = "selfreg";
01921 fe->ccnd_id = h->ccndid->buf;
01922 fe->ccnd_id_size = h->ccndid->length;
01923 fe->faceid = ~0;
01924 fe->name_prefix = ccn_charbuf_create();
01925 fe->flags = i->flags & 0xFF;
01926 fe->lifetime = -1;
01927 ccn_name_init(fe->name_prefix);
01928 ccn_name_append_components(fe->name_prefix, prefix, 0, prefix_size);
01929 reg_request = ccn_charbuf_create();
01930 ccnb_append_forwarding_entry(reg_request, fe);
01931 empty = ccn_charbuf_create();
01932 ccn_name_init(empty);
01933 signed_reg_request = ccn_charbuf_create();
01934 ccn_sign_content(h, signed_reg_request, empty, NULL,
01935 reg_request->buf, reg_request->length);
01936 ccn_name_append(reqname,
01937 signed_reg_request->buf, signed_reg_request->length);
01938
01939 ccn_express_interest(h, reqname, &p->action, templ);
01940 ccn_charbuf_destroy(&fe->name_prefix);
01941 ccn_charbuf_destroy(&reqname);
01942 ccn_charbuf_destroy(&templ);
01943 ccn_charbuf_destroy(®_request);
01944 ccn_charbuf_destroy(&signed_reg_request);
01945 ccn_charbuf_destroy(&empty);
01946 }
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957 int
01958 ccn_verify_content(struct ccn *h,
01959 const unsigned char *msg,
01960 struct ccn_parsed_ContentObject *pco)
01961 {
01962 struct ccn_pkey *pubkey = NULL;
01963 int res;
01964 unsigned char *buf = (unsigned char *)msg;
01965
01966 res = ccn_locate_key(h, msg, pco, &pubkey);
01967 if (res == 0) {
01968
01969 res = ccn_verify_signature(buf, pco->offset[CCN_PCO_E], pco, pubkey);
01970 res = (res == 1) ? 0 : -1;
01971 }
01972 return(res);
01973 }
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986 int
01987 ccn_load_private_key(struct ccn *h,
01988 const char *keystore_path,
01989 const char *keystore_passphrase,
01990 struct ccn_charbuf *pubid_out)
01991 {
01992 struct ccn_keystore *keystore = NULL;
01993 int res = 0;
01994 struct ccn_charbuf *pubid = pubid_out;
01995 struct ccn_charbuf *pubid_store = NULL;
01996 struct hashtb_enumerator ee;
01997 struct hashtb_enumerator *e = ⅇ
01998
01999 if (pubid == NULL)
02000 pubid = pubid_store = ccn_charbuf_create();
02001 if (pubid == NULL) {
02002 res = NOTE_ERRNO(h);
02003 goto Cleanup;
02004 }
02005 keystore = ccn_keystore_create();
02006 if (keystore == NULL) {
02007 res = NOTE_ERRNO(h);
02008 goto Cleanup;
02009 }
02010 res = ccn_keystore_init(keystore,
02011 (char *)keystore_path,
02012 (char *)keystore_passphrase);
02013 if (res != 0) {
02014 res = NOTE_ERRNO(h);
02015 goto Cleanup;
02016 }
02017 pubid->length = 0;
02018 ccn_charbuf_append(pubid,
02019 ccn_keystore_public_key_digest(keystore),
02020 ccn_keystore_public_key_digest_length(keystore));
02021 hashtb_start(h->keystores, e);
02022 res = hashtb_seek(e, pubid->buf, pubid->length, 0);
02023 if (res == HT_NEW_ENTRY) {
02024 struct ccn_keystore **p = e->data;
02025 *p = keystore;
02026 keystore = NULL;
02027 res = 0;
02028 }
02029 else if (res == HT_OLD_ENTRY)
02030 res = 0;
02031 else
02032 res = NOTE_ERRNO(h);
02033 hashtb_end(e);
02034 Cleanup:
02035 ccn_charbuf_destroy(&pubid_store);
02036 ccn_keystore_destroy(&keystore);
02037 return(res);
02038 }
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051 int
02052 ccn_load_default_key(struct ccn *h,
02053 const char *keystore_path,
02054 const char *keystore_passphrase)
02055 {
02056 struct ccn_charbuf *default_pubid = NULL;
02057 int res;
02058
02059 if (h->default_pubid != NULL)
02060 return(NOTE_ERR(h, EINVAL));
02061 default_pubid = ccn_charbuf_create();
02062 res = ccn_load_private_key(h,
02063 keystore_path,
02064 keystore_passphrase,
02065 default_pubid);
02066 if (res == 0)
02067 h->default_pubid = default_pubid;
02068 else
02069 ccn_charbuf_destroy(&default_pubid);
02070 return(res);
02071 }
02072
02073 static void
02074 finalize_keystore(struct hashtb_enumerator *e)
02075 {
02076 struct ccn_keystore **p = e->data;
02077 ccn_keystore_destroy(p);
02078 }
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089 int
02090 ccn_get_public_key(struct ccn *h,
02091 const struct ccn_signing_params *params,
02092 struct ccn_charbuf *digest_result,
02093 struct ccn_charbuf *result)
02094 {
02095 struct hashtb_enumerator ee;
02096 struct hashtb_enumerator *e = ⅇ
02097 struct ccn_keystore *keystore = NULL;
02098 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
02099 int res;
02100 res = ccn_chk_signing_params(h, params, &sp, NULL, NULL, NULL);
02101 if (res < 0)
02102 return(res);
02103 hashtb_start(h->keystores, e);
02104 if (hashtb_seek(e, sp.pubid, sizeof(sp.pubid), 0) == HT_OLD_ENTRY) {
02105 struct ccn_keystore **pk = e->data;
02106 keystore = *pk;
02107 if (digest_result != NULL) {
02108 digest_result->length = 0;
02109 ccn_charbuf_append(digest_result,
02110 ccn_keystore_public_key_digest(keystore),
02111 ccn_keystore_public_key_digest_length(keystore));
02112 }
02113 if (result != NULL) {
02114 struct ccn_buf_decoder decoder;
02115 struct ccn_buf_decoder *d;
02116 const unsigned char *p;
02117 size_t size;
02118 result->length = 0;
02119 ccn_append_pubkey_blob(result, ccn_keystore_public_key(keystore));
02120 d = ccn_buf_decoder_start(&decoder, result->buf, result->length);
02121 res = ccn_buf_match_blob(d, &p, &size);
02122 if (res >= 0) {
02123 memmove(result->buf, p, size);
02124 result->length = size;
02125 res = 0;
02126 }
02127 }
02128 }
02129 else {
02130 res = NOTE_ERR(h, -1);
02131 hashtb_delete(e);
02132 }
02133 hashtb_end(e);
02134 return(res);
02135 }
02136
02137
02138
02139
02140
02141 int
02142 ccn_chk_signing_params(struct ccn *h,
02143 const struct ccn_signing_params *params,
02144 struct ccn_signing_params *result,
02145 struct ccn_charbuf **ptimestamp,
02146 struct ccn_charbuf **pfinalblockid,
02147 struct ccn_charbuf **pkeylocator)
02148 {
02149 struct ccn_charbuf *default_pubid = NULL;
02150 struct ccn_charbuf *temp = NULL;
02151 const char *home = NULL;
02152 const char *ccnx_dir = NULL;
02153 int res = 0;
02154 int i;
02155 int conflicting;
02156 int needed;
02157
02158 if (params != NULL)
02159 *result = *params;
02160 if ((result->sp_flags & ~(CCN_SP_TEMPL_TIMESTAMP |
02161 CCN_SP_TEMPL_FINAL_BLOCK_ID |
02162 CCN_SP_TEMPL_FRESHNESS |
02163 CCN_SP_TEMPL_KEY_LOCATOR |
02164 CCN_SP_FINAL_BLOCK |
02165 CCN_SP_OMIT_KEY_LOCATOR
02166 )) != 0)
02167 return(NOTE_ERR(h, EINVAL));
02168 conflicting = CCN_SP_TEMPL_FINAL_BLOCK_ID | CCN_SP_FINAL_BLOCK;
02169 if ((result->sp_flags & conflicting) == conflicting)
02170 return(NOTE_ERR(h, EINVAL));
02171 conflicting = CCN_SP_TEMPL_KEY_LOCATOR | CCN_SP_OMIT_KEY_LOCATOR;
02172 if ((result->sp_flags & conflicting) == conflicting)
02173 return(NOTE_ERR(h, EINVAL));
02174 for (i = 0; i < sizeof(result->pubid) && result->pubid[i] == 0; i++)
02175 continue;
02176 if (i == sizeof(result->pubid)) {
02177 if (h->default_pubid == NULL) {
02178 default_pubid = ccn_charbuf_create();
02179 temp = ccn_charbuf_create();
02180 if (default_pubid == NULL || temp == NULL)
02181 return(NOTE_ERRNO(h));
02182 ccnx_dir = getenv("CCNX_DIR");
02183 if (ccnx_dir == NULL || ccnx_dir[0] == 0) {
02184 home = getenv("HOME");
02185 if (home == NULL)
02186 home = "";
02187 ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", home);
02188 }
02189 else
02190 ccn_charbuf_putf(temp, "%s/.ccnx_keystore", ccnx_dir);
02191 res = ccn_load_private_key(h,
02192 ccn_charbuf_as_string(temp),
02193 "Th1s1sn0t8g00dp8ssw0rd.",
02194 default_pubid);
02195 if (res == 0 && default_pubid->length == sizeof(result->pubid)) {
02196 h->default_pubid = default_pubid;
02197 default_pubid = NULL;
02198 }
02199 }
02200 if (h->default_pubid == NULL)
02201 res = NOTE_ERRNO(h);
02202 else
02203 memcpy(result->pubid, h->default_pubid->buf, sizeof(result->pubid));
02204 }
02205 ccn_charbuf_destroy(&default_pubid);
02206 ccn_charbuf_destroy(&temp);
02207 needed = result->sp_flags & (CCN_SP_TEMPL_TIMESTAMP |
02208 CCN_SP_TEMPL_FINAL_BLOCK_ID |
02209 CCN_SP_TEMPL_FRESHNESS |
02210 CCN_SP_TEMPL_KEY_LOCATOR );
02211 if (result->template_ccnb != NULL) {
02212 struct ccn_buf_decoder decoder;
02213 struct ccn_buf_decoder *d;
02214 size_t start;
02215 size_t stop;
02216 size_t size;
02217 const unsigned char *ptr = NULL;
02218 d = ccn_buf_decoder_start(&decoder,
02219 result->template_ccnb->buf,
02220 result->template_ccnb->length);
02221 if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
02222 ccn_buf_advance(d);
02223 if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest))
02224 ccn_parse_required_tagged_BLOB(d,
02225 CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
02226 start = d->decoder.token_index;
02227 ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Timestamp, 1, -1);
02228 stop = d->decoder.token_index;
02229 if ((needed & CCN_SP_TEMPL_TIMESTAMP) != 0) {
02230 i = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp,
02231 d->buf,
02232 start, stop,
02233 &ptr, &size);
02234 if (i == 0) {
02235 if (ptimestamp != NULL) {
02236 *ptimestamp = ccn_charbuf_create();
02237 ccn_charbuf_append(*ptimestamp, ptr, size);
02238 }
02239 needed &= ~CCN_SP_TEMPL_TIMESTAMP;
02240 }
02241 }
02242 ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Type, 1, -1);
02243 i = ccn_parse_optional_tagged_nonNegativeInteger(d,
02244 CCN_DTAG_FreshnessSeconds);
02245 if ((needed & CCN_SP_TEMPL_FRESHNESS) != 0 && i >= 0) {
02246 result->freshness = i;
02247 needed &= ~CCN_SP_TEMPL_FRESHNESS;
02248 }
02249 if (ccn_buf_match_dtag(d, CCN_DTAG_FinalBlockID)) {
02250 ccn_buf_advance(d);
02251 start = d->decoder.token_index;
02252 if (ccn_buf_match_some_blob(d))
02253 ccn_buf_advance(d);
02254 stop = d->decoder.token_index;
02255 ccn_buf_check_close(d);
02256 if ((needed & CCN_SP_TEMPL_FINAL_BLOCK_ID) != 0 &&
02257 d->decoder.state >= 0 && stop > start) {
02258 if (pfinalblockid != NULL) {
02259 *pfinalblockid = ccn_charbuf_create();
02260 ccn_charbuf_append(*pfinalblockid,
02261 d->buf + start, stop - start);
02262 }
02263 needed &= ~CCN_SP_TEMPL_FINAL_BLOCK_ID;
02264 }
02265 }
02266 start = d->decoder.token_index;
02267 if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator))
02268 ccn_buf_advance_past_element(d);
02269 stop = d->decoder.token_index;
02270 if ((needed & CCN_SP_TEMPL_KEY_LOCATOR) != 0 &&
02271 d->decoder.state >= 0 && stop > start) {
02272 if (pkeylocator != NULL) {
02273 *pkeylocator = ccn_charbuf_create();
02274 ccn_charbuf_append(*pkeylocator,
02275 d->buf + start, stop - start);
02276 }
02277 needed &= ~CCN_SP_TEMPL_KEY_LOCATOR;
02278 }
02279 ccn_buf_check_close(d);
02280 }
02281 if (d->decoder.state < 0)
02282 res = NOTE_ERR(h, EINVAL);
02283 }
02284 if (needed != 0)
02285 res = NOTE_ERR(h, EINVAL);
02286 return(res);
02287 }
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300 int
02301 ccn_sign_content(struct ccn *h,
02302 struct ccn_charbuf *resultbuf,
02303 const struct ccn_charbuf *name_prefix,
02304 const struct ccn_signing_params *params,
02305 const void *data, size_t size)
02306 {
02307 struct hashtb_enumerator ee;
02308 struct hashtb_enumerator *e = ⅇ
02309 struct ccn_signing_params p = CCN_SIGNING_PARAMS_INIT;
02310 struct ccn_charbuf *signed_info = NULL;
02311 struct ccn_keystore *keystore = NULL;
02312 struct ccn_charbuf *timestamp = NULL;
02313 struct ccn_charbuf *finalblockid = NULL;
02314 struct ccn_charbuf *keylocator = NULL;
02315 int res;
02316
02317 res = ccn_chk_signing_params(h, params, &p,
02318 ×tamp, &finalblockid, &keylocator);
02319 if (res < 0)
02320 return(res);
02321 hashtb_start(h->keystores, e);
02322 if (hashtb_seek(e, p.pubid, sizeof(p.pubid), 0) == HT_OLD_ENTRY) {
02323 struct ccn_keystore **pk = e->data;
02324 keystore = *pk;
02325 signed_info = ccn_charbuf_create();
02326 if (keylocator == NULL && (p.sp_flags & CCN_SP_OMIT_KEY_LOCATOR) == 0) {
02327
02328 keylocator = ccn_charbuf_create();
02329 ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
02330 ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
02331 res = ccn_append_pubkey_blob(keylocator,
02332 ccn_keystore_public_key(keystore));
02333 ccn_charbuf_append_closer(keylocator);
02334 ccn_charbuf_append_closer(keylocator);
02335 }
02336 if (res >= 0 && (p.sp_flags & CCN_SP_FINAL_BLOCK) != 0) {
02337 int ncomp;
02338 struct ccn_indexbuf *ndx;
02339 const unsigned char *comp = NULL;
02340 size_t size = 0;
02341
02342 ndx = ccn_indexbuf_create();
02343 ncomp = ccn_name_split(name_prefix, ndx);
02344 if (ncomp < 0)
02345 res = NOTE_ERR(h, EINVAL);
02346 else {
02347 finalblockid = ccn_charbuf_create();
02348 ccn_name_comp_get(name_prefix->buf,
02349 ndx, ncomp - 1, &comp, &size);
02350 ccn_charbuf_append_tt(finalblockid, size, CCN_BLOB);
02351 ccn_charbuf_append(finalblockid, comp, size);
02352 }
02353 ccn_indexbuf_destroy(&ndx);
02354 }
02355 if (res >= 0)
02356 res = ccn_signed_info_create(signed_info,
02357 ccn_keystore_public_key_digest(keystore),
02358 ccn_keystore_public_key_digest_length(keystore),
02359 timestamp,
02360 p.type,
02361 p.freshness,
02362 finalblockid,
02363 keylocator);
02364 if (res >= 0)
02365 res = ccn_encode_ContentObject(resultbuf,
02366 name_prefix,
02367 signed_info,
02368 data,
02369 size,
02370 NULL,
02371 ccn_keystore_private_key(keystore));
02372 }
02373 else {
02374 res = NOTE_ERR(h, -1);
02375 hashtb_delete(e);
02376 }
02377 hashtb_end(e);
02378 ccn_charbuf_destroy(×tamp);
02379 ccn_charbuf_destroy(&keylocator);
02380 ccn_charbuf_destroy(&finalblockid);
02381 ccn_charbuf_destroy(&signed_info);
02382 return(res);
02383 }
02384
02385
02386
02387
02388
02389
02390 int
02391 ccn_is_final_block(struct ccn_upcall_info *info)
02392 {
02393 const unsigned char *ccnb;
02394 size_t ccnb_size;
02395 int res;
02396 ccnb = info->content_ccnb;
02397 if (ccnb == NULL || info->pco == NULL)
02398 return(0);
02399 ccnb_size = info->pco->offset[CCN_PCO_E];
02400 if (info->pco->offset[CCN_PCO_B_FinalBlockID] !=
02401 info->pco->offset[CCN_PCO_E_FinalBlockID]) {
02402 const unsigned char *finalid = NULL;
02403 size_t finalid_size = 0;
02404 const unsigned char *nameid = NULL;
02405 size_t nameid_size = 0;
02406 struct ccn_indexbuf *cc = info->content_comps;
02407 if (cc->n < 2) return(-1);
02408 res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb,
02409 info->pco->offset[CCN_PCO_B_FinalBlockID],
02410 info->pco->offset[CCN_PCO_E_FinalBlockID],
02411 &finalid,
02412 &finalid_size);
02413 if (res < 0) return(-1);
02414 res = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb,
02415 cc->buf[cc->n - 2],
02416 cc->buf[cc->n - 1],
02417 &nameid,
02418 &nameid_size);
02419 if (res < 0) return(-1);
02420 if (finalid_size == nameid_size &&
02421 0 == memcmp(finalid, nameid, nameid_size))
02422 return(1);
02423 }
02424 return(0);
02425 }