chiark / gitweb /
Allow admin clients to filter out async messages. Send notifications
[tripe] / keyexch.c
index 18594cf31414447f1b37e4de6be9ae2e0a6d8a07..7c0217c5ccdae50b69af40e7fb20af3ae1768ccc 100644 (file)
--- a/keyexch.c
+++ b/keyexch.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: keyexch.c,v 1.13 2004/04/18 18:08:11 mdw Exp $
+ * $Id$
  *
  * Key exchange protocol
  *
@@ -72,7 +72,7 @@
  *     Challenge accpeted: here's the answer.  Commit to my challenge.  Move
  *     to @KXS_COMMIT@.
  *
- * %$\cookie{kx-switch}, c_A, c_B, E_K(r_B^\alpha, w_A))$%
+ * %$\cookie{kx-switch-rq}, c_A, c_B, E_K(r_B^\alpha, w_A))$%
  *     Reply received: here's my reply.  Committed; send data; move to
  *     @KXS_SWITCH@.
  *
 #define T_VALID MIN(2)                 /* Challenge validity period */
 #define T_RETRY SEC(10)                        /* Challenge retransmit interval */
 
-#define ISVALID(kx, now) ((now) < (kx)->t_valid)
+#define VALIDP(kx, now) ((now) < (kx)->t_valid)
+
+/*----- Static tables -----------------------------------------------------*/
+
+static const char *const pkname[] = {
+  "pre-challenge", "cookie", "challenge",
+  "reply", "switch-rq", "switch-ok"
+};
 
 /*----- Various utilities -------------------------------------------------*/
 
@@ -423,7 +430,7 @@ static ge *getreply(keyexch *kx, ge *c, mp *ck)
   G_EXP(gg, y, gg->g, a);
   ok = G_EQ(gg, y, c);
   if (!ok) {
-    a_warn("invalid expected-reply check from `%s'", p_name(kx->p));
+    a_warn("KX %s bad-expected-reply-log", p_name(kx->p));
     IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
       trace(T_CRYPTO, "crypto: computed challenge = %s", gestr(gg, y));
     }))
@@ -457,7 +464,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
   /* --- Ensure that we're in a sensible state --- */
 
   if (kx->s != KXS_CHAL) {
-    a_warn("unexpected challenge from `%s'", p_name(kx->p));
+    a_warn("KX %s unexpected %s", p_name(kx->p), pkname[msg]);
     goto bad;
   }
 
@@ -467,7 +474,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
       (msg >= KX_COOKIE && (hc = buf_get(b, algs.hashsz)) == 0) ||
       (msg >= KX_CHAL && (ck = buf_getmp(b)) == 0) ||
       BLEFT(b)) {
-    a_warn("malformed packet from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid %s", p_name(kx->p), pkname[msg]);
     goto bad;
   }
 
@@ -484,6 +491,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
 
   if (!hc && kx->nr >= KX_THRESH) {
     T( trace(T_KEYEXCH, "keyexch: too many challenges -- sending cookie"); )
+    a_warn("KX %s sending-cookie", p_name(kx->p));
     b = p_txstart(kx->p, MSG_KEYEXCH | KX_COOKIE);
     G_TOBUF(gg, b, kx->c);
     h = GH_INIT(algs.h);
@@ -498,7 +506,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
   /* --- Discard a packet with an invalid cookie --- */
 
   if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) {
-    a_warn("incorrect cookie from `%s'", p_name(kx->p));
+    a_warn("KX %s incorrect cookie", p_name(kx->p));
     goto bad;
   }
 
@@ -719,11 +727,11 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in,
     if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck));
   }))
   if (memcmp(hc_out, kx->hc, algs.hashsz) != 0) {
-    a_warn("incorrect cookie from `%s'", p_name(kx->p));
+    a_warn("KX %s incorrect cookie", p_name(kx->p));
     goto bad;
   }
   if ((kxc = kxc_byhc(kx, hc_in)) == 0) {
-    a_warn("received reply for unknown challenge from `%s'", p_name(kx->p));
+    a_warn("KX %s unknown-challenge", p_name(kx->p));
     goto bad;
   }
 
@@ -731,7 +739,7 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in,
 
   if (!kxc->r) {
     if (!ck) {
-      a_warn("unexpected switch request from `%s'", p_name(kx->p));
+      a_warn("KX %s unexpected switch-rq", p_name(kx->p));
       goto bad;
     }
     if ((r = getreply(kx, kxc->c, ck)) == 0)
@@ -744,20 +752,20 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in,
 
   buf_init(&bb, buf_o, sizeof(buf_o));
   if (ks_decrypt(kxc->ks, ty, b, &bb)) {
-    a_warn("failed to decrypt reply from `%s'", p_name(kx->p));
+    a_warn("KX %s decrypt-failed reply", p_name(kx->p));
     goto bad;
   }
   buf_init(b, BBASE(&bb), BLEN(&bb));
   r = G_CREATE(gg);
   if (G_FROMBUF(gg, b, r)) {
-    a_warn("invalid reply packet from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid reply", p_name(kx->p));
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
     trace(T_CRYPTO, "crypto: reply = %s", gestr(gg, r));
   }))
   if (!G_EQ(gg, r, kx->rx)) {
-    a_warn("incorrect reply from `%s'", p_name(kx->p));
+    a_warn("KX %s incorrect reply", p_name(kx->p));
     goto bad;
   }
 
@@ -814,20 +822,20 @@ static int doreply(keyexch *kx, buf *b)
   kxchal *kxc;
 
   if (kx->s != KXS_CHAL && kx->s != KXS_COMMIT) {
-    a_warn("unexpected reply from `%s'", p_name(kx->p));
+    a_warn("KX %s unexpected-reply", p_name(kx->p));
     goto bad;
   }
   if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
       (hc_out = buf_get(b, algs.hashsz)) == 0 ||
       (ck = buf_getmp(b)) == 0) {
-    a_warn("invalid reply packet from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid reply", p_name(kx->p));
     goto bad;
   }
   if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_REPLY,
                        hc_in, hc_out, ck, b)) == 0)
     goto bad;
   if (BLEFT(b)) {
-    a_warn("invalid reply packet from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid reply", p_name(kx->p));
     goto bad;
   }
   if (kx->s == KXS_CHAL) {
@@ -842,6 +850,25 @@ bad:
   return (-1);
 }
 
+/* --- @kxfinish@ --- *
+ *
+ * Arguments:  @keyexch *kx@ = pointer to key exchange block
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets everything up following a successful key exchange.
+ */
+
+static void kxfinish(keyexch *kx)
+{
+  kxchal *kxc = kx->r[0];
+  ks_activate(kxc->ks);
+  settimer(kx, ks_tregen(kxc->ks));
+  kx->s = KXS_SWITCH;
+  a_notify("KXDONE %s", p_name(kx->p));
+  p_stats(kx->p)->t_kx = time(0);
+}
+
 /* --- @doswitch@ --- *
  *
  * Arguments:  @keyexch *kx@ = pointer to key exchange block
@@ -859,30 +886,28 @@ static int doswitch(keyexch *kx, buf *b)
 
   if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
       (hc_out = buf_get(b, algs.hashsz)) == 0) {
-    a_warn("invalid switch request from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid switch-rq", p_name(kx->p));
     goto bad;
   }
   if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_SWITCH,
                        hc_in, hc_out, 0, b)) == 0)
     goto bad;
   if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
-    a_warn("invalid switch request from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid switch-rq", p_name(kx->p));
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, {
     trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, algs.hashsz);
   })
   if (memcmp(hswrq, kxc->hswrq_in, algs.hashsz) != 0) {
-    a_warn("incorrect switch request hash from `%s'", p_name(kx->p));
+    a_warn("KX %s incorrect switch-rq", p_name(kx->p));
     goto bad;
   }
   switch (kx->s) {
     case KXS_CHAL:
       commit(kx, kxc);
     case KXS_COMMIT:
-      ks_activate(kxc->ks);
-      settimer(kx, ks_tregen(kxc->ks));
-      kx->s = KXS_SWITCH;
+      kxfinish(kx);
       break;
   }
   resend(kx);
@@ -909,18 +934,18 @@ static int doswitchok(keyexch *kx, buf *b)
   buf bb;
 
   if (kx->s < KXS_COMMIT) {
-    a_warn("unexpected switch confirmation from `%s'", p_name(kx->p));
+    a_warn("KX %s unexpected switch-ok", p_name(kx->p));
     goto bad;
   }
   kxc = kx->r[0];
   buf_init(&bb, buf_o, sizeof(buf_o));
   if (ks_decrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, b, &bb)) {
-    a_warn("failed to decrypt switch confirmation from `%s'", p_name(kx->p));
+    a_warn("KX %s decrypt-failed switch-ok", p_name(kx->p));
     goto bad;
   }
   buf_init(b, BBASE(&bb), BLEN(&bb));
   if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
-    a_warn("invalid switch confirmation from `%s'", p_name(kx->p));
+    a_warn("KX %s invalid switch-ok", p_name(kx->p));
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, {
@@ -928,14 +953,11 @@ static int doswitchok(keyexch *kx, buf *b)
                hswok, algs.hashsz);
   })
   if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) {
-    a_warn("incorrect switch confirmation hash from `%s'", p_name(kx->p));
+    a_warn("KX %s incorrect switch-ok", p_name(kx->p));
     goto bad;
   }
-  if (kx->s < KXS_SWITCH) {
-    ks_activate(kxc->ks);
-    settimer(kx, ks_tregen(kxc->ks));
-    kx->s = KXS_SWITCH;
-  }
+  if (kx->s < KXS_SWITCH)
+    kxfinish(kx);
   return (0);
 
 bad:
@@ -1037,7 +1059,7 @@ static int checkpub(keyexch *kx)
   now = time(0);
   if (KEY_EXPIRED(now, kx->texp_kpub)) {
     stop(kx);
-    a_warn("public key for `%s' has expired", p_name(kx->p));
+    a_warn("KX %s public-key-expired", p_name(kx->p));
     G_COPY(gg, kx->kpub, gg->i);
     kx->f &= ~KXF_PUBKEY;
     return (-1);
@@ -1062,9 +1084,10 @@ void kx_start(keyexch *kx)
 
   if (checkpub(kx))
     return;
-  if (!ISVALID(kx, now)) {
+  if (!VALIDP(kx, now)) {
     stop(kx);
     start(kx, now);
+    a_notify("KXSTART %s", p_name(kx->p));
   }
   resend(kx);
 }
@@ -1088,17 +1111,10 @@ void kx_message(keyexch *kx, unsigned msg, buf *b)
   size_t sz = BSZ(b);
   int rc;
 
-#ifndef NTRACE
-  static const char *const pkname[] = {
-    "prechallenge", "cookie", "challenge",
-    "reply", "switch request", "switch confirmation"
-  };
-#endif
-
   if (checkpub(kx))
     return;
 
-  if (!ISVALID(kx, now)) {
+  if (!VALIDP(kx, now)) {
     stop(kx);
     start(kx, now);
   }
@@ -1122,8 +1138,7 @@ void kx_message(keyexch *kx, unsigned msg, buf *b)
       rc = doswitchok(kx, b);
       break;
     default:
-      a_warn("unexpected key exchange message type %u from `%p'",
-            p_name(kx->p));
+      a_warn("KX %s unknown-message 0x%02x", p_name(kx->p), msg);
       rc = -1;
       break;
   }
@@ -1202,6 +1217,7 @@ int kx_init(keyexch *kx, peer *p, keyset **ks)
   kx->f = KXF_DEAD | KXF_PUBKEY;
   start(kx, time(0));
   resend(kx);
+  a_notify("KXSTART %s", p_name(kx->p));
   return (0);
 }