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