chiark / gitweb /
Allow different peer associations to use different private keys.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 25 Jan 2012 23:49:47 +0000 (23:49 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 7 May 2012 14:35:11 +0000 (15:35 +0100)
Add a `peertag' slot to the `peerspec' structure stating which private
key to use; a null pointer means to use the default `tag_priv'.  Add a
`p_privtag' function to retrieve the private key tag to use.

The ADD command now has a `-priv' option which sets this slot
appropriately.  The `connect' service fetches a `priv' key. from the
database to set this option.

peerdb/peers.in.5.in
py/tripe.py.in
server/admin.c
server/keyexch.c
server/peer.c
server/tripe-admin.5.in
server/tripe.h
svc/connect.in

index c876365..48f69b3 100644 (file)
@@ -188,6 +188,9 @@ Network address for this peer, or
 Used by
 .BR connect (8).
 .TP
+.B priv
+Tag of the private key to use when communicating with the peer.
+.TP
 .B raddr
 Remote address for the tunnel interface to the peer.  Used by
 .BR tripe-ifup (8).
index 78a305b..c2b430b 100644 (file)
@@ -831,7 +831,8 @@ class TripeCommandDispatcher (TripeConnection):
     return _simple(me.command(bg = True,
                               *['ADD'] +
                               _kwopts(kw, ['tunnel', 'keepalive',
-                                           'key', 'cork', 'mobile']) +
+                                           'key', 'priv', 'cork',
+                                           'mobile']) +
                               [peer] +
                               list(addr)))
   def addr(me, peer):
index 0fb57cd..0e3effb 100644 (file)
@@ -1250,6 +1250,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
   add = xmalloc(sizeof(*add));
   add->peer.name = 0;
   add->peer.tag = 0;
+  add->peer.privtag = 0;
   add->peer.t_ka = 0;
   add->peer.tops = tun_default;
   add->peer.f = 0;
@@ -1279,6 +1280,11 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
       add->peer.tag = xstrdup(arg);
     })
     OPT("-mobile", { add->peer.f |= PSF_MOBILE; })
+    OPTARG("-priv", arg, {
+      if (add->peer.privtag)
+       xfree(add->peer.privtag);
+      add->peer.privtag = xstrdup(arg);
+    })
   });
 
   /* --- Make sure someone's not got there already --- */
@@ -1304,6 +1310,7 @@ bad_syntax:
 fail:
   if (add->peer.name) xfree(add->peer.name);
   if (add->peer.tag) xfree(add->peer.tag);
+  if (add->peer.privtag) xfree(add->peer.privtag);
   xfree(add);
   return;
 }
@@ -1828,7 +1835,10 @@ static void acmd_peerinfo(admin *a, unsigned ac, char *av[])
   if ((p = a_findpeer(a, av[0])) != 0) {
     ps = p_spec(p);
     a_info(a, "tunnel=%s", ps->tops->name, A_END);
-    a_info(a, "key=%s", p_tag(p), A_END);
+    a_info(a, "key=%s", p_tag(p),
+          "current-key=%s", p->kx.kpub->tag, A_END);
+    a_info(a, "private-key=%s", p_privtag(p),
+          "current-private-key=%s", p->kx.kpriv->tag, A_END);
     a_info(a, "keepalive=%lu", ps->t_ka, A_END);
     a_ok(a);
   }
index 1527a29..50a85f6 100644 (file)
@@ -1383,11 +1383,11 @@ newkeys:
 
 int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f)
 {
-  if ((kx->kpriv = km_findpriv(tag_priv)) == 0) goto fail_0;
+  if ((kx->kpriv = km_findpriv(p_privtag(p))) == 0) goto fail_0;
   if ((kx->kpub = km_findpub(p_tag(p))) == 0) goto fail_1;
-  if (!km_samealgsp(kx->kpriv, kx->kpub)) {
-    a_warn("KX", "?PEER", kx->p, "algorithms-mismatch",
-          "local-private-key", "%s", tag_priv,
+  if (!group_samep(kx->kpriv->g, kx->kpub->g)) {
+    a_warn("KX", "?PEER", kx->p, "group-mismatch",
+          "local-private-key", "%s", p_privtag(p),
           "peer-public-key", "%s", p_tag(p),
           A_END);
     goto fail_2;
index 308ab1d..75f7acb 100644 (file)
@@ -820,6 +820,7 @@ unsigned p_port(void)
 static void p_keepalive(struct timeval *now, void *pv)
 {
   peer *p = pv;
+
   p_txstart(p, MSG_MISC | MISC_NOP); p_dotxend(p);
   T( trace(T_PEER, "peer: sent keepalive to %s", p->spec.name); )
   p_setkatimer(p);
@@ -871,8 +872,8 @@ peer *p_create(peerspec *spec)
   T( trace(T_PEER, "peer: creating new peer `%s'", spec->name); )
   p->spec = *spec;
   p->spec.name = (/*unconst*/ char *)SYM_NAME(p->byname);
-  if (spec->tag)
-    p->spec.tag = xstrdup(spec->tag);
+  if (spec->tag) p->spec.tag = xstrdup(spec->tag);
+  if (spec->privtag) p->spec.privtag = xstrdup(spec->privtag);
   p->ks = 0;
   p->pings = 0;
   p->ifname = 0;
@@ -902,8 +903,7 @@ peer *p_create(peerspec *spec)
   return (p);
 
 tidy_4:
-  if (spec->t_ka)
-    sel_rmtimer(&p->tka);
+  if (spec->t_ka) sel_rmtimer(&p->tka);
   xfree(p->ifname);
   p->t->ops->destroy(p->t);
 tidy_3:
@@ -911,6 +911,7 @@ tidy_3:
 tidy_2:
   am_remove(&byaddr, p->byaddr);
   if (p->spec.tag) xfree(p->spec.tag);
+  if (p->spec.privtag) xfree(p->spec.privtag);
 tidy_1:
   sym_remove(&byname, p->byname);
 tidy_0:
@@ -938,6 +939,16 @@ const char *p_name(peer *p)
 const char *p_tag(peer *p)
   { return (p->spec.tag ? p->spec.tag : p->spec.name); }
 
+/* --- @p_privtag@ --- *
+ *
+ * Arguments:  @peer *p@ = pointer to a peer block
+ *
+ * Returns:    A pointer to the peer's private key tag.
+ */
+
+const char *p_privtag(peer *p)
+  { return (p->spec.privtag ? p->spec.privtag : tag_priv); }
+
 /* --- @p_spec@ --- *
  *
  * Arguments:  @peer *p@ = pointer to a peer block
@@ -1002,15 +1013,12 @@ void p_destroy(peer *p)
   a_notify("KILL", "%s", p->spec.name, A_END);
   ksl_free(&p->ks);
   kx_free(&p->kx);
-  if (p->spec.f & PSF_MOBILE)
-    nmobile--;
-  if (p->ifname)
-    xfree(p->ifname);
-  if (p->spec.tag)
-    xfree(p->spec.tag);
+  if (p->spec.f & PSF_MOBILE) nmobile--;
+  if (p->ifname) xfree(p->ifname);
+  if (p->spec.tag) xfree(p->spec.tag);
+  if (p->spec.privtag) xfree(p->spec.privtag);
   p->t->ops->destroy(p->t);
-  if (p->spec.t_ka)
-    sel_rmtimer(&p->tka);
+  if (p->spec.t_ka) sel_rmtimer(&p->tka);
   for (pg = p->pings; pg; pg = ppg) {
     ppg = pg->next;
     p_pingdone(pg, PING_PEERDIED);
index a27179d..6ffa6cd 100644 (file)
@@ -546,10 +546,22 @@ The keepalive interval, in seconds, or zero if no keepalives are to be
 sent.
 .TP
 .B key
-The key tag being used for the peer, as passed to the
+The (short) key tag being used for the peer, as passed to the
 .B ADD
-command.  (You don't get a full key-id, since that might change while
-the daemon's running.)
+command.
+.TP
+.B current-key
+The full key tag of the peer's public key currently being used.  This
+may change during the life of the association.
+.TP
+.B private-key
+The private key tag being used for the peer, as passed to the
+.B ADD
+command.
+.TP
+.B current-private-key
+The full key tag of the private key currently being used for this
+association.  This may change during the life of the association.
 .RE
 .SP
 .BI "PING \fR[" options "\fR] " peer
index b22dccc..b4eee1b 100644 (file)
@@ -353,6 +353,7 @@ typedef struct stats {
 
 typedef struct peerspec {
   char *name;                          /* Peer's name */
+  char *privtag;                       /* Private key tag */
   char *tag;                           /* Public key tag */
   const tunnel_ops *tops;              /* Tunnel operations */
   unsigned long t_ka;                  /* Keep alive interval */
@@ -1330,6 +1331,15 @@ extern const char *p_name(peer */*p*/);
 
 extern const char *p_tag(peer */*p*/);
 
+/* --- @p_privtag@ --- *
+ *
+ * Arguments:  @peer *p@ = pointer to a peer block
+ *
+ * Returns:    A pointer to the peer's private key tag.
+ */
+
+extern const char *p_privtag(peer */*p*/);
+
 /* --- @p_spec@ --- *
  *
  * Arguments:  @peer *p@ = pointer to a peer block
index 0ae539f..5f8940e 100644 (file)
@@ -92,6 +92,7 @@ def addpeer(peer, addr):
           tunnel = peer.get('tunnel', None),
           keepalive = peer.get('keepalive', None),
           key = peer.get('key', None),
+          priv = peer.get('priv', None),
           mobile = peer.get('mobile', 'nil') in booltrue,
           cork = peer.get('cork', 'nil') in booltrue,
           *addr)