X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=site.c;h=6b09588653aef388ff0c7291b8392908482a5c22;hb=e3f1375768e53a28a4b5e7b965f2f9f3472aab42;hp=51465011d1b6e1aa7a688eeae70d52d72653e1dc;hpb=cbc2519681f5fceab5c6153110215090663eb3e9;p=secnet.git diff --git a/site.c b/site.c index 5146501..6b09588 100644 --- a/site.c +++ b/site.c @@ -321,7 +321,7 @@ struct site { uint32_t local_capabilities; int32_t setup_retries; /* How many times to send setup packets */ int32_t setup_retry_interval; /* Initial timeout for setup packets */ - int32_t wait_timeout; /* How long to wait if setup unsuccessful */ + int32_t wait_timeout_mean; /* How long to wait if setup unsuccessful */ int32_t mobile_peer_expiry; /* How long to remember 2ary addresses */ int32_t key_lifetime; /* How long a key lasts once set up */ int32_t key_renegotiate_time; /* If we see traffic (or a keepalive) @@ -535,6 +535,10 @@ struct msg { char *sig; }; +static int32_t wait_timeout(struct site *st) { + return st->wait_timeout_mean; +} + static _Bool set_new_transform(struct site *st, char *pk) { _Bool ok; @@ -1353,7 +1357,7 @@ static void decrement_resolving_count(struct site *st, int by) } else if (st->local_mobile) { /* Not very good. We should queue (another) renegotiation * so that we can update the peer address. */ - st->key_renegotiate_time=st->now+st->wait_timeout; + st->key_renegotiate_time=st->now+wait_timeout(st); } else { slog(st,LOG_SETUP_INIT,"resolution failed: " " continuing to use source address of peer's packets"); @@ -1628,7 +1632,7 @@ static bool_t send_msg7(struct site *st, cstring_t reason) static void enter_state_wait(struct site *st) { slog(st,LOG_STATE,"entering state WAIT"); - st->timeout=st->now+st->wait_timeout; + st->timeout=st->now+wait_timeout(st); st->state=SITE_WAIT; set_link_quality(st); BUF_FREE(&st->buffer); /* will have had an outgoing packet in it */ @@ -1778,6 +1782,26 @@ static bool_t we_have_priority(struct site *st, const struct msg *m) { return st->our_name_later; } +static bool_t setup_late_msg_ok(struct site *st, + const struct buffer_if *buf_in, + uint32_t msgtype, + const struct comm_addr *source) { + /* 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)) + /* 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)) + /* spoof ? from stale run ? who knows */ + return False; + transport_setup_msgok(st,source); + return True; +} + /* This function is called by the communication device to deliver packets from our peers. It should return True if the packet is recognised as being for @@ -1839,9 +1863,21 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, BUF_FREE(buf); return True; } + } else if (st->state==SITE_SENTMSG2 || + st->state==SITE_SENTMSG4) { + if (consttime_memeq(named_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 */ + transport_setup_msgok(st,source); + } else { + slog(st,LOG_UNEXPECTED,"competing incoming message 1"); + } + BUF_FREE(buf); + return True; } /* The message 1 was received at an unexpected stage of the - key setup. XXX POLICY - what do we do? */ + key setup. Well, they lost the race. */ slog(st,LOG_UNEXPECTED,"unexpected incoming message 1"); BUF_FREE(buf); return True; @@ -1886,6 +1922,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, case LABEL_MSG2: /* Setup packet: expected only in state SENTMSG1 */ if (st->state!=SITE_SENTMSG1) { + if ((st->state==SITE_SENTMSG3 || + st->state==SITE_SENTMSG5) && + setup_late_msg_ok(st,buf,msgtype,source)) + break; slog(st,LOG_UNEXPECTED,"unexpected MSG2"); } else if (process_msg2(st,buf,source)) { transport_setup_msgok(st,source); @@ -1898,6 +1938,9 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, case LABEL_MSG3BIS: /* 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)) + break; slog(st,LOG_UNEXPECTED,"unexpected MSG3"); } else if (process_msg3(st,buf,source,msgtype)) { transport_setup_msgok(st,source); @@ -1909,6 +1952,9 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, case LABEL_MSG4: /* 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)) + break; slog(st,LOG_UNEXPECTED,"unexpected MSG4"); } else if (process_msg4(st,buf,source)) { transport_setup_msgok(st,source); @@ -2112,7 +2158,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->key_lifetime= CFG_NUMBER("key-lifetime", KEY_LIFETIME); st->setup_retries= CFG_NUMBER("setup-retries", SETUP_RETRIES); st->setup_retry_interval= CFG_NUMBER("setup-timeout", SETUP_RETRY_INTERVAL); - st->wait_timeout= CFG_NUMBER("wait-time", WAIT_TIME); + st->wait_timeout_mean= CFG_NUMBER("wait-time", WAIT_TIME); st->mtu_target= dict_read_number(dict,"mtu-target",False,"site",loc,0); st->mobile_peer_expiry= dict_read_number(