X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=site.c;h=922aa590396e85acef813696aec2764393d05b7a;hb=99d512b7519c0a4e5c595e44c7533ae2130d0e08;hp=6e5c5a67d56ed0d8b2bf8a06662298c9039a6c27;hpb=403cdd364693a05c700f04085fc05dbf575d97ef;p=secnet.git diff --git a/site.c b/site.c index 6e5c5a6..922aa59 100644 --- a/site.c +++ b/site.c @@ -109,6 +109,8 @@ #define CASES_MSG3_KNOWN LABEL_MSG3: case LABEL_MSG3BIS +struct msg; + int32_t site_max_start_pad = 4*4; static cstring_t state_name(uint32_t state) @@ -140,6 +142,7 @@ static cstring_t state_name(uint32_t state) #define LOG_DUMP 0x00000100 #define LOG_ERROR 0x00000400 #define LOG_PEER_ADDRS 0x00000800 +#define LOG_SIGKEYS 0x00001000 static struct flagstr log_event_table[]={ { "unexpected", LOG_UNEXPECTED }, @@ -153,8 +156,9 @@ static struct flagstr log_event_table[]={ { "dump-packets", LOG_DUMP }, { "errors", LOG_ERROR }, { "peer-addrs", LOG_PEER_ADDRS }, + { "sigkeys", LOG_SIGKEYS }, { "default", LOG_SETUP_INIT|LOG_SETUP_TIMEOUT| - LOG_ACTIVATE_KEY|LOG_TIMEOUT_KEY|LOG_SEC|LOG_ERROR }, + LOG_ACTIVATE_KEY|LOG_TIMEOUT_KEY|LOG_SEC|LOG_ERROR|LOG_SIGKEYS }, { "all", 0xffffffff }, { NULL, 0 } }; @@ -317,7 +321,6 @@ struct site { struct transform_if **transforms; int ntransforms; struct dh_if *dh; - struct hash_if *hash; uint32_t index; /* Index of this site */ uint32_t early_capabilities; @@ -391,19 +394,28 @@ static uint32_t event_log_priority(struct site *st, uint32_t event) case LOG_DUMP: return M_DEBUG; case LOG_ERROR: return M_ERR; case LOG_PEER_ADDRS: return M_DEBUG; + case LOG_SIGKEYS: return M_INFO; default: return M_ERR; } } +static uint32_t slog_start(struct site *st, uint32_t event) +{ + uint32_t class=event_log_priority(st, event); + if (class) { + slilog_part(st->log,class,"%s: ",st->tunname); + } + return class; +} + static void vslog(struct site *st, uint32_t event, cstring_t msg, va_list ap) FORMAT(printf,3,0); static void vslog(struct site *st, uint32_t event, cstring_t msg, va_list ap) { uint32_t class; - class=event_log_priority(st, event); + class=slog_start(st,event); if (class) { - slilog_part(st->log,class,"%s: ",st->tunname); vslilog_part(st->log,class,msg,ap); slilog_part(st->log,class,"\n"); } @@ -458,7 +470,9 @@ static bool_t initiate_key_setup(struct site *st, cstring_t reason, static void enter_state_run(struct site *st); static bool_t enter_state_resolve(struct site *st); static void decrement_resolving_count(struct site *st, int by); -static bool_t enter_new_state(struct site *st,uint32_t next); +static bool_t enter_new_state(struct site *st,uint32_t next, + const struct msg *prompt + /* may be 0 for SENTMSG1 */); static void enter_state_wait(struct site *st); static void activate_new_key(struct site *st); @@ -534,8 +548,7 @@ struct msg { int32_t pklen; char *pk; int32_t hashlen; - int32_t siglen; - char *sig; + struct alg_msg_data sig; }; static int32_t wait_timeout(struct site *st) { @@ -613,10 +626,10 @@ static void append_string_xinfo_done(struct buffer_if *buf, /* Build any of msg1 to msg4. msg5 and msg6 are built from the inside out using a transform of config data supplied by netlink */ -static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what) +static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what, + const struct msg *prompt + /* may be 0 for MSG1 */) { - void *hst; - uint8_t *hash; string_t dhpub; unsigned minor; @@ -637,6 +650,7 @@ static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what) if (type_is_msg34(type)) { buf_append_uint16(&st->buffer,st->mtu_target); } + struct sigprivkey_if *privkey=st->privkey; append_string_xinfo_done(&st->buffer,&xia); buf_append_string(&st->buffer,st->remotename); @@ -656,18 +670,15 @@ static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what) dhpub=st->dh->makepublic(st->dh->st,st->dhsecret,st->dh->len); buf_append_string(&st->buffer,dhpub); free(dhpub); - hash=safe_malloc(st->hash->len, "generate_msg"); - hst=st->hash->init(); - st->hash->update(hst,st->buffer.start,st->buffer.size); - st->hash->final(hst,hash); - bool_t ok=st->privkey->sign(st->privkey->st,hash,st->hash->len, - &st->buffer); + + bool_t ok=privkey->sign(privkey->st, + st->buffer.start, + st->buffer.size, + &st->buffer); if (!ok) goto fail; - free(hash); return True; fail: - free(hash); return False; } @@ -745,17 +756,13 @@ static bool_t unpick_msg(struct site *st, uint32_t type, CHECK_AVAIL(msg,m->pklen); m->pk=buf_unprepend(msg,m->pklen); m->hashlen=msg->start-m->hashstart; - CHECK_AVAIL(msg,2); - m->siglen=buf_unprepend_uint16(msg); - CHECK_AVAIL(msg,m->siglen); - m->sig=buf_unprepend(msg,m->siglen); - CHECK_EMPTY(msg); + struct sigpubkey_if *pubkey=st->pubkey; - /* In `process_msg3_msg4' below, we assume that we can write a nul - * terminator following the signature. Make sure there's enough space. - */ - if (msg->start >= msg->base + msg->alloclen) + if (!pubkey->unpick(pubkey->st,msg,&m->sig)) { return False; + } + + CHECK_EMPTY(msg); return True; } @@ -804,14 +811,21 @@ static bool_t check_msg(struct site *st, uint32_t type, struct msg *m, return False; } -static bool_t generate_msg1(struct site *st) +static bool_t kex_init(struct site *st) { st->random->generate(st->random->st,NONCELEN,st->localN); - return generate_msg(st,LABEL_MSG1,"site:MSG1"); + return True; +} + +static bool_t generate_msg1(struct site *st, const struct msg *prompt_maybe_0) +{ + return + generate_msg(st,LABEL_MSG1,"site:MSG1",prompt_maybe_0); } static bool_t process_msg1(struct site *st, struct buffer_if *msg1, - const struct comm_addr *src, struct msg *m) + const struct comm_addr *src, + const struct msg *m) { /* We've already determined we're in an appropriate state to process an incoming MSG1, and that the MSG1 has correct values @@ -823,25 +837,26 @@ static bool_t process_msg1(struct site *st, struct buffer_if *msg1, return True; } -static bool_t generate_msg2(struct site *st) +static bool_t generate_msg2(struct site *st, + const struct msg *prompt_may_be_null) { - st->random->generate(st->random->st,NONCELEN,st->localN); - return generate_msg(st,LABEL_MSG2,"site:MSG2"); + return + generate_msg(st,LABEL_MSG2,"site:MSG2",prompt_may_be_null); } static bool_t process_msg2(struct site *st, struct buffer_if *msg2, - const struct comm_addr *src) + const struct comm_addr *src, + struct msg *m /* returned */) { - struct msg m; cstring_t err; - if (!unpick_msg(st,LABEL_MSG2,msg2,&m)) return False; - if (!check_msg(st,LABEL_MSG2,&m,&err)) { + if (!unpick_msg(st,LABEL_MSG2,msg2,m)) return False; + if (!check_msg(st,LABEL_MSG2,m,&err)) { slog(st,LOG_SEC,"msg2: %s",err); return False; } - st->setup_session_id=m.source; - st->remote_capabilities=m.remote_capabilities; + st->setup_session_id=m->source; + st->remote_capabilities=m->remote_capabilities; /* Select the transform to use */ @@ -872,11 +887,11 @@ kind##_found: \ #undef CHOOSE_CRYPTO - memcpy(st->remoteN,m.nR,NONCELEN); + memcpy(st->remoteN,m->nR,NONCELEN); return True; } -static bool_t generate_msg3(struct site *st) +static bool_t generate_msg3(struct site *st, const struct msg *prompt) { /* Now we have our nonce and their nonce. Think of a secret key, and create message number 3. */ @@ -885,27 +900,20 @@ static bool_t generate_msg3(struct site *st) (st->remote_capabilities & CAPAB_TRANSFORM_MASK) ? LABEL_MSG3BIS : LABEL_MSG3, - "site:MSG3"); + "site:MSG3",prompt); } static bool_t process_msg3_msg4(struct site *st, struct msg *m) { - uint8_t *hash; - void *hst; + struct sigpubkey_if *pubkey=st->pubkey; /* Check signature and store g^x mod m */ - hash=safe_malloc(st->hash->len, "process_msg3_msg4"); - hst=st->hash->init(); - st->hash->update(hst,m->hashstart,m->hashlen); - st->hash->final(hst,hash); - /* Terminate signature with a '0' - already checked that this will fit */ - m->sig[m->siglen]=0; - if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m->sig)) { + if (!pubkey->check(pubkey->st, + m->hashstart,m->hashlen, + &m->sig)) { slog(st,LOG_SEC,"msg3/msg4 signature failed check!"); - free(hash); return False; } - free(hash); st->remote_adv_mtu=m->remote_mtu; @@ -913,9 +921,9 @@ static bool_t process_msg3_msg4(struct site *st, struct msg *m) } static bool_t process_msg3(struct site *st, struct buffer_if *msg3, - const struct comm_addr *src, uint32_t msgtype) + const struct comm_addr *src, uint32_t msgtype, + struct msg *m /* returned */) { - struct msg m; cstring_t err; switch (msgtype) { @@ -923,17 +931,17 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3, default: assert(0); } - if (!unpick_msg(st,msgtype,msg3,&m)) return False; - if (!check_msg(st,msgtype,&m,&err)) { + if (!unpick_msg(st,msgtype,msg3,m)) return False; + if (!check_msg(st,msgtype,m,&err)) { slog(st,LOG_SEC,"msg3: %s",err); return False; } - uint32_t capab_adv_late = m.remote_capabilities + uint32_t capab_adv_late = m->remote_capabilities & ~st->remote_capabilities & st->early_capabilities; if (capab_adv_late) { slog(st,LOG_SEC,"msg3 impermissibly adds early capability flag(s)" " %#"PRIx32" (was %#"PRIx32", now %#"PRIx32")", - capab_adv_late, st->remote_capabilities, m.remote_capabilities); + capab_adv_late, st->remote_capabilities, m->remote_capabilities); return False; } @@ -942,11 +950,11 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3, int i; \ for (i=0; in##kind##s; i++) { \ iface=st->kind##s[i]; \ - if (iface->capab_bit == m.capab_##kind##num) \ + if (iface->capab_bit == m->capab_##kind##num) \ goto kind##_found; \ } \ slog(st,LOG_SEC,"peer chose unknown-to-us " what " %d!", \ - m.capab_##kind##num); \ + m->capab_##kind##num); \ return False; \ kind##_found: \ st->chosen_##kind=iface; \ @@ -956,7 +964,7 @@ kind##_found: \ #undef CHOSE_CRYPTO - if (!process_msg3_msg4(st,&m)) + if (!process_msg3_msg4(st,m)) return False; /* Update our idea of the remote site's capabilities, now that we've @@ -967,46 +975,46 @@ kind##_found: \ * doesn't change any of the bits we relied upon in the past, but it may * also have set additional capability bits. We simply throw those away * now, and use the authentic capabilities from this MSG3. */ - st->remote_capabilities=m.remote_capabilities; + st->remote_capabilities=m->remote_capabilities; /* Terminate their DH public key with a '0' */ - m.pk[m.pklen]=0; + m->pk[m->pklen]=0; /* Invent our DH secret key */ st->random->generate(st->random->st,st->dh->len,st->dhsecret); /* Generate the shared key and set up the transform */ - if (!set_new_transform(st,m.pk)) return False; + if (!set_new_transform(st,m->pk)) return False; return True; } -static bool_t generate_msg4(struct site *st) +static bool_t generate_msg4(struct site *st, const struct msg *prompt) { /* We have both nonces, their public key and our private key. Generate our public key, sign it and send it to them. */ - return generate_msg(st,LABEL_MSG4,"site:MSG4"); + return generate_msg(st,LABEL_MSG4,"site:MSG4",prompt); } static bool_t process_msg4(struct site *st, struct buffer_if *msg4, - const struct comm_addr *src) + const struct comm_addr *src, + struct msg *m /* returned */) { - struct msg m; cstring_t err; - if (!unpick_msg(st,LABEL_MSG4,msg4,&m)) return False; - if (!check_msg(st,LABEL_MSG4,&m,&err)) { + if (!unpick_msg(st,LABEL_MSG4,msg4,m)) return False; + if (!check_msg(st,LABEL_MSG4,m,&err)) { slog(st,LOG_SEC,"msg4: %s",err); return False; } - if (!process_msg3_msg4(st,&m)) + if (!process_msg3_msg4(st,m)) return False; /* Terminate their DH public key with a '0' */ - m.pk[m.pklen]=0; + m->pk[m->pklen]=0; /* Generate the shared key and set up the transform */ - if (!set_new_transform(st,m.pk)) return False; + if (!set_new_transform(st,m->pk)) return False; return True; } @@ -1030,7 +1038,7 @@ static bool_t unpick_msg0(struct site *st, struct buffer_if *msg0, /* Leaves transformed part of buffer untouched */ } -static bool_t generate_msg5(struct site *st) +static bool_t generate_msg5(struct site *st, const struct msg *prompt) { cstring_t transform_err; @@ -1096,7 +1104,7 @@ static void create_msg6(struct site *st, struct transform_inst_if *transform, buf_prepend_uint32(&st->buffer,session_id); } -static bool_t generate_msg6(struct site *st) +static bool_t generate_msg6(struct site *st, const struct msg *prompt) { if (!is_transform_valid(st->new_transform)) return False; @@ -1373,7 +1381,7 @@ static void decrement_resolving_count(struct site *st, int by) switch (st->state) { case SITE_RESOLVE: if (transport_compute_setupinit_peers(st,addrs,naddrs,0)) { - enter_new_state(st,SITE_SENTMSG1); + enter_new_state(st,SITE_SENTMSG1,0); } else { /* Can't figure out who to try to to talk to */ slog(st,LOG_SETUP_INIT, @@ -1433,7 +1441,7 @@ static bool_t initiate_key_setup(struct site *st, cstring_t reason, slog(st,LOG_SETUP_INIT,"resolving peer address(es)"); return enter_state_resolve(st); } else if (transport_compute_setupinit_peers(st,0,0,prod_hint)) { - return enter_new_state(st,SITE_SENTMSG1); + return enter_new_state(st,SITE_SENTMSG1,0); } slog(st,LOG_SETUP_INIT,"key exchange failed: no address for peer"); return False; @@ -1587,21 +1595,25 @@ static bool_t enter_state_resolve(struct site *st) return ensure_resolving(st); } -static bool_t enter_new_state(struct site *st, uint32_t next) +static bool_t enter_new_state(struct site *st, uint32_t next, + const struct msg *prompt + /* may be 0 for SENTMSG1 */) { - bool_t (*gen)(struct site *st); + bool_t (*gen)(struct site *st, const struct msg *prompt); int r; slog(st,LOG_STATE,"entering state %s",state_name(next)); switch(next) { case SITE_SENTMSG1: state_assert(st,st->state==SITE_RUN || st->state==SITE_RESOLVE); + if (!kex_init(st)) return False; gen=generate_msg1; st->msg1_crossed_logged = False; break; case SITE_SENTMSG2: state_assert(st,st->state==SITE_RUN || st->state==SITE_RESOLVE || st->state==SITE_SENTMSG1 || st->state==SITE_WAIT); + if (!kex_init(st)) return False; gen=generate_msg2; break; case SITE_SENTMSG3: @@ -1632,7 +1644,7 @@ static bool_t enter_new_state(struct site *st, uint32_t next) if (hacky_par_start_failnow()) return False; - r= gen(st) && send_msg(st); + r= gen(st,prompt) && send_msg(st); hacky_par_end(&r, st->setup_retries, st->setup_retry_interval, @@ -1816,15 +1828,31 @@ static void site_outgoing(void *sst, struct buffer_if *buf) } static bool_t named_for_us(struct site *st, const struct buffer_if *buf_in, - uint32_t type, struct msg *m) + uint32_t type, struct msg *m, + struct priomsg *whynot) /* For packets which are identified by the local and remote names. * If it has our name and our peer's name in it it's for us. */ { struct buffer_if buf[1]; buffer_readonly_clone(buf,buf_in); - return unpick_msg(st,type,buf,m) - && name_matches(&m->remote,st->remotename) - && name_matches(&m->local,st->localname); + + if (!unpick_msg(st,type,buf,m)) { + priomsg_update_fixed(whynot, comm_notify_whynot_unpick, "malformed"); + return False; + } +#define NAME_MATCHES(lr) \ + if (!name_matches(&m->lr, st->lr##name)) { \ + if (priomsg_update_fixed(whynot, comm_notify_whynot_name_##lr, \ + "unknown " #lr " name: ")) { \ + truncmsg_add_packet_string(&whynot->m, m->lr.len, m->lr.name); \ + } \ + return False; \ + } + NAME_MATCHES(remote); + NAME_MATCHES(local ); +#undef NAME_MATCHES + + return True; } static bool_t we_have_priority(struct site *st, const struct msg *m) { @@ -1839,17 +1867,17 @@ static bool_t we_have_priority(struct site *st, const struct msg *m) { static bool_t setup_late_msg_ok(struct site *st, const struct buffer_if *buf_in, uint32_t msgtype, - const struct comm_addr *source) { + const struct comm_addr *source, + struct msg *m /* returned */) { /* For setup packets which seem from their type like they are * late. Maybe they came via a different path. All we do is make * a note of the sending address, iff they look like they are part * of the current key setup attempt. */ - struct msg m; - if (!named_for_us(st,buf_in,msgtype,&m)) + if (!named_for_us(st,buf_in,msgtype,m,0)) /* named_for_us calls unpick_msg which gets the nonces */ return False; - if (!consttime_memeq(m.nR,st->remoteN,NONCELEN) || - !consttime_memeq(m.nL,st->localN, NONCELEN)) + if (!consttime_memeq(m->nR,st->remoteN,NONCELEN) || + !consttime_memeq(m->nL,st->localN, NONCELEN)) /* spoof ? from stale run ? who knows */ return False; transport_setup_msgok(st,source); @@ -1862,7 +1890,8 @@ static bool_t setup_late_msg_ok(struct site *st, this current site instance (and should therefore not be processed by other sites), even if the packet was otherwise ignored. */ static bool_t site_incoming(void *sst, struct buffer_if *buf, - const struct comm_addr *source) + const struct comm_addr *source, + struct priomsg *whynot) { struct site *st=sst; @@ -1870,10 +1899,11 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, uint32_t dest=get_uint32(buf->start); uint32_t msgtype=get_uint32(buf->start+8); - struct msg named_msg; + struct msg msg; + /* initialised by named_for_us, or process_msgN for N!=1 */ if (msgtype==LABEL_MSG1) { - if (!named_for_us(st,buf,msgtype,&named_msg)) + if (!named_for_us(st,buf,msgtype,&msg,whynot)) return False; /* It's a MSG1 addressed to us. Decide what to do about it. */ dump_packet(st,buf,source,True,True); @@ -1881,9 +1911,9 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, st->state==SITE_WAIT) { /* We should definitely process it */ transport_compute_setupinit_peers(st,0,0,source); - if (process_msg1(st,buf,source,&named_msg)) { + if (process_msg1(st,buf,source,&msg)) { slog(st,LOG_SETUP_INIT,"key setup initiated by peer"); - bool_t entered=enter_new_state(st,SITE_SENTMSG2); + bool_t entered=enter_new_state(st,SITE_SENTMSG2,&msg); if (entered && st->addresses && st->local_mobile) /* We must do this as the very last thing, because the resolver callback might reenter us. */ @@ -1897,7 +1927,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* We've just sent a message 1! They may have crossed on the wire. If we have priority then we ignore the incoming one, otherwise we process it as usual. */ - if (we_have_priority(st,&named_msg)) { + if (we_have_priority(st,&msg)) { BUF_FREE(buf); if (!st->msg1_crossed_logged++) slog(st,LOG_SETUP_INIT,"crossed msg1s; we are higher " @@ -1906,10 +1936,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, } else { slog(st,LOG_SETUP_INIT,"crossed msg1s; we are lower " "priority => use incoming msg1"); - if (process_msg1(st,buf,source,&named_msg)) { + if (process_msg1(st,buf,source,&msg)) { BUF_FREE(&st->buffer); /* Free our old message 1 */ transport_setup_msgok(st,source); - enter_new_state(st,SITE_SENTMSG2); + enter_new_state(st,SITE_SENTMSG2,&msg); } else { slog(st,LOG_ERROR,"failed to process an incoming " "crossed msg1 (we have low priority)"); @@ -1919,7 +1949,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, } } else if (st->state==SITE_SENTMSG2 || st->state==SITE_SENTMSG4) { - if (consttime_memeq(named_msg.nR,st->remoteN,NONCELEN)) { + if (consttime_memeq(msg.nR,st->remoteN,NONCELEN)) { /* We are ahead in the protocol, but that msg1 had the * peer's nonce so presumably it is from this key * exchange run, via a slower route */ @@ -1937,7 +1967,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, return True; } if (msgtype==LABEL_PROD) { - if (!named_for_us(st,buf,msgtype,&named_msg)) + if (!named_for_us(st,buf,msgtype,&msg,whynot)) return False; dump_packet(st,buf,source,True,True); if (st->state!=SITE_RUN) { @@ -1978,12 +2008,12 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, if (st->state!=SITE_SENTMSG1) { if ((st->state==SITE_SENTMSG3 || st->state==SITE_SENTMSG5) && - setup_late_msg_ok(st,buf,msgtype,source)) + setup_late_msg_ok(st,buf,msgtype,source,&msg)) break; slog(st,LOG_UNEXPECTED,"unexpected MSG2"); - } else if (process_msg2(st,buf,source)) { + } else if (process_msg2(st,buf,source,&msg)) { transport_setup_msgok(st,source); - enter_new_state(st,SITE_SENTMSG3); + enter_new_state(st,SITE_SENTMSG3,&msg); } else { slog(st,LOG_SEC,"invalid MSG2"); } @@ -1992,12 +2022,12 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG2 */ if (st->state!=SITE_SENTMSG2) { if ((st->state==SITE_SENTMSG4) && - setup_late_msg_ok(st,buf,msgtype,source)) + setup_late_msg_ok(st,buf,msgtype,source,&msg)) break; slog(st,LOG_UNEXPECTED,"unexpected MSG3"); - } else if (process_msg3(st,buf,source,msgtype)) { + } else if (process_msg3(st,buf,source,msgtype,&msg)) { transport_setup_msgok(st,source); - enter_new_state(st,SITE_SENTMSG4); + enter_new_state(st,SITE_SENTMSG4,&msg); } else { slog(st,LOG_SEC,"invalid MSG3"); } @@ -2006,12 +2036,12 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG3 */ if (st->state!=SITE_SENTMSG3) { if ((st->state==SITE_SENTMSG5) && - setup_late_msg_ok(st,buf,msgtype,source)) + setup_late_msg_ok(st,buf,msgtype,source,&msg)) break; slog(st,LOG_UNEXPECTED,"unexpected MSG4"); - } else if (process_msg4(st,buf,source)) { + } else if (process_msg4(st,buf,source,&msg)) { transport_setup_msgok(st,source); - enter_new_state(st,SITE_SENTMSG5); + enter_new_state(st,SITE_SENTMSG5,&msg); } else { slog(st,LOG_SEC,"invalid MSG4"); } @@ -2026,7 +2056,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, if (st->state==SITE_SENTMSG4) { if (process_msg5(st,buf,source,st->new_transform)) { transport_setup_msgok(st,source); - enter_new_state(st,SITE_RUN); + enter_new_state(st,SITE_RUN,&msg); } else { slog(st,LOG_SEC,"invalid MSG5"); } @@ -2066,6 +2096,8 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, return True; } + priomsg_update_fixed(whynot, comm_notify_whynot_general, + "not MSG1 or PROD; unknown dest index"); return False; } @@ -2101,6 +2133,17 @@ static void site_childpersist_clearkeys(void *sst, uint32_t newphase) crypto operations, but that's a task for another day. */ } +static void setup_sethash(struct site *st, dict_t *dict, + struct hash_if **hash, struct cloc loc, + sig_sethash_fn *sethash, void *sigkey_st) { + if (!*hash) *hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc); + sethash(sigkey_st,*hash); +} +#define SETUP_SETHASH(k) do{ \ + if ((k)->sethash) \ + setup_sethash(st,dict, &hash,loc, (k)->sethash,(k)->st); \ +}while(0) + static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, list_t *args) { @@ -2193,6 +2236,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc); st->random=find_cl_if(dict,"random",CL_RANDOMSRC,True,"site",loc); + struct hash_if *hash=0; st->privkey=find_cl_if(dict,"local-key",CL_SIGPRIVKEY,True,"site",loc); st->addresses=dict_read_string_array(dict,"address",False,"site",loc,0); if (st->addresses) @@ -2203,7 +2247,9 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, GET_CLOSURE_LIST("transform",transforms,ntransforms,CL_TRANSFORM); st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc); - st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc); + + SETUP_SETHASH(st->privkey); + SETUP_SETHASH(st->pubkey); #define DEFAULT(D) (st->peer_mobile || st->local_mobile \ ? DEFAULT_MOBILE_##D : DEFAULT_##D)