00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <errno.h>
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <sys/errno.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032 #include <ccn/ccn.h>
00033 #include <ccn/charbuf.h>
00034 #include <ccn/ccn_private.h>
00035 #include <ccn/schedule.h>
00036 #include <ccn/sockaddrutil.h>
00037 #include <ccn/uri.h>
00038 #include <ccn/keystore.h>
00039 #include "ccnr_private.h"
00040
00041 #include "ccnr_internal_client.h"
00042
00043 #include "ccnr_forwarding.h"
00044 #include "ccnr_io.h"
00045 #include "ccnr_msg.h"
00046 #include "ccnr_proto.h"
00047 #include "ccnr_util.h"
00048
00049 static struct ccn_charbuf *
00050 ccnr_init_service_ccnb(struct ccnr_handle *ccnr, struct ccn *h, const char *baseuri, int freshness)
00051 {
00052 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00053 struct ccn_charbuf *name = ccn_charbuf_create();
00054 struct ccn_charbuf *pubid = ccn_charbuf_create();
00055 struct ccn_charbuf *pubkey = ccn_charbuf_create();
00056 struct ccn_charbuf *keyid = ccn_charbuf_create();
00057 struct ccn_charbuf *cob = ccn_charbuf_create();
00058 int res;
00059
00060 res = ccn_get_public_key(h, NULL, pubid, pubkey);
00061 if (res < 0) abort();
00062 ccn_name_from_uri(name, baseuri);
00063 ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1);
00064 ccn_charbuf_append_string(keyid, ".M.K");
00065 ccn_charbuf_append_value(keyid, 0, 1);
00066 ccn_charbuf_append_charbuf(keyid, pubid);
00067 ccn_name_append(name, keyid->buf, keyid->length);
00068 ccn_create_version(h, name, 0, ccnr->starttime, ccnr->starttime_usec * 1000);
00069 sp.template_ccnb = ccn_charbuf_create();
00070 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
00071 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
00072 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
00073 ccn_charbuf_append_charbuf(sp.template_ccnb, name);
00074 ccn_charbuf_append_closer(sp.template_ccnb);
00075
00076
00077
00078
00079 ccn_charbuf_append_closer(sp.template_ccnb);
00080 ccn_charbuf_append_closer(sp.template_ccnb);
00081 sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
00082 ccn_name_from_uri(name, "%00");
00083 sp.sp_flags |= CCN_SP_FINAL_BLOCK;
00084 sp.type = CCN_CONTENT_KEY;
00085 sp.freshness = freshness;
00086 res = ccn_sign_content(h, cob, name, &sp, pubkey->buf, pubkey->length);
00087 if (res != 0) abort();
00088 ccn_charbuf_destroy(&name);
00089 ccn_charbuf_destroy(&pubid);
00090 ccn_charbuf_destroy(&pubkey);
00091 ccn_charbuf_destroy(&keyid);
00092 ccn_charbuf_destroy(&sp.template_ccnb);
00093 return(cob);
00094 }
00095
00096
00097
00098
00099 PUBLIC enum ccn_upcall_res
00100 ccnr_answer_req(struct ccn_closure *selfp,
00101 enum ccn_upcall_kind kind,
00102 struct ccn_upcall_info *info)
00103 {
00104 struct ccn_charbuf *msg = NULL;
00105 struct ccn_charbuf *name = NULL;
00106 struct ccn_charbuf *keylocator = NULL;
00107 struct ccn_charbuf *signed_info = NULL;
00108 struct ccn_charbuf *reply_body = NULL;
00109 struct ccnr_handle *ccnr = NULL;
00110 int res = 0;
00111 int start = 0;
00112 int end = 0;
00113 int morecomps = 0;
00114 const unsigned char *final_comp = NULL;
00115 size_t final_size = 0;
00116 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00117
00118 switch (kind) {
00119 case CCN_UPCALL_FINAL:
00120 free(selfp);
00121 return(CCN_UPCALL_RESULT_OK);
00122 case CCN_UPCALL_INTEREST:
00123 break;
00124 case CCN_UPCALL_CONSUMED_INTEREST:
00125 return(CCN_UPCALL_RESULT_OK);
00126 default:
00127 return(CCN_UPCALL_RESULT_ERR);
00128 }
00129 ccnr = (struct ccnr_handle *)selfp->data;
00130 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00131 ccnr_debug_ccnb(ccnr, __LINE__, "ccnr_answer_req", NULL,
00132 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00133 morecomps = selfp->intdata & MORECOMPS_MASK;
00134 if ((info->pi->answerfrom & CCN_AOK_NEW) == 0 &&
00135 selfp->intdata != OP_SERVICE &&
00136 selfp->intdata != OP_NOTICE)
00137 return(CCN_UPCALL_RESULT_OK);
00138 if (info->matched_comps >= info->interest_comps->n)
00139 goto Bail;
00140 if (selfp->intdata != OP_PING &&
00141 selfp->intdata != OP_NOTICE &&
00142 selfp->intdata != OP_SERVICE &&
00143 info->pi->prefix_comps != info->matched_comps + morecomps)
00144 goto Bail;
00145 if (morecomps == 1) {
00146 res = ccn_name_comp_get(info->interest_ccnb, info->interest_comps,
00147 info->matched_comps,
00148 &final_comp, &final_size);
00149 if (res < 0)
00150 goto Bail;
00151 }
00152 if ((selfp->intdata & MUST_VERIFY) != 0) {
00153 struct ccn_parsed_ContentObject pco = {0};
00154
00155 res = ccn_parse_ContentObject(final_comp, final_size, &pco, NULL);
00156 if (res < 0) {
00157 ccnr_debug_ccnb(ccnr, __LINE__, "co_parse_failed", NULL,
00158 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00159 goto Bail;
00160 }
00161 res = ccn_verify_content(info->h, final_comp, &pco);
00162 if (res != 0) {
00163 ccnr_debug_ccnb(ccnr, __LINE__, "co_verify_failed", NULL,
00164 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00165 goto Bail;
00166 }
00167 }
00168 sp.freshness = 10;
00169 switch (selfp->intdata & OPER_MASK) {
00170 case OP_SERVICE:
00171 if (ccnr->service_ccnb == NULL)
00172 ccnr->service_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_LOCAL_URI, 600);
00173 if (ccn_content_matches_interest(
00174 ccnr->service_ccnb->buf,
00175 ccnr->service_ccnb->length,
00176 1,
00177 NULL,
00178 info->interest_ccnb,
00179 info->pi->offset[CCN_PI_E],
00180 info->pi
00181 )) {
00182 ccn_put(info->h, ccnr->service_ccnb->buf,
00183 ccnr->service_ccnb->length);
00184 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00185 goto Finish;
00186 }
00187
00188 if (ccnr->neighbor_ccnb == NULL)
00189 ccnr->neighbor_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_NEIGHBOR_URI, 5);
00190 if (ccn_content_matches_interest(
00191 ccnr->neighbor_ccnb->buf,
00192 ccnr->neighbor_ccnb->length,
00193 1,
00194 NULL,
00195 info->interest_ccnb,
00196 info->pi->offset[CCN_PI_E],
00197 info->pi
00198 )) {
00199 ccn_put(info->h, ccnr->neighbor_ccnb->buf,
00200 ccnr->neighbor_ccnb->length);
00201 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00202 goto Finish;
00203 }
00204 if (ccn_content_matches_interest(
00205 ccnr->policy_link_cob->buf,
00206 ccnr->policy_link_cob->length,
00207 1,
00208 NULL,
00209 info->interest_ccnb,
00210 info->pi->offset[CCN_PI_E],
00211 info->pi
00212 )) {
00213 ccn_put(info->h, ccnr->policy_link_cob->buf,
00214 ccnr->policy_link_cob->length);
00215 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00216 goto Finish;
00217 }
00218 goto Bail;
00219 break;
00220 default:
00221 goto Bail;
00222 }
00223 if (res < 0)
00224 goto Bail;
00225 if (res == CCN_CONTENT_NACK)
00226 sp.type = res;
00227 msg = ccn_charbuf_create();
00228 name = ccn_charbuf_create();
00229 start = info->pi->offset[CCN_PI_B_Name];
00230 end = info->interest_comps->buf[info->pi->prefix_comps];
00231 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00232 ccn_charbuf_append_closer(name);
00233 res = ccn_sign_content(info->h, msg, name, &sp,
00234 reply_body->buf, reply_body->length);
00235 if (res < 0)
00236 goto Bail;
00237 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00238 ccnr_debug_ccnb(ccnr, __LINE__, "ccnr_answer_req_response", NULL,
00239 msg->buf, msg->length);
00240 res = ccn_put(info->h, msg->buf, msg->length);
00241 if (res < 0)
00242 goto Bail;
00243 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00244 goto Finish;
00245 Bail:
00246 res = CCN_UPCALL_RESULT_ERR;
00247 Finish:
00248 ccn_charbuf_destroy(&msg);
00249 ccn_charbuf_destroy(&name);
00250 ccn_charbuf_destroy(&keylocator);
00251 ccn_charbuf_destroy(&reply_body);
00252 ccn_charbuf_destroy(&signed_info);
00253 return(res);
00254 }
00255
00256 static int
00257 ccnr_internal_client_refresh(struct ccn_schedule *sched,
00258 void *clienth,
00259 struct ccn_scheduled_event *ev,
00260 int flags)
00261 {
00262 struct ccnr_handle *ccnr = clienth;
00263 int microsec = 0;
00264 if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00265 ccnr->internal_client != NULL &&
00266 ccnr->internal_client_refresh == ev) {
00267 microsec = ccn_process_scheduled_operations(ccnr->internal_client);
00268 if (microsec > ev->evint)
00269 microsec = ev->evint;
00270 }
00271 if (microsec <= 0 && ccnr->internal_client_refresh == ev)
00272 ccnr->internal_client_refresh = NULL;
00273 return(microsec);
00274 }
00275
00276 #define CCNR_ID_TEMPL "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
00277
00278 PUBLIC void
00279 ccnr_uri_listen(struct ccnr_handle *ccnr, struct ccn *ccn, const char *uri,
00280 ccn_handler p, intptr_t intdata)
00281 {
00282 struct ccn_charbuf *name;
00283 struct ccn_charbuf *uri_modified = NULL;
00284 struct ccn_closure *closure;
00285 struct ccn_indexbuf *comps;
00286 const unsigned char *comp;
00287 size_t comp_size;
00288 size_t offset;
00289
00290 name = ccn_charbuf_create();
00291 ccn_name_from_uri(name, uri);
00292 comps = ccn_indexbuf_create();
00293 if (ccn_name_split(name, comps) < 0)
00294 abort();
00295 if (ccn_name_comp_get(name->buf, comps, 1, &comp, &comp_size) >= 0) {
00296 if (comp_size == 32 && 0 == memcmp(comp, CCNR_ID_TEMPL, 32)) {
00297
00298 offset = comp - name->buf;
00299 memcpy(name->buf + offset, ccnr->ccnr_id, 32);
00300 uri_modified = ccn_charbuf_create();
00301 ccn_uri_append(uri_modified, name->buf, name->length, 1);
00302 uri = (char *)uri_modified->buf;
00303 }
00304 }
00305 closure = calloc(1, sizeof(*closure));
00306 closure->p = p;
00307 closure->data = ccnr;
00308 closure->intdata = intdata;
00309 ccn_set_interest_filter(ccn, name, closure);
00310 ccn_charbuf_destroy(&name);
00311 ccn_charbuf_destroy(&uri_modified);
00312 ccn_indexbuf_destroy(&comps);
00313 }
00314
00315
00316
00317
00318
00319
00320 #ifndef CCNR_KEYSTORE_PASS
00321 #define CCNR_KEYSTORE_PASS "Th1s 1s n0t 8 g00d R3p0s1t0ry p8ssw0rd!"
00322 #endif
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 int
00333 ccnr_init_repo_keystore(struct ccnr_handle *ccnr, struct ccn *h)
00334 {
00335 struct ccn_charbuf *temp = NULL;
00336 struct ccn_charbuf *culprit = NULL;
00337 struct stat statbuf;
00338 int res = -1;
00339 size_t save;
00340 char *keystore_path = NULL;
00341 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00342
00343 temp = ccn_charbuf_create();
00344 culprit = temp;
00345 ccn_charbuf_putf(temp, "%s/", ccnr->directory);
00346 res = stat(ccn_charbuf_as_string(temp), &statbuf);
00347 if (res == -1)
00348 goto Finish;
00349 if ((statbuf.st_mode & S_IFDIR) == 0) {
00350 res = -1;
00351 errno = ENOTDIR;
00352 goto Finish;
00353 }
00354 save = temp->length;
00355 ccn_charbuf_putf(temp, "ccnx_repository_keystore");
00356 keystore_path = strdup(ccn_charbuf_as_string(temp));
00357 res = stat(keystore_path, &statbuf);
00358
00359 if (res == 0 && h != NULL)
00360 res = ccn_load_default_key(h, keystore_path, CCNR_KEYSTORE_PASS);
00361 if (res >= 0) {
00362 culprit = NULL;
00363 goto Finish;
00364 }
00365
00366 res = ccn_keystore_file_init(keystore_path, CCNR_KEYSTORE_PASS, "Repository", 0, 0);
00367 if (res != 0) {
00368 res = -1;
00369 goto Finish;
00370 }
00371 if (CCNSHOULDLOG(ccnr, keystore, CCNL_WARNING))
00372 ccnr_msg(ccnr, "New repository private key saved in %s", keystore_path);
00373 if (h != NULL)
00374 res = ccn_load_default_key(h, keystore_path, CCNR_KEYSTORE_PASS);
00375 Finish:
00376 if (res >= 0 && h != NULL)
00377 res = ccn_chk_signing_params(h, NULL, &sp, NULL, NULL, NULL);
00378 if (res >= 0 && h != NULL) {
00379 memcpy(ccnr->ccnr_id, sp.pubid, sizeof(ccnr->ccnr_id));
00380 if (ccnr->ccnr_keyid == NULL)
00381 ccnr->ccnr_keyid = ccn_charbuf_create();
00382 else
00383 ccnr->ccnr_keyid->length = 0;
00384 ccn_charbuf_append_value(ccnr->ccnr_keyid, CCN_MARKER_CONTROL, 1);
00385 ccn_charbuf_append_string(ccnr->ccnr_keyid, ".M.K");
00386 ccn_charbuf_append_value(ccnr->ccnr_keyid, 0, 1);
00387 ccn_charbuf_append(ccnr->ccnr_keyid, ccnr->ccnr_id, sizeof(ccnr->ccnr_id));
00388 }
00389 if (res < 0) {
00390 ccnr->running = -1;
00391 if (culprit != NULL)
00392 ccnr_msg(ccnr, "Error accessing keystore - %s: %s\n",
00393 strerror(errno), ccn_charbuf_as_string(temp));
00394 }
00395 ccn_charbuf_destroy(&temp);
00396 if (keystore_path != NULL)
00397 free(keystore_path);
00398 return(res);
00399 }
00400
00401 static int
00402 post_face_notice(struct ccnr_handle *ccnr, unsigned filedesc)
00403 {
00404 struct fdholder *fdholder = ccnr_r_io_fdholder_from_fd(ccnr, filedesc);
00405 struct ccn_charbuf *msg = ccn_charbuf_create();
00406 int res = -1;
00407 int port;
00408
00409
00410 if (fdholder == NULL)
00411 ccn_charbuf_putf(msg, "destroyface(%u);\n", filedesc);
00412 else {
00413 ccn_charbuf_putf(msg, "newface(%u, 0x%x", filedesc, fdholder->flags);
00414 if (fdholder->name->length != 0 &&
00415 (fdholder->flags & (CCNR_FACE_INET | CCNR_FACE_INET6)) != 0) {
00416 ccn_charbuf_putf(msg, ", ");
00417 port = ccn_charbuf_append_sockaddr(msg, (struct sockaddr *)fdholder->name->buf);
00418 if (port < 0)
00419 msg->length--;
00420 else if (port > 0)
00421 ccn_charbuf_putf(msg, ":%d", port);
00422 }
00423 ccn_charbuf_putf(msg, ");\n", filedesc);
00424 }
00425 res = ccn_seqw_write(ccnr->notice, msg->buf, msg->length);
00426 ccn_charbuf_destroy(&msg);
00427 return(res);
00428 }
00429
00430 static int
00431 ccnr_notice_push(struct ccn_schedule *sched,
00432 void *clienth,
00433 struct ccn_scheduled_event *ev,
00434 int flags)
00435 {
00436 struct ccnr_handle *ccnr = clienth;
00437 struct ccn_indexbuf *chface = NULL;
00438 int i = 0;
00439 int j = 0;
00440 int microsec = 0;
00441 int res = 0;
00442
00443 if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00444 ccnr->notice != NULL &&
00445 ccnr->notice_push == ev &&
00446 ccnr->chface != NULL) {
00447 chface = ccnr->chface;
00448 ccn_seqw_batch_start(ccnr->notice);
00449 for (i = 0; i < chface->n && res != -1; i++)
00450 res = post_face_notice(ccnr, chface->buf[i]);
00451 ccn_seqw_batch_end(ccnr->notice);
00452 for (j = 0; i < chface->n; i++, j++)
00453 chface->buf[j] = chface->buf[i];
00454 chface->n = j;
00455 if (res == -1)
00456 microsec = 3000;
00457 }
00458 if (microsec <= 0)
00459 ccnr->notice_push = NULL;
00460 return(microsec);
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470 void
00471 ccnr_face_status_change(struct ccnr_handle *ccnr, unsigned filedesc)
00472 {
00473 struct ccn_indexbuf *chface = ccnr->chface;
00474 if (chface != NULL) {
00475 ccn_indexbuf_set_insert(chface, filedesc);
00476 if (ccnr->notice_push == NULL)
00477 ccnr->notice_push = ccn_schedule_event(ccnr->sched, 2000,
00478 ccnr_notice_push,
00479 NULL, 0);
00480 }
00481 }
00482
00483 int
00484 ccnr_internal_client_start(struct ccnr_handle *ccnr)
00485 {
00486 if (ccnr->internal_client != NULL)
00487 return(-1);
00488 if (ccnr->face0 == NULL)
00489 abort();
00490 ccnr->internal_client = ccn_create();
00491 if (ccnr_init_repo_keystore(ccnr, ccnr->internal_client) < 0) {
00492 ccn_destroy(&ccnr->internal_client);
00493 return(-1);
00494 }
00495 ccnr->internal_client_refresh = ccn_schedule_event(ccnr->sched, 50000,
00496 ccnr_internal_client_refresh,
00497 NULL, CCN_INTEREST_LIFETIME_MICROSEC);
00498 return(0);
00499 }
00500
00501 void
00502 ccnr_internal_client_stop(struct ccnr_handle *ccnr)
00503 {
00504 ccnr->notice = NULL;
00505 if (ccnr->notice_push != NULL)
00506 ccn_schedule_cancel(ccnr->sched, ccnr->notice_push);
00507 ccn_indexbuf_destroy(&ccnr->chface);
00508 ccn_destroy(&ccnr->internal_client);
00509 ccn_charbuf_destroy(&ccnr->service_ccnb);
00510 ccn_charbuf_destroy(&ccnr->neighbor_ccnb);
00511 if (ccnr->internal_client_refresh != NULL)
00512 ccn_schedule_cancel(ccnr->sched, ccnr->internal_client_refresh);
00513 }
00514
00515
00516
00517
00518
00519 static int
00520 ccnr_direct_client_refresh(struct ccn_schedule *sched,
00521 void *clienth,
00522 struct ccn_scheduled_event *ev,
00523 int flags)
00524 {
00525 struct ccnr_handle *ccnr = clienth;
00526 int microsec = 0;
00527 if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00528 ccnr->direct_client != NULL &&
00529 ccnr->direct_client_refresh == ev) {
00530 microsec = ccn_process_scheduled_operations(ccnr->direct_client);
00531
00532 if CCNSHOULDLOG(ccnr, refresh, CCNL_FINEST)
00533 ccnr_msg(ccnr, "direct_client_refresh %d in %d usec",
00534 ccn_get_connection_fd(ccnr->direct_client), microsec);
00535 if (microsec > ev->evint)
00536 microsec = ev->evint;
00537 if (microsec == 0)
00538 microsec = CCN_INTEREST_LIFETIME_MICROSEC;
00539 }
00540 if (microsec <= 0 && ccnr->direct_client_refresh == ev)
00541 ccnr->direct_client_refresh = NULL;
00542 return(microsec);
00543 }
00544
00545 int
00546 ccnr_direct_client_start(struct ccnr_handle *ccnr)
00547 {
00548 ccnr->direct_client = ccn_create();
00549 if (ccnr_init_repo_keystore(ccnr, ccnr->direct_client) < 0) {
00550 ccn_destroy(&ccnr->direct_client);
00551 return(-1);
00552 }
00553 ccnr->direct_client_refresh = ccn_schedule_event(ccnr->sched, 50000,
00554 ccnr_direct_client_refresh,
00555 NULL, CCN_INTEREST_LIFETIME_MICROSEC);
00556 return(0);
00557 }
00558
00559 void
00560 ccnr_direct_client_stop(struct ccnr_handle *ccnr)
00561 {
00562 if (ccnr->notice_push != NULL)
00563 ccn_schedule_cancel(ccnr->sched, ccnr->notice_push);
00564 ccn_indexbuf_destroy(&ccnr->chface);
00565 ccn_destroy(&ccnr->direct_client);
00566 ccn_charbuf_destroy(&ccnr->service_ccnb);
00567 ccn_charbuf_destroy(&ccnr->neighbor_ccnb);
00568 if (ccnr->direct_client_refresh != NULL)
00569 ccn_schedule_cancel(ccnr->sched, ccnr->direct_client_refresh);
00570 }
00571