Disassociate public key tags from peer names.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 17 May 2010 16:14:09 +0000 (17:14 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 17 May 2010 23:15:42 +0000 (00:15 +0100)
Peer names are being used for too much now.  Originally, they /only/
identified the public key.  The peer management services muddy the issue
greatly by mapping peer names to database records.

I propose to resolve this mess in favour of the peer management
services.  The ADD command now takes an optional argument naming the
public key to use to authenticate the peer (defaulting to the peer name,
as before).  The `connect' service consults the peer database to find
which key to pass to the server.

This change modifies the server to support a new `-key' option to ADD,
and use the value of this option in preference to the peer name if it's
supplied.  It also updates the `connect' service to use this option if
necessary.  Finally, there's documentation of the various protocol and
database structure changes, and a small tweak to the test suite to make
sure the whole thing stands a chance of working.

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

index 59bee45..ad7faed 100644 (file)
@@ -166,6 +166,10 @@ Local address for the tunnel interface to the peer.  Used by
 Interval for sending keepalive pings.  Used by
 .BR connect (8).
 .TP
+.B key
+Key tag to use to authenticate the peer.  Used by
+.BR connect (8).
+.TP
 .B mtu
 Maximum transmission unit for the tunnel interface.  Used by
 .BR tripe-ifup (8).
index f556bae..37de5a4 100644 (file)
@@ -830,7 +830,8 @@ class TripeCommandDispatcher (TripeConnection):
   def add(me, peer, *addr, **kw):
     return _simple(me.command(bg = True,
                               *['ADD'] +
-                              _kwopts(kw, ['tunnel', 'keepalive', 'cork']) +
+                              _kwopts(kw, ['tunnel', 'keepalive',
+                                           'key', 'cork']) +
                               [peer] +
                               list(addr)))
   def addr(me, peer):
index a62bbe2..a339167 100644 (file)
@@ -1205,6 +1205,7 @@ static void a_doadd(admin_resop *r, int rc)
       a_bgok(&add->r.bg);
   }
 
+  if (add->peer.tag) xfree(add->peer.tag);
   xfree(add->peer.name);
 }
 
@@ -1228,6 +1229,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.t_ka = 0;
   add->peer.tops = tun_default;
   add->peer.kxf = 0;
@@ -1251,6 +1253,11 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
     })
     OPTTIME("-keepalive", t, { add->peer.t_ka = t; })
     OPT("-cork", { add->peer.kxf |= KXF_CORK; })
+    OPTARG("-key", arg, {
+      if (add->peer.tag)
+       xfree(add->peer.tag);
+      add->peer.tag = xstrdup(arg);
+    })
   });
 
   /* --- Make sure someone's not got there already --- */
@@ -1275,6 +1282,7 @@ bad_syntax:
   a_fail(a, "bad-syntax", "add", "[OPTIONS] PEER ADDR ...", A_END);
 fail:
   if (add->peer.name) xfree(add->peer.name);
+  if (add->peer.tag) xfree(add->peer.tag);
   xfree(add);
   return;
 }
@@ -1785,6 +1793,7 @@ 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", ps->tag, A_END);
     a_info(a, "keepalive=%lu", ps->t_ka, A_END);
     a_ok(a);
   }
index 6490dd7..d007a43 100644 (file)
@@ -1235,7 +1235,7 @@ void kx_free(keyexch *kx)
 
 void kx_newkeys(keyexch *kx)
 {
-  if (km_getpubkey(p_name(kx->p), kx->kpub, &kx->texp_kpub))
+  if (km_getpubkey(p_tag(kx->p), kx->kpub, &kx->texp_kpub))
     return;
   kx->f |= KXF_PUBKEY;
   if ((kx->f & KXF_DEAD) || kx->s != KXS_SWITCH) {
@@ -1266,7 +1266,7 @@ int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f)
   kx->ks = ks;
   kx->p = p;
   kx->kpub = G_CREATE(gg);
-  if (km_getpubkey(p_name(p), kx->kpub, &kx->texp_kpub)) {
+  if (km_getpubkey(p_tag(p), kx->kpub, &kx->texp_kpub)) {
     G_DESTROY(gg, kx->kpub);
     return (-1);
   }
index 4bb2c82..456efd7 100644 (file)
@@ -737,6 +737,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);
   p->ks = 0;
   p->pings = 0;
   p->ifname = 0;
@@ -773,6 +775,7 @@ tidy_3:
   if (fd >= 0) close(fd);
 tidy_2:
   am_remove(&byaddr, p->byaddr);
+  if (p->spec.tag) xfree(p->spec.tag);
 tidy_1:
   sym_remove(&byname, p->byname);
 tidy_0:
@@ -789,6 +792,16 @@ tidy_0:
 
 const char *p_name(peer *p) { return (p->spec.name); }
 
+/* --- @p_tag@ --- *
+ *
+ * Arguments:  @peer *p@ = pointer to a peer block
+ *
+ * Returns:    A pointer to the peer's public key tag.
+ */
+
+const char *p_tag(peer *p)
+  { return (p->spec.tag ? p->spec.tag : p->spec.name); }
+
 /* --- @p_spec@ --- *
  *
  * Arguments:  @peer *p@ = pointer to a peer block
@@ -853,6 +866,8 @@ void p_destroy(peer *p)
   kx_free(&p->kx);
   if (p->ifname)
     xfree(p->ifname);
+  if (p->spec.tag)
+    xfree(p->spec.tag);
   p->t->ops->destroy(p->t);
   if (p->spec.t_ka)
     sel_rmtimer(&p->tka);
index 393a661..38961e1 100644 (file)
@@ -224,24 +224,25 @@ WITH_2TRIPES([alice], [bob], [-nslip], [-talice], [-tbob], [
   AT_CHECK([TRIPECTL -dalice ADD bob INET 127.0.0.1 $(cat bob/port)])
   echo >>bob/expected-server-output \
     "WARN PEER - unexpected-source INET 127.0.0.1 $(cat alice/port)"
-  AT_CHECK([TRIPECTL -dbob ADD alice INET 127.0.0.1 $(cat alice/port)])
+  AT_CHECK([TRIPECTL -dbob ADD -key alice not-alice \
+                              INET 127.0.0.1 $(cat alice/port)])
 
   ## Check transport pinging.
   AT_CHECK([TRIPECTL -dalice PING bob],, [ignore])
-  AT_CHECK([TRIPECTL -dbob PING alice],, [ignore])
+  AT_CHECK([TRIPECTL -dbob PING not-alice],, [ignore])
 
   ## Wait for the completion announcement.
   wait
 
   ## Check encrypted pinging.
   AT_CHECK([TRIPECTL -dalice EPING bob],, [ignore])
-  AT_CHECK([TRIPECTL -dbob EPING alice],, [ignore])
+  AT_CHECK([TRIPECTL -dbob EPING not-alice],, [ignore])
 
   ## Check that packets can flow from one to the other.
   AT_CHECK([echo "from alice" | USLIP -p alice/bob])
-  AT_CHECK([USLIP -g bob/alice],, [from alice[]nl])
+  AT_CHECK([USLIP -g bob/not-alice],, [from alice[]nl])
 
-  AT_CHECK([echo "from bob" | USLIP -p bob/alice])
+  AT_CHECK([echo "from bob" | USLIP -p bob/not-alice])
   AT_CHECK([USLIP -g alice/bob],, [from bob[]nl])
 ])
 
index 826d0f4..e921cfc 100644 (file)
@@ -348,6 +348,12 @@ or
 for days, hours, minutes, or seconds respectively; if no suffix is
 given, seconds are assumed.
 .TP
+.BI "\-key " tag
+Use the public key
+.I tag
+to authenticate the peer.  The default is to use the key tagged
+.IR peer .
+.TP
 .BI "\-tunnel " tunnel
 Use the named tunnel driver, rather than the default.
 .\"-opts
@@ -523,6 +529,12 @@ The tunnel driver used for this peer.
 .B keepalive
 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
+.B ADD
+command.  (You don't get a full key-id, since that might change while
+the daemon's running.)
 .RE
 .SP
 .BI "PING \fR[" options "\fR] " peer
index 2b6f950..a210e52 100644 (file)
@@ -333,6 +333,7 @@ typedef struct stats {
 
 typedef struct peerspec {
   char *name;                          /* Peer's name */
+  char *tag;                           /* Public key tag */
   const tunnel_ops *tops;              /* Tunnel operations */
   unsigned long t_ka;                  /* Keep alive interval */
   addr sa;                             /* Socket address to speak to */
@@ -1249,6 +1250,15 @@ extern peer *p_create(peerspec */*spec*/);
 
 extern const char *p_name(peer */*p*/);
 
+/* --- @p_tag@ --- *
+ *
+ * Arguments:  @peer *p@ = pointer to a peer block
+ *
+ * Returns:    A pointer to the peer's public key tag.
+ */
+
+extern const char *p_tag(peer */*p*/);
+
 /* --- @p_spec@ --- *
  *
  * Arguments:  @peer *p@ = pointer to a peer block
index 77357f5..ddd2636 100644 (file)
@@ -172,6 +172,8 @@ The service will submit the command
 .RB [ \-cork ]
 .RB [ \-keepalive
 .IR time ]
+.RB [ \-key
+.IR tag ]
 .RB [ \-tunnel
 .IR driver ]
 .I address
@@ -200,6 +202,15 @@ to the
 key.
 .hP \*o
 The option
+.B \-key
+.I tag
+is provided if the database record assigns a value
+.I tag
+to the
+.B key
+key.
+.hP \*o
+The option
 .B \-tunnel
 .I driver
 is provided if the database record assigns a value
index dae1162..37241bb 100644 (file)
@@ -90,6 +90,7 @@ def addpeer(peer, addr):
     S.add(peer.name,
           tunnel = peer.get('tunnel', None),
           keepalive = peer.get('keepalive', None),
+          key = peer.get('key', None),
           cork = peer.get('cork', 'nil') in ['t', 'true', 'y', 'yes', 'on'],
           *addr)
   except T.TripeError, exc: