chiark / gitweb /
Support expiry of other peers' public keys.
[tripe] / keyexch.c
index 1eb6981aa4e3a524819399dd15cc7b3e0d11188d..c17f4009f95d54f9c199bdfbb31ee50666ebed94 100644 (file)
--- a/keyexch.c
+++ b/keyexch.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: keyexch.c,v 1.2 2001/02/16 21:24:27 mdw Exp $
+ * $Id: keyexch.c,v 1.4 2001/06/22 19:40:36 mdw Exp $
  *
  * Key exchange protocol
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: keyexch.c,v $
+ * Revision 1.4  2001/06/22 19:40:36  mdw
+ * Support expiry of other peers' public keys.
+ *
+ * Revision 1.3  2001/06/19 22:07:09  mdw
+ * Cosmetic fixes.
+ *
  * Revision 1.2  2001/02/16 21:24:27  mdw
  * Rewrite for new key exchange protocol.
  *
@@ -163,7 +169,6 @@ static void kxc_stoptimer(kxchal *kxc)
 /* --- @kxc_new@ --- *
  *
  * Arguments:  @keyexch *kx@ = pointer to key exchange block
- *             @
  *
  * Returns:    A pointer to the challenge block.
  *
@@ -535,12 +540,14 @@ static void resend(keyexch *kx)
 
   switch (kx->s) {
     case KXS_CHAL:
-      T( trace(T_KEYEXCH, "sending prechallenge to `%s'", p_name(kx->p)); )
+      T( trace(T_KEYEXCH, "keyexch: sending prechallenge to `%s'",
+              p_name(kx->p)); )
       b = p_txstart(kx->p, MSG_KEYEXCH | KX_PRECHAL);
       buf_putmp(b, kx->c);
       break;
     case KXS_COMMIT:
-      T( trace(T_KEYEXCH, "sending switch request to `%s'", p_name(kx->p)); )
+      T( trace(T_KEYEXCH, "keyexch: sending switch request to `%s'",
+              p_name(kx->p)); )
       kxc = kx->r[0];
       b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCH);
       buf_put(b, kx->hc, HASHSZ);
@@ -552,7 +559,7 @@ static void resend(keyexch *kx)
       ks_encrypt(kxc->ks, &bb, b);
       break;
     case KXS_SWITCH:
-      T( trace(T_KEYEXCH, "sending switch confirmation to `%s'",
+      T( trace(T_KEYEXCH, "keyexch: sending switch confirmation to `%s'",
               p_name(kx->p)); )
       kxc = kx->r[0];
       b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCHOK);
@@ -843,6 +850,9 @@ static void stop(keyexch *kx)
 {
   unsigned i;
 
+  if (kx->f & KXF_DEAD)
+    return;
+
   if (kx->f & KXF_TIMER)
     sel_rmtimer(&kx->t);
   for (i = 0; i < kx->nr; i++)
@@ -850,6 +860,9 @@ static void stop(keyexch *kx)
   mp_drop(kx->alpha);
   mp_drop(kx->c);
   mp_drop(kx->rx);
+  kx->t_valid = 0;
+  kx->f |= KXF_DEAD;
+  kx->f &= ~KXF_TIMER;
 }
 
 /* --- @start@ --- *
@@ -867,8 +880,10 @@ static void start(keyexch *kx, time_t now)
 {
   HASH_CTX h;
 
+  assert(kx->f & KXF_DEAD);
+
+  kx->f &= ~KXF_DEAD;
   kx->nr = 0;
-  kx->f = 0;
   kx->alpha = mprand_range(MP_NEW, kpriv.dp.q, &rand_global, 0);
   kx->c = mpmont_exp(&mg, MP_NEW, kpriv.dp.g, kx->alpha);
   kx->rx = mpmont_exp(&mg, MP_NEW, kx->kpub.y, kx->alpha);
@@ -891,6 +906,32 @@ static void start(keyexch *kx, time_t now)
   })
 }
 
+/* --- @checkpub@ --- *
+ *
+ * Arguments:  @keyexch *kx@ = pointer to key exchange context
+ *
+ * Returns:    Zero if OK, nonzero if the peer's public key has expired.
+ *
+ * Use:                Deactivates the key-exchange until the peer acquires a new
+ *             public key.
+ */
+
+static int checkpub(keyexch *kx)
+{
+  time_t now;
+  if (kx->f & KXF_DEAD)
+    return (-1);
+  now = time(0);
+  if (KEY_EXPIRED(now, kx->texp_kpub)) {
+    stop(kx);
+    a_warn("public key for `%s' has expired", p_name(kx->p));
+    dh_pubfree(&kx->kpub);
+    kx->f &= ~KXF_PUBKEY;
+    return (-1);
+  }
+  return (0);
+}
+
 /* --- @kx_start@ --- *
  *
  * Arguments:  @keyexch *kx@ = pointer to key exchange context
@@ -906,6 +947,8 @@ void kx_start(keyexch *kx)
 {
   time_t now = time(0);
 
+  if (checkpub(kx))
+    return;
   if (!ISVALID(kx, now)) {
     stop(kx);
     start(kx, now);
@@ -939,6 +982,9 @@ void kx_message(keyexch *kx, unsigned msg, buf *b)
   };
 #endif
 
+  if (checkpub(kx))
+    return;
+
   if (!ISVALID(kx, now)) {
     stop(kx);
     start(kx, now);
@@ -989,7 +1035,8 @@ void kx_message(keyexch *kx, unsigned msg, buf *b)
 void kx_free(keyexch *kx)
 {
   stop(kx);
-  dh_pubfree(&kx->kpub);
+  if (kx->f & KXF_PUBKEY)
+    dh_pubfree(&kx->kpub);
 }
 
 /* --- @kx_newkeys@ --- *
@@ -1008,15 +1055,18 @@ void kx_newkeys(keyexch *kx)
 {
   dh_pub dp;
 
-  if (km_getpubkey(p_name(kx->p), &dp))
+  if (km_getpubkey(p_name(kx->p), &dp, &kx->texp_kpub))
     return;
-  dh_pubfree(&kx->kpub);
+  if (kx->f & KXF_PUBKEY)
+    dh_pubfree(&kx->kpub);
   kx->kpub = dp;
-  if (kx->s != KXS_SWITCH) {
+  kx->f |= KXF_PUBKEY;
+  if ((kx->f & KXF_DEAD) || kx->s != KXS_SWITCH) {
     T( trace(T_KEYEXCH, "keyexch: restarting key negotiation with `%s'",
             p_name(kx->p)); )
-    kx->t_valid = 0;
-    kx_start(kx);
+    stop(kx);
+    start(kx, time(0));
+    resend(kx);
   }
 }
 
@@ -1037,8 +1087,9 @@ int kx_init(keyexch *kx, peer *p, keyset **ks)
 {
   kx->ks = ks;
   kx->p = p;
-  if (km_getpubkey(p_name(p), &kx->kpub))
+  if (km_getpubkey(p_name(p), &kx->kpub, &kx->texp_kpub))
     return (-1);
+  kx->f = KXF_DEAD | KXF_PUBKEY;
   start(kx, time(0));
   resend(kx);
   return (0);