From 48b845698dcf3ec4b9f8b9f1848a157f0245d7cc Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 17 May 2010 17:14:09 +0100 Subject: [PATCH] Disassociate public key tags from peer names. 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 | 4 ++++ py/tripe.py.in | 3 ++- server/admin.c | 9 +++++++++ server/keyexch.c | 4 ++-- server/peer.c | 15 +++++++++++++++ server/tests.at | 11 ++++++----- server/tripe-admin.5.in | 12 ++++++++++++ server/tripe.h | 10 ++++++++++ svc/connect.8.in | 11 +++++++++++ svc/connect.in | 1 + 10 files changed, 72 insertions(+), 8 deletions(-) diff --git a/peerdb/peers.in.5.in b/peerdb/peers.in.5.in index 59bee454..ad7faeda 100644 --- a/peerdb/peers.in.5.in +++ b/peerdb/peers.in.5.in @@ -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). diff --git a/py/tripe.py.in b/py/tripe.py.in index f556bae5..37de5a40 100644 --- a/py/tripe.py.in +++ b/py/tripe.py.in @@ -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): diff --git a/server/admin.c b/server/admin.c index a62bbe22..a339167c 100644 --- a/server/admin.c +++ b/server/admin.c @@ -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); } diff --git a/server/keyexch.c b/server/keyexch.c index 6490dd73..d007a434 100644 --- a/server/keyexch.c +++ b/server/keyexch.c @@ -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); } diff --git a/server/peer.c b/server/peer.c index 4bb2c82c..456efd77 100644 --- a/server/peer.c +++ b/server/peer.c @@ -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); diff --git a/server/tests.at b/server/tests.at index 393a6616..38961e1d 100644 --- a/server/tests.at +++ b/server/tests.at @@ -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]) ]) diff --git a/server/tripe-admin.5.in b/server/tripe-admin.5.in index 826d0f44..e921cfcf 100644 --- a/server/tripe-admin.5.in +++ b/server/tripe-admin.5.in @@ -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 diff --git a/server/tripe.h b/server/tripe.h index 2b6f950a..a210e526 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -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 diff --git a/svc/connect.8.in b/svc/connect.8.in index 77357f52..ddd2636b 100644 --- a/svc/connect.8.in +++ b/svc/connect.8.in @@ -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 diff --git a/svc/connect.in b/svc/connect.in index dae11620..37241bbc 100644 --- a/svc/connect.in +++ b/svc/connect.in @@ -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: -- 2.11.0