chiark / gitweb /
site: fix site name checking leaving room for expansion
[secnet.git] / site.c
diff --git a/site.c b/site.c
index 566b215d3bcc416fd4ff80d5b70213cf5b557cc8..2e8335ae634bb297035f2761f0ec6a4ecb06810e 100644 (file)
--- a/site.c
+++ b/site.c
@@ -347,14 +347,19 @@ static bool_t current_valid(struct site *st)
     type=buf_unprepend_uint32((b)); \
     if (type!=(t)) return False; } while(0)
 
+struct parsedname {
+    int32_t len;
+    uint8_t *name;
+    int32_t extrainfo_len;
+    uint8_t *extrainfo;
+};
+
 struct msg {
     uint8_t *hashstart;
     uint32_t dest;
     uint32_t source;
-    int32_t remlen;
-    uint8_t *remote;
-    int32_t loclen;
-    uint8_t *local;
+    struct parsedname remote;
+    struct parsedname local;
     uint8_t *nR;
     uint8_t *nL;
     int32_t pklen;
@@ -402,6 +407,24 @@ static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what)
     return True;
 }
 
+static bool_t unpick_name(struct buffer_if *msg, struct parsedname *nm)
+{
+    CHECK_AVAIL(msg,2);
+    nm->len=buf_unprepend_uint16(msg);
+    CHECK_AVAIL(msg,nm->len);
+    nm->name=buf_unprepend(msg,nm->len);
+    uint8_t *nul=memchr(nm->name,0,nm->len);
+    if (!nul) {
+       nm->extrainfo_len=0;
+       nm->extrainfo=0;
+    } else {
+       nm->extrainfo=nul+1;
+       nm->extrainfo_len=msg->start-nm->extrainfo;
+       nm->len=nul-nm->name;
+    }
+    return True;
+}
+
 static bool_t unpick_msg(struct site *st, uint32_t type,
                         struct buffer_if *msg, struct msg *m)
 {
@@ -411,14 +434,8 @@ static bool_t unpick_msg(struct site *st, uint32_t type,
     CHECK_AVAIL(msg,4);
     m->source=buf_unprepend_uint32(msg);
     CHECK_TYPE(msg,type);
-    CHECK_AVAIL(msg,2);
-    m->remlen=buf_unprepend_uint16(msg);
-    CHECK_AVAIL(msg,m->remlen);
-    m->remote=buf_unprepend(msg,m->remlen);
-    CHECK_AVAIL(msg,2);
-    m->loclen=buf_unprepend_uint16(msg);
-    CHECK_AVAIL(msg,m->loclen);
-    m->local=buf_unprepend(msg,m->loclen);
+    if (!unpick_name(msg,&m->remote)) return False;
+    if (!unpick_name(msg,&m->local)) return False;
     CHECK_AVAIL(msg,NONCELEN);
     m->nR=buf_unprepend(msg,NONCELEN);
     if (type==LABEL_MSG1) {
@@ -444,6 +461,14 @@ static bool_t unpick_msg(struct site *st, uint32_t type,
     return True;
 }
 
+static bool_t name_matches(const struct parsedname *nm, const char *expected)
+{
+    int expected_len=strlen(expected);
+    return
+       nm->len == expected_len &&
+       !memcmp(nm->name, expected, expected_len);
+}    
+
 static bool_t check_msg(struct site *st, uint32_t type, struct msg *m,
                        cstring_t *error)
 {
@@ -451,11 +476,11 @@ static bool_t check_msg(struct site *st, uint32_t type, struct msg *m,
 
     /* Check that the site names and our nonce have been sent
        back correctly, and then store our peer's nonce. */ 
-    if (memcmp(m->remote,st->remotename,strlen(st->remotename)!=0)) {
+    if (!name_matches(&m->remote,st->remotename)) {
        *error="wrong remote site name";
        return False;
     }
-    if (memcmp(m->local,st->localname,strlen(st->localname)!=0)) {
+    if (!name_matches(&m->local,st->localname)) {
        *error="wrong local site name";
        return False;
     }
@@ -566,7 +591,7 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3,
 
     /* Set up the transform */
     st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
-                             st->sharedsecretlen);
+                             st->sharedsecretlen,st->setup_priority);
 
     return True;
 }
@@ -613,7 +638,7 @@ static bool_t process_msg4(struct site *st, struct buffer_if *msg4,
                       st->sharedsecret,st->sharedsecretlen);
     /* Set up the transform */
     st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
-                             st->sharedsecretlen);
+                             st->sharedsecretlen,st->setup_priority);
 
     return True;
 }
@@ -731,7 +756,8 @@ static bool_t process_msg6(struct site *st, struct buffer_if *msg6,
     return True;
 }
 
-static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0)
+static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0,
+                          const struct comm_addr *src)
 {
     cstring_t transform_err, auxkey_err, newkey_err="n/a";
     struct msg0 m;
@@ -750,11 +776,8 @@ static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0)
                           "peer has used new key","auxiliary key",LOG_SEC);
        return True;
     }
-
-    if (problem==2) {
-       slog(st,LOG_DROP,"transform: %s (merely skew)",transform_err);
-       return False;
-    }
+    if (problem==2)
+       goto skew;
 
     buffer_copy(msg0, &st->scratch);
     problem = st->auxiliary_key.transform->reverse
@@ -778,11 +801,14 @@ static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0)
        }
        return True;
     }
+    if (problem==2)
+       goto skew;
 
     if (st->state==SITE_SENTMSG5) {
        buffer_copy(msg0, &st->scratch);
-       if (!st->new_transform->reverse(st->new_transform->st,
-                                       msg0,&newkey_err)) {
+       problem = st->new_transform->reverse(st->new_transform->st,
+                                            msg0,&newkey_err);
+       if (!problem) {
            /* It looks like we didn't get the peer's MSG6 */
            /* This is like a cut-down enter_new_state(SITE_RUN) */
            slog(st,LOG_STATE,"will enter state RUN (MSG0 with new key)");
@@ -791,11 +817,18 @@ static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0)
            activate_new_key(st);
            return True; /* do process the data in this packet */
        }
+       if (problem==2)
+           goto skew;
     }
 
     slog(st,LOG_SEC,"transform: %s (aux: %s, new: %s)",
         transform_err,auxkey_err,newkey_err);
     initiate_key_setup(st,"incoming message would not decrypt");
+    send_nak(src,m.dest,m.source,m.type,msg0,"message would not decrypt");
+    return False;
+
+ skew:
+    slog(st,LOG_DROP,"transform: %s (merely skew)",transform_err);
     return False;
 }
 
@@ -804,7 +837,7 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0,
 {
     uint32_t type;
 
-    if (!decrypt_msg0(st,msg0))
+    if (!decrypt_msg0(st,msg0,src))
        return False;
 
     CHECK_AVAIL(msg0,4);
@@ -1286,7 +1319,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf,
        uint32_t msgtype=ntohl(get_uint32(buf->start+8));
        if (msgtype!=LABEL_MSG0) dump_packet(st,buf,source,True);
        switch (msgtype) {
-       case 0: /* NAK */
+       case LABEL_NAK:
            /* If the source is our current peer then initiate a key setup,
               because our peer's forgotten the key */
            if (get_uint32(buf->start+4)==st->current.remote_session_id) {