From 3cdc3f3a27e8c4f4fe692009d868c773d298a68c Mon Sep 17 00:00:00 2001 Message-Id: <3cdc3f3a27e8c4f4fe692009d868c773d298a68c.1713496821.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sat, 30 Apr 2005 19:01:12 +0000 Subject: [PATCH] Allow admin clients to filter out async messages. Send notifications about interesting events. Rewrite all the messages to be more easily machine-readable and document them all. Fix the Ethereal dissector for the new Ethereal, and fix the build system for the new autotools. Organization: Straylight/Edgeware From: mdw --- .links | 5 - Makefile.am | 5 +- acconfig.h | 78 ------ admin.c | 439 +++++++++++++++++++++++-------- client.c | 54 +++- configure.in | 47 ++-- debian/control | 2 +- doc/protocol.ms | 103 ++++---- doc/tmac.rfc | 31 ++- doc/tripe-admin.5 | 564 ++++++++++++++++++++++++++++++++++++---- doc/tripe.8 | 5 + ethereal/packet-tripe.c | 105 ++++---- keyexch.c | 102 +++++--- keymgmt.c | 38 +-- keyset.c | 6 +- mallory.c | 16 +- peer.c | 34 ++- setup | 2 +- tripe-init.in | 29 ++- tripe.c | 16 +- tripe.h | 30 ++- tun-bsd.c | 8 +- tun-linux.c | 9 +- tun-unet.c | 12 +- 24 files changed, 1232 insertions(+), 508 deletions(-) delete mode 100644 acconfig.h diff --git a/.links b/.links index c017eca8..5ecd9c64 100644 --- a/.links +++ b/.links @@ -1,6 +1 @@ COPYING -install-sh -mkinstalldirs -missing -config.sub -config.guess diff --git a/Makefile.am b/Makefile.am index b45927eb..cb7455a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ## -*-makefile-*- ## -## $Id: Makefile.am,v 1.10 2004/04/08 01:36:17 mdw Exp $ +## $Id$ ## ## Makefile for TrIPE ## @@ -43,11 +43,10 @@ tripe_SOURCES = \ keymgmt.c keyexch.c keyset.c \ servutil.c util.c util.h EXTRA_tripe_SOURCES = \ - tun-unet.c tun-bsd.c + tun-unet.c tun-bsd.c tun-linux.c tripe_LDADD = $(CATACOMB_LIBS) tripectl_SOURCES = \ client.c util.c util.h - tun-unet.c tun-bsd.c tripe_mitm_SOURCES = \ mallory.c tripe_mitm_LDADD = $(CATACOMB_LIBS) diff --git a/acconfig.h b/acconfig.h deleted file mode 100644 index a36ff8e0..00000000 --- a/acconfig.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*-c-*- - * - * $Id: acconfig.h,v 1.6 2004/04/08 01:36:17 mdw Exp $ - * - * Configuration header for TrIPE - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Trivial IP Encryption (TrIPE). - * - * TrIPE is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * TrIPE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with TrIPE; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef ACCONFIG_H -#define ACCONFIG_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Autoconfiguration data --------------------------------------------*/ -@TOP@ - -/* Package and version number. */ -#define PACKAGE "tripe" -#define VERSION "1.0.0" - -/* Define to disable the tracing options. This might improve performance a - * little bit, and can prevent sensitive information from being leaked if - * you're in the habit of typing things like `tripectl trace A' by - * accident. */ -#undef NTRACE - -/* Define according to the type of tunneling interface appropriate for your - * system. Linux types should say `TUN_LINUX' for the TUN/TAP driver if - * using kernel 2.4.0 or later, or say `TUN_UNET' for 2.2-series kernels and - * build the `usernet' module. BSD types should say `TUN_BSD' to use the - * built-in `tun' devices. */ -#undef TUN_TYPE - -/* Define this to your default configuration directory. This is where - * tripe searches for keys and other stuff. */ -#define CONFIGDIR "." - -/* Define this to the directory in which tripe's admin socket is to be - * placed. Common choices are `.' -- the tripe configuration directory -- - * and /var/run. */ -#define SOCKETDIR "." - -/* Define if your Ethereal plugin headers are broken (e.g., Debian 3.0) but - * you're running some sensible ELF system, and I should try to bodge around - * the damage. */ -#undef ETHEREAL_BUGGERED - -@BOTTOM@ - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/admin.c b/admin.c index b95db51c..0213996a 100644 --- a/admin.c +++ b/admin.c @@ -50,6 +50,14 @@ const trace_opt tr_opts[] = { unsigned tr_flags = 0; #endif +static const trace_opt w_opts[] = { + { 't', AF_TRACE, "trace messages" }, + { 'n', AF_NOTE, "asynchronous notifications" }, + { 'w', AF_WARN, "warnings" }, + { 'A', AF_ALLMSGS, "all of the above" }, + { 0, 0, 0 } +}; + /*----- Static variables --------------------------------------------------*/ static admin *admins; @@ -70,6 +78,23 @@ static void a_unlock(admin */*a*/); /*----- Output functions --------------------------------------------------*/ +/* --- @mystrieq@ --- * + * + * Arguments: @const char *x, *y@ = two strings + * + * Returns: True if @x@ and @y are equal, up to case. + */ + +static int mystrieq(const char *x, const char *y) +{ + for (;;) { + if (!*x && !*y) return (1); + if (tolower((unsigned char)*x) != tolower((unsigned char)*y)) + return (0); + x++; y++; + } +} + /* --- @trywrite@ --- * * * Arguments: @admin *a@ = pointer to an admin block @@ -100,8 +125,7 @@ again: goto again; if (errno != EAGAIN && errno != EWOULDBLOCK) { a_destroy(a); - a_warn("disconnecting admin client due to write errors: %s", - strerror(errno)); + a_warn("ADMIN client-read-error -- %s", strerror(errno)); return (-1); } } @@ -204,10 +228,12 @@ static void a_flush(int fd, unsigned mode, void *v) /*----- Utility functions -------------------------------------------------*/ -/* --- @a_write@ --- * +/* --- @a_write@, @a_vwrite@ --- * * * Arguments: @admin *a@ = admin connection to write to + * @const char *tag@ = tag prefix string, or null * @const char *fmt@ = pointer to format string + * @va_list ap@ = arguments in list * @...@ = other arguments * * Returns: --- @@ -215,17 +241,124 @@ static void a_flush(int fd, unsigned mode, void *v) * Use: Sends a message to an admin connection. */ -static void a_write(admin *a, const char *fmt, ...) +static void a_vwrite(admin *a, const char *tag, const char *fmt, va_list ap) { - va_list ap; dstr d = DSTR_INIT; + if (tag) { + dstr_puts(&d, tag); + if (fmt) + dstr_putc(&d, ' '); + } + if (fmt) + dstr_vputf(&d, fmt, &ap); + dstr_putc(&d, '\n'); + dosend(a, d.buf, d.len); + dstr_destroy(&d); +} + +static void a_write(admin *a, const char *tag, const char *fmt, ...) +{ + va_list ap; va_start(ap, fmt); - dstr_vputf(&d, fmt, &ap); + a_vwrite(a, tag, fmt, ap); va_end(ap); - dosend(a, d.buf, d.len); +} + +/* --- @a_ok@, @a_info@, @a_fail@ --- * + * + * Arguments: @admin *a@ = connection + * @const char *fmt@ = format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Convenience functions for @a_write@. + */ + +static void a_ok(admin *a) { a_write(a, "OK", 0); } + +static void a_info(admin *a, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + a_vwrite(a, "INFO", fmt, ap); + va_end(ap); +} + +static void a_fail(admin *a, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + a_vwrite(a, "FAIL", fmt, ap); + va_end(ap); +} + +/* --- @a_alert@, @a_valert@, @a_rawalert@ --- * + * + * Arguments: @unsigned f_and, f_eq@ = filter for connections + * @const char *tag@ = tag prefix string + * @const char *fmt@ = pointer to format string + @ @const char *p@ = pointer to raw string + * @size_t sz@ = size of raw string + * @va_list ap@ = arguments in list + * @...@ = other arguments + * + * Returns: --- + * + * Use: Write a message to all admin connections matched by the given + * filter. + */ + +static void a_rawalert(unsigned f_and, unsigned f_eq, const char *tag, + const char *p, size_t sz) +{ + admin *a, *aa; + dstr d = DSTR_INIT; + + if (!(flags & F_INIT)) + return; + if (tag) { + dstr_puts(&d, tag); + if (p) + dstr_putc(&d, ' '); + } + if (p) + dstr_putm(&d, p, sz); + dstr_putc(&d, '\n'); + p = d.buf; + sz = d.len; + for (a = admins; a; a = aa) { + aa = a->next; + if ((a->f & f_and) == f_eq) + dosend(a, d.buf, d.len); + } dstr_destroy(&d); } +static void a_valert(unsigned f_and, unsigned f_eq, const char *tag, + const char *fmt, va_list ap) +{ + dstr d = DSTR_INIT; + + if (!(flags & F_INIT)) + return; + if (fmt) + dstr_vputf(&d, fmt, &ap); + a_rawalert(f_and, f_eq, tag, fmt ? d.buf : 0, fmt ? d.len : 0); + dstr_destroy(&d); +} + +#if 0 /*unused*/ +static void a_alert(unsigned f_and, unsigned f_eq, const char *tag, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + a_valert(f_and, f_eq, tag, fmt, ap); + va_end(ap); +} +#endif + /* --- @a_warn@ --- * * * Arguments: @const char *fmt@ = pointer to format string @@ -239,24 +372,16 @@ static void a_write(admin *a, const char *fmt, ...) void a_warn(const char *fmt, ...) { va_list ap; - admin *a, *aa; - dstr d = DSTR_INIT; - if (flags & F_INIT) - dstr_puts(&d, "WARN "); va_start(ap, fmt); - dstr_vputf(&d, fmt, &ap); - va_end(ap); - if (!(flags & F_INIT)) - moan("%s", d.buf); + if (flags & F_INIT) + a_valert(0, 0, "WARN", fmt, ap); else { - dstr_putc(&d, '\n'); - for (a = admins; a; a = aa) { - aa = a->next; - dosend(a, d.buf, d.len); - } + fprintf(stderr, "%s: ", QUIS); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); } - dstr_destroy(&d); + va_end(ap); } /* --- @a_trace@ --- * @@ -267,26 +392,36 @@ void a_warn(const char *fmt, ...) * * Returns: --- * - * Use: Custom trace output handler. + * Use: Custom trace output handler. Sends trace messages to + * interested admin connections. */ #ifndef NTRACE static void a_trace(const char *p, size_t sz, void *v) { - dstr d = DSTR_INIT; - admin *a, *aa; - - dstr_puts(&d, "TRACE "); - dstr_putm(&d, p, sz); - dstr_putc(&d, '\n'); - for (a = admins; a; a = aa) { - aa = a->next; - dosend(a, d.buf, d.len); - } - dstr_destroy(&d); + a_rawalert(AF_TRACE, AF_TRACE, "TRACE", p, sz); } #endif +/* --- @a_notify@ --- * + * + * Arguments: @const char *fmt@ = pointer to format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Sends a notification to interested admin connections. + */ + +void a_notify(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + a_valert(AF_NOTE, AF_NOTE, "NOTE", fmt, ap); + va_end(ap); +} + /* --- @a_quit@ --- * * * Arguments: --- @@ -322,11 +457,11 @@ static void a_sigdie(int sig, void *v) case SIGTERM: p = "SIGTERM"; break; case SIGINT: p = "SIGINT"; break; default: - sprintf(buf, "signal %i", sig); + sprintf(buf, "%i", sig); p = buf; break; } - a_warn("shutting down on %s", p); + a_warn("SERVER quit signal %s", p); a_quit(); } @@ -342,7 +477,7 @@ static void a_sigdie(int sig, void *v) static void a_sighup(int sig, void *v) { - a_warn("received SIGHUP: ignoring"); + a_warn("SERVER ignore signal SIGHUP"); } /*----- Adding peers ------------------------------------------------------*/ @@ -366,15 +501,15 @@ static void a_resolve(struct hostent *h, void *v) TIMER; sel_rmtimer(&a->t); if (!h) - a_write(a, "FAIL couldn't resolve hostname `%s'\n", a->paddr); + a_fail(a, "resolve-error %s", a->paddr); else if (p_find(a->pname)) - a_write(a, "FAIL peer `%s' already registered\n", a->pname); + a_fail(a, "peer-exists %s", a->pname); else { memcpy(&a->peer.sin.sin_addr, h->h_addr, sizeof(struct in_addr)); if (!p_create(a->pname, &a->peer.sa, a->sasz)) - a_write(a, "FAIL couldn't create peer\n"); + a_fail(a, "peer-create-fail %s" a->pname); else - a_write(a, "OK\n"); + a_ok(a); } xfree(a->pname); xfree(a->paddr); @@ -400,7 +535,7 @@ static void a_timer(struct timeval *tv, void *v) a_lock(a); T( trace(T_ADMIN, "admin: %u resolver timeout", a->seq); ) bres_abort(&a->r); - a_write(a, "FAIL timeout resolving `%s'\n", a->paddr); + a_fail(a, "resolver-timeout %s\n", a->paddr); xfree(a->pname); xfree(a->paddr); a->pname = 0; @@ -423,42 +558,49 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) { unsigned long pt; struct timeval tv; + unsigned i; char *p; /* --- Make sure someone's not got there already --- */ if (p_find(av[0])) { - a_write(a, "FAIL peer `%s' already registered\n", av[0]); + a_fail(a, "peer-exists %s", av[0]); return; } /* --- Fill in the easy bits of address --- */ BURN(a->peer); + i = 1; + if (mystrieq(av[i], "inet")) i++; + if (ac - i != 2) { + a_fail(a, "bad-syntax -- add PEER [inet] ADDRESS PORT"); + return; + } a->peer.sin.sin_family = AF_INET; a->sasz = sizeof(a->peer.sin); - pt = strtoul(av[2], &p, 0); + pt = strtoul(av[i + 1], &p, 0); if (*p) { - struct servent *s = getservbyname(av[2], "udp"); + struct servent *s = getservbyname(av[i + 1], "udp"); if (!s) { - a_write(a, "FAIL service `%s' not known\n", av[2]); + a_fail(a, "unknown-service %s", av[i + 1]); return; } pt = ntohs(s->s_port); } if (pt == 0 || pt >= 65536) { - a_write(a, "FAIL bad port number %lu\n", pt); + a_fail(a, "invalid-port %lu", pt); return; } a->peer.sin.sin_port = htons(pt); /* --- If the name is numeric, do it the easy way --- */ - if (inet_aton(av[1], &a->peer.sin.sin_addr)) { + if (inet_aton(av[i], &a->peer.sin.sin_addr)) { if (!p_create(av[0], &a->peer.sa, a->sasz)) - a_write(a, "FAIL couldn't create peer\n"); + a_fail(a, "peer-create-fail %s", a->pname); else - a_write(a, "OK\n"); + a_ok(a); return; } @@ -470,7 +612,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) */ a->pname = xstrdup(av[0]); - a->paddr = xstrdup(av[1]); + a->paddr = xstrdup(av[i]); selbuf_disable(&a->b); gettimeofday(&tv, 0); tv.tv_sec += T_RESOLVE; @@ -484,21 +626,36 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) /* --- Miscellaneous commands --- */ -#ifndef NTRACE +/* --- @traceish@ --- * + * + * Arguments: @admin *a@ = connection to complain on + * @unsigned ac@ = number of arguments + * @char *av[]@ = vector of arguments + * @const char *what@ = what we're messing with + * @const trace_opt *tt@ = options table + * @unsigned *ff@ = where the flags are + * + * Returns: Nonzero if anything changed. + * + * Use: Guts of trace-ish commands like `trace' and `watch'. + */ -static void acmd_trace(admin *a, unsigned ac, char *av[]) +static int traceish(admin *a, unsigned ac, char *av[], + const char *what, const trace_opt *tt, unsigned *ff) { + int ch = 0; + if (!ac || strcmp(av[0], "?") == 0) { const trace_opt *t; - a_write(a, "INFO Trace options:\n"); - for (t = tr_opts; t->ch; t++) { - a_write(a, "INFO %c %c %s\n", - t->ch, (tr_flags & t->f) == t->f ? '*' : ' ', t->help); + a_info(a, "Current %s status:", what); + for (t = tt; t->ch; t++) { + a_info(a, "%c %c %s", + t->ch, (*ff & t->f) == t->f ? '*' : ' ', t->help); } } else { unsigned sense = 1; - unsigned f = tr_flags; - const trace_opt *tt; + unsigned f = *ff; + const trace_opt *t; char *p = av[0]; while (*p) { @@ -506,46 +663,98 @@ static void acmd_trace(admin *a, unsigned ac, char *av[]) case '+': sense = 1; break; case '-': sense = 0; break; default: - for (tt = tr_opts; tt->ch; tt++) { - if (tt->ch == *p) { - if (sense) f |= tt->f; - else f &= ~tt->f; + for (t = tt; t->ch; t++) { + if (t->ch == *p) { + if (sense) f |= t->f; + else f &= ~t->f; goto tropt_ok; } } - a_write(a, "FAIL unknown trace option `%c'\n", *p); - return; + a_fail(a, "bad-%s-option %c", what, *p); + return (0); tropt_ok:; break; } p++; } - tr_flags = f; - trace_level(tr_flags); + *ff = f; + ch = 1; } - a_write(a, "OK\n"); + a_ok(a); + return (ch); +} + +#ifndef NTRACE + +static void acmd_trace(admin *a, unsigned ac, char *av[]) +{ + if (traceish(a, ac, av, "trace", tr_opts, &tr_flags)) + trace_level(tr_flags); } #endif +static void acmd_watch(admin *a, unsigned ac, char *av[]) +{ + traceish(a, ac, av, "watch", w_opts, &a->f); +} + +static void quotify(dstr *d, const char *p) +{ + if (d->len) + dstr_putc(d, ' '); + if (*p && !p[strcspn(p, "\"' \t\n\v")]) + dstr_puts(d, p); + else { + dstr_putc(d, '\"'); + while (*p) { + if (*p == '\\' || *p == '\"') + dstr_putc(d, '\\'); + dstr_putc(d, *p++); + } + dstr_putc(d, '\"'); + } +} + +static void alertcmd(admin *a, unsigned f_and, unsigned f_eq, + const char *tag, unsigned ac, char *av[]) +{ + dstr d = DSTR_INIT; + unsigned i; + + dstr_puts(&d, "USER"); + for (i = 0; i < ac; i++) + quotify(&d, av[i]); + dstr_putz(&d); + a_rawalert(f_and, f_eq, tag, d.buf, d.len); + dstr_destroy(&d); + a_ok(a); +} + +static void acmd_notify(admin *a, unsigned ac, char *av[]) + { alertcmd(a, AF_NOTE, AF_NOTE, "NOTE", ac, av); } +static void acmd_warn(admin *a, unsigned ac, char *av[]) + { alertcmd(a, AF_WARN, AF_WARN, "WARN", ac, av); } + static void acmd_port(admin *a, unsigned ac, char *av[]) { - a_write(a, "INFO %u\nOK\n", p_port()); + a_info(a, "%u", p_port()); + a_ok(a); } static void acmd_daemon(admin *a, unsigned ac, char *av[]) { if (flags & F_DAEMON) - a_write(a, "FAIL already running as a daemon\n"); + a_fail(a, "already-daemon"); else { - a_warn("becoming a daemon"); + a_notify("DAEMON"); if (a_stdin) a_destroy(a_stdin); if (u_daemon()) - a_write(a, "FAIL error becoming a daemon: %s", strerror(errno)); + a_fail(a, "daemon-error -- %s", strerror(errno)); else { flags |= F_DAEMON; - a_write(a, "OK\n"); + a_ok(a); } } } @@ -554,8 +763,8 @@ static void acmd_list(admin *a, unsigned ac, char *av[]) { peer *p; for (p = p_first(); p; p = p_next(p)) - a_write(a, "INFO %s\n", p_name(p)); - a_write(a, "OK\n"); + a_info(a, "%s", p_name(p)); + a_ok(a); } static void acmd_ifname(admin *a, unsigned ac, char *av[]) @@ -563,9 +772,11 @@ static void acmd_ifname(admin *a, unsigned ac, char *av[]) peer *p; if ((p = p_find(av[0])) == 0) - a_write(a, "FAIL peer `%s' not found\n", av[0]); - else - a_write(a, "INFO %s\nOK\n", p_ifname(p)); + a_fail(a, "unknown-peer %s", av[0]); + else { + a_info(a, "%s", p_ifname(p)); + a_ok(a); + } } static void acmd_addr(admin *a, unsigned ac, char *av[]) @@ -574,13 +785,14 @@ static void acmd_addr(admin *a, unsigned ac, char *av[]) const addr *ad; if ((p = p_find(av[0])) == 0) - a_write(a, "FAIL peer `%s' not found\n", av[0]); + a_fail(a, "unknown-peer %s", av[0]); else { ad = p_addr(p); assert(ad->sa.sa_family == AF_INET); - a_write(a, "INFO %s %u\nOK\n", + a_info(a, "INET %s %u", inet_ntoa(ad->sin.sin_addr), (unsigned)ntohs(ad->sin.sin_port)); + a_ok(a); } } @@ -590,24 +802,25 @@ static void acmd_stats(admin *a, unsigned ac, char *av[]) stats *st; if ((p = p_find(av[0])) == 0) - a_write(a, "FAIL peer `%s' not found\n", av[0]); + a_fail(a, "unknown-peer %s", av[0]); else { st = p_stats(p); - a_write(a, "INFO start-time=%s\n", timestr(st->t_start)); - a_write(a, "INFO last-packet-time=%s\n", timestr(st->t_last)); - a_write(a, "INFO packets-in=%lu bytes-in=%lu\n", st->n_in, st->sz_in); - a_write(a, "INFO packets-out=%lu bytes-out=%lu\n", + a_info(a, "start-time=%s", timestr(st->t_start)); + a_info(a, "last-packet-time=%s", timestr(st->t_last)); + a_info(a, "last-keyexch-time=%s", timestr(st->t_kx)); + a_info(a, "packets-in=%lu bytes-in=%lu", st->n_in, st->sz_in); + a_info(a, "packets-out=%lu bytes-out=%lu", st->n_out, st->sz_out); - a_write(a, "INFO keyexch-packets-in=%lu keyexch-bytes-in=%lu\n", + a_info(a, "keyexch-packets-in=%lu keyexch-bytes-in=%lu", st->n_kxin, st->sz_kxin); - a_write(a, "INFO keyexch-packets-out=%lu keyexch-bytes-out=%lu\n", + a_info(a, "keyexch-packets-out=%lu keyexch-bytes-out=%lu", st->n_kxout, st->sz_kxout); - a_write(a, "INFO ip-packets-in=%lu ip-bytes-in=%lu\n", + a_info(a, "ip-packets-in=%lu ip-bytes-in=%lu", st->n_ipin, st->sz_ipin); - a_write(a, "INFO ip-packets-out=%lu ip-bytes-out=%lu\n", + a_info(a, "ip-packets-out=%lu ip-bytes-out=%lu", st->n_ipout, st->sz_ipout); - a_write(a, "INFO rejected-packets=%lu\n", st->n_reject); - a_write(a, "OK\n"); + a_info(a, "rejected-packets=%lu", st->n_reject); + a_ok(a); } } @@ -615,20 +828,26 @@ static void acmd_kill(admin *a, unsigned ac, char *av[]) { peer *p; if ((p = p_find(av[0])) == 0) - a_write(a, "FAIL peer `%s' not found\n", av[0]); + a_fail(a, "unknown-peer %s", av[0]); else { p_destroy(p); - a_write(a, "OK\n"); + a_ok(a); } } static void acmd_quit(admin *a, unsigned ac, char *av[]) { - a_warn("closing down on admin request"); - a_write(a, "OK\n"); + a_warn("SERVER quit admin-request"); + a_ok(a); a_quit(); } +static void acmd_version(admin *a, unsigned ac, char *av[]) +{ + a_info(a, "%s %s", PACKAGE, VERSION); + a_ok(a); +} + /* --- The command table and help --- */ typedef struct acmd { @@ -642,9 +861,13 @@ static void acmd_help(admin */*a*/, unsigned /*ac*/, char */*av*/[]); static const acmd acmdtab[] = { { "help", "help", 0, 0, acmd_help }, + { "version", "version", 0, 0, acmd_version }, #ifndef NTRACE { "trace", "trace [OPTIONS]", 0, 1, acmd_trace }, #endif + { "watch", "watch [OPTIONS]", 0, 1, acmd_watch }, + { "notify", "notify MESSAGE ...", 1, 0xffff, acmd_notify }, + { "warn", "warn MESSAGE ...", 1, 0xffff, acmd_warn }, { "port", "port", 0, 0, acmd_port }, { "daemon", "daemon", 0, 0, acmd_daemon }, { "list", "list", 0, 0, acmd_list }, @@ -652,7 +875,7 @@ static const acmd acmdtab[] = { { "addr", "addr PEER", 1, 1, acmd_addr }, { "stats", "stats PEER", 1, 1, acmd_stats }, { "kill", "kill PEER", 1, 1, acmd_kill }, - { "add", "add PEER ADDR PORT", 3, 3, acmd_add }, + { "add", "add PEER ADDR ...", 2, 0xffff, acmd_add }, { "quit", "quit", 0, 0, acmd_quit }, { 0, 0, 0, 0, 0 } }; @@ -661,8 +884,8 @@ static void acmd_help(admin *a, unsigned ac, char *av[]) { const acmd *c; for (c = acmdtab; c->name; c++) - a_write(a, "INFO %s\n", c->help); - a_write(a, "OK\n"); + a_info(a, "%s", c->help); + a_ok(a); } /*----- Connection handling -----------------------------------------------*/ @@ -781,7 +1004,7 @@ static void a_line(char *p, size_t len, void *vp) { admin *a = vp; const acmd *c; - char *av[4]; + char *av[16]; size_t ac; TIMER; @@ -791,15 +1014,14 @@ static void a_line(char *p, size_t len, void *vp) a_destroy(a); return; } - ac = str_qsplit(p, av, 4, 0, STRF_QUOTE); + ac = str_qsplit(p, av, 16, 0, STRF_QUOTE); if (!ac) return; - for (p = av[0]; *p; p++) *p = tolower((unsigned char)*p); for (c = acmdtab; c->name; c++) { - if (strcmp(av[0], c->name) == 0) { + if (mystrieq(av[0], c->name)) { ac--; if (c->argmin > ac || ac > c->argmax) - a_write(a, "FAIL syntax: %s\n", c->help); + a_fail(a, "bad-syntax -- %s", c->help); else { a_lock(a); c->func(a, ac, av + 1); @@ -808,26 +1030,28 @@ static void a_line(char *p, size_t len, void *vp) return; } } - a_write(a, "FAIL unknown command `%s'\n", av[0]); + a_fail(a, "unknown-command %s", av[0]); } /* --- @a_create@ --- * * * Arguments: @int fd_in, fd_out@ = file descriptors to use + * @unsigned f@ = initial flags to set * * Returns: --- * * Use: Creates a new admin connection. */ -void a_create(int fd_in, int fd_out) +void a_create(int fd_in, int fd_out, unsigned f) { admin *a = CREATE(admin); + T( static unsigned seq = 0; a->seq = seq++; ) T( trace(T_ADMIN, "admin: accepted connection %u", a->seq); ) a->pname = 0; - a->f = 0; + a->f = f; if (fd_in == STDIN_FILENO) a_stdin = a; fdflags(fd_in, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); @@ -864,10 +1088,10 @@ static void a_accept(int fd, unsigned mode, void *v) if ((nfd = accept(fd, (struct sockaddr *)&sun, &sz)) < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK && errno != ECONNABORTED && errno != EPROTO) - a_warn("accept admin connection failed: %s", strerror(errno)); + a_warn("ADMIN accept-error -- %s", strerror(errno)); return; } - a_create(nfd, nfd); + a_create(nfd, nfd, 0); } /* --- @a_daemon@ --- * @@ -963,6 +1187,7 @@ again: sig_add(&s_term, SIGTERM, a_sigdie, 0); sig_add(&s_hup, SIGHUP, a_sighup, 0); + signal(SIGPIPE, SIG_IGN); sigaction(SIGINT, 0, &sa); if (sa.sa_handler != SIG_IGN) sig_add(&s_int, SIGINT, a_sigdie, 0); diff --git a/client.c b/client.c index 7edc790b..314bb87c 100644 --- a/client.c +++ b/client.c @@ -169,7 +169,48 @@ static void uline(char *p, size_t len, void *b) f |= f_uclose; } else { p[len] = '\n'; - write(fd, p, len + 1); + errno = EIO; + if (write(fd, p, len + 1) != len + 1) + moan("write failed: %s", strerror(errno)); + } +} + +static void setup(const char *cmd) +{ + dstr d = DSTR_INIT; + char ch; + char *p, *q; + int n; + + dstr_puts(&d, cmd); + dstr_putc(&d, '\n'); + errno = EIO; /* Relax: be vague */ + if (write(fd, d.buf, d.len) != d.len) { + die(EXIT_FAILURE, "error sending setup command `%s': %s", + cmd, strerror(errno)); + } + dstr_reset(&d); + for (;;) { + n = read(fd, &ch, 1); + if (!n) + die(EXIT_FAILURE, "unexpected EOF during setup"); + if (n < 0) { + die(EXIT_FAILURE, "error receiving reply to `%s': %s", + cmd, strerror(errno)); + } + if (d.len < 256) + dstr_putc(&d, ch); + if (ch == '\n') { + p = d.buf; + q = str_getword(&p); + if (!q) + ; + else if (strcmp(q, "OK") == 0) + return; + else if (strcmp(q, "FAIL") == 0) + die(EXIT_FAILURE, "setup command `%s' failed: %s", cmd, p); + dstr_reset(&d); + } } } @@ -245,7 +286,7 @@ Options in full:\n\ \n\ -D, --daemon Become a background task after connecting.\n\ -d, --directory=DIR Select current directory [default " CONFIGDIR "].\n\ --a, --admin-socket=FILE Select socket to connect to +-a, --admin-socket=FILE Select socket to connect to\n\ [default " SOCKETDIR "/tripesock].\n\ -P, --pidfile=FILE Write process-id to FILE.\n\ \n\ @@ -440,9 +481,12 @@ int main(int argc, char *argv[]) fprintf(pidfp, "%li\n", (long)getpid()); fclose(pidfp); } + signal(SIGPIPE, SIG_IGN); /* --- If we're meant to be interactive, do that --- */ + if (optind == argc) + setup("WATCH -A+tw"); if (!(f & f_noinput) && optind == argc) { sel_state sel; selbuf bu, bs; @@ -460,14 +504,16 @@ int main(int argc, char *argv[]) if (optind < argc) { dstr d = DSTR_INIT; + setup((f & f_warn) ? "WATCH -A+w" : "WATCH -A"); dstr_puts(&d, argv[optind++]); while (optind < argc) { dstr_putc(&d, ' '); dstr_puts(&d, argv[optind++]); } dstr_putc(&d, '\n'); - write(fd, d.buf, d.len); - shutdown(fd, 1); + errno = EIO; + if (write(fd, d.buf, d.len) != d.len || shutdown(fd, 1)) + die(EXIT_FAILURE, "write failed: %s", strerror(errno)); dstr_destroy(&d); f |= f_command; } diff --git a/configure.in b/configure.in index 03ad025c..6163a8d8 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl -*-autoconf-*- dnl -dnl $Id: configure.in,v 1.16 2004/04/19 07:44:16 mdw Exp $ +dnl $Id$ dnl dnl Configuration script for TrIPE dnl @@ -33,6 +33,7 @@ AC_CANONICAL_HOST AC_PROG_MAKE_SET AC_PROG_CC AM_PROG_LIBTOOL +AC_CHECK_HEADERS([stdarg.h]) mdw_GCC_FLAGS([-Wall]) mdw_OPT_TRACE @@ -90,17 +91,20 @@ changequote(,)dnl 2.[4-9].* | 2.[1-9][0-9]*.* | [3-9].* | [1-9][0-9]*.*) changequote([,])dnl tun=linux - AC_DEFINE([TUN_TYPE], [TUN_LINUX]) + AC_DEFINE([TUN_TYPE], [TUN_LINUX], + [Set to the tunnel driver for your OS. See TUN_* in tripe.h.]) ;; *) tun=unet - AC_DEFINE([TUN_TYPE], [TUN_UNET]) + AC_DEFINE([TUN_TYPE], [TUN_UNET], + [Set to the tunnel driver for your OS. See TUN_* in tripe.h.]) ;; esac ;; *bsd*) tun=bsd - AC_DEFINE([TUN_TYPE], [TUN_BSD]) + AC_DEFINE([TUN_TYPE], [TUN_BSD], + [Set to the tunnel driver for your OS. See TUN_* in tripe.h.]) ;; *) AC_MSG_ERROR([Unsupported OS: no tunnel interface available]) @@ -118,14 +122,14 @@ if test "$ethereal" = true -a "$ETHEREAL_PLUGIN_DIR" = unknown; then mdw_cv_ethereal_plugin_dir="failed" ethprefix=none for i in "${prefix}" /usr/local /usr `echo $PATH | tr : " "`; do - if test -x "$i/bin/ethereal"; then + if test -x "$i/bin/tethereal"; then ethprefix=$i break fi done if test "$ethprefix" != none; then - ethbin=$ethprefix/bin/ethereal - ethver=`$ethbin -v | sed 's/^[^ ]* \([0-9A-Za-z.]*\).*$/\1/'` + ethbin=$ethprefix/bin/tethereal + ethver=`$ethbin -v | sed 's/^[^ ]* \([0-9A-Za-z.]*\).*$/\1/;q'` dir=$ethprefix/lib/ethereal/plugins/$ethver if test -d "$dir"; then mdw_cv_ethereal_plugin_dir=$dir @@ -162,10 +166,11 @@ if test "$ethereal" = true; then AC_TRY_COMPILE([ #include #include -#include +#include +#include ], [ dissector_handle_t dh; - dh = creat_dissector_handle(0, 0); + dh = create_dissector_handle(0, 0); ], [bad=false; break]) done if test $bad = false; then @@ -180,26 +185,6 @@ if test "$ethereal" = true; then fi if test "$ethereal" = true; then - AC_CACHE_CHECK([whether the Ethereal headers are broken], - [mdw_cv_ethereal_buggered], [ - CFLAGS="$GLIB_CFLAGS $i" - AC_TRY_COMPILE([ -#include -#include -#include -#include -], [ - G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat) - { - plugin_address_table_init(pat); - } - ], [mdw_cv_ethereal_buggered=no], [mdw_cv_ethereal_buggered=yes]) - CFLAGS=$mdw_CFLAGS - ]) - if test $mdw_cv_ethereal_buggered = yes; then - AC_DEFINE(ETHEREAL_BUGGERED) - fi - ETHEREAL_CFLAGS="$CFLAGS $GLIB_CFLAGS $mdw_cv_ethereal_includes" AC_SUBST(ETHEREAL_CFLAGS) AC_SUBST(ETHEREAL_PLUGIN_DIR) @@ -210,6 +195,10 @@ if test "$ethereal" = false -a "$requireethereal" = true; then AC_MSG_ERROR([failed to configure Ethereal plugin]) fi +AH_TEMPLATE([CONFIGDIR], + [Tripe should look here for keys and other configuration.]) +AH_TEMPLATE([SOCKETDIR], + [Tripe should make its administration socket here.]) mdw_DEFINE_PATHS([ mdw_DEFINE_PATH([CONFIGDIR], [$configdir]) mdw_DEFINE_PATH([SOCKETDIR], [$socketdir]) diff --git a/debian/control b/debian/control index 1fb7fdf7..337580a5 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: net Priority: extra Maintainer: Mark Wooding Build-Depends: catacomb-dev (>= 2.1.0), mlib-dev (>= 2.0.3), - ethereal-dev, debhelper (>= 4.0.2) + tethereal, ethereal-dev (>= 0.10.10), debhelper (>= 4.0.2) Standards-Version: 3.1.1 Package: tripe diff --git a/doc/protocol.ms b/doc/protocol.ms index f02bb1cd..849a6622 100644 --- a/doc/protocol.ms +++ b/doc/protocol.ms @@ -4,53 +4,52 @@ .TL "Straylight/Edgeware" "Mark Wooding" .TL "Request for Comments: XXXX" "Straylight/Edgeware" .TL "" "11 April 2003" - - +. .TT XXXX Wooding "April 2003" \ "TrIPE: The Trivial IP Encryption Protocol" - -.T0 "Status of this Memo" - +. +.TI 0 "Status of this Memo" +.P This memo defines an Experimental Protocol for the Internet community. This memo does not specify an Internet standard of any kind. Discussion and suggestions for improvement are requested. Distribution of this memo is unlimited. - +.P .T0 "Introduction" - +.P TrIPE is a simple protocol which enables IP datagrams (or other data) to be exchanged between a pair of hosts over a hostile network while maintaining the properties of secrecy and authenticity; i.e., that the content of the datagrams cannot be determined by eavesdroppers on the network, and that either endpoint can determine whether a datagram received is an unaltered copy of one that was sent by the other. - +.P While similar services are provided by other protocols (e.g., [IPSEC]), they tend to be very complicated and difficult to analyze (see, for example, [IPSEC-EVAL]). By contrast, TrIPE attempts to get away with doing as little as possible. There are no negotiations to decide which ciphers are to be used: these things are defined in the protocol specification. There is only one key-exchange algorithm defined. - +.P In addition to making analysis easier, a simpler protocol also helps reduce the complexity of implementations: this makes implementation errors less likely, and makes auditing an implementation for security holes a more realistic proposition. - +.P .T0 "Interpretation" - +.P The key words `MUST', `MUST NOT', `REQUIRED', `SHALL', `SHALL NOT', `SHOULD', `SHOULD NOT', `RECOMMENDED', `MAY', and `OPTIONAL' in this document are to be interpreted as described in [REQ]. - +.P .T0 "Protocol overview" - +.P The TrIPE protocol sets up a secure point-to-point channel between two peer hosts, through which IP datagrams may be passed securely. - +.P All TrIPE messages are sent as UDP datagrams. No UDP port has been registered for TrIPE yet. - +.P When a pair of peer hosts are made aware of each other, they begin a key negotiation, using an authenticated Diffie-Hellman key exchange protocol. This enables them to agree a @@ -61,15 +60,14 @@ time, or after they have been used to encrypt a given amount of data, whichever happens first. Before the current keyset expires, a new key negotation is started, so that the peers can seamlessly start using the new keys before the old ones become invalid. - +.P .T1 "Keysets" - +.P A .I keyset is a collection of symmetric keys and associated state information. The items required, and the symbolic names by which they are described in this document are: - .UL .LI .B "Incoming and outgoing encryption keys" @@ -77,13 +75,15 @@ this document are: and .K' c "" ) .LE - +.P .T1 "Key exchange" - - - +. +. +.P .T0 "Data representation and notation" +. .de SD +.P .LS .. .de SM @@ -105,7 +105,7 @@ and .SM "\\$1" "\\$2" "\\$3" .LS 2n .. - +.P We need to deal with a number of data items during the protocol. .if t \{\ Object names are given in @@ -115,32 +115,27 @@ A plain name indicates `our' value; a `primed' name (e.g., .I alpha' ) indicates the peer's corresponding value. If a compound data item name is primed, toggle the primed-ness of the components. - +.P Data objects are given types which determine their representation in protocol messages. Type names are given in .B UPPERCASE . - +.P .T1 "Atomic data items" - .DL .DI OCTET A single octet, representing a value between 0 and 255. - .DI U16 A pair of octets, representing a value between 0 and 65535. The more significant octet appears first. - .DI U32 Four octets, representing a value between 0 and 4294967295. More significant octets appear first. - .DI "STRING \fIn\fR\fB" A string of .I n octets. A .B STRING does not have a numeric value. - .DI MP A nonnegative multiprecision integer. Let .I n @@ -148,11 +143,12 @@ be the integer to be represented, and let .I z be the number of octets required to represent .I n -in base-256 format with no leading zeroes; i.e., if -.I n -= 0, then +in base-256 format with no leading zeroes, except that if +.I n += 0 +then .I z -= 0; otherwise += 1; in other cases, .I z is the unique integer such that .ie t 256\*(^(\fIz\fP\-1\*(^) \(<= \fIn\fP < 256\*(^(\fIz\fP\*(^). @@ -169,17 +165,16 @@ octets which are the base-256 digits of .I n , most significant first. .LE - +.P .T1 "Structured data items" - +.P A .I structure is a compound object which is simply the concatenation of a number of its component objects. Structures are used directly as messages, and indirectly as things to be hashed or encrypted. - +.P The notation - .SD . ST STRUCT . kx-cookie . SR OCTET . 0x11 @@ -187,21 +182,28 @@ The notation . SM STRING 20 hash . LE .LE - +.P indicates that .I msg-cookie consists of the two items - - - - +. +.f +. +.SD +. ST STRUCT . msg-packet +. SR OCTET . 0x00 +. br +payload +. LE +.LE +. .SD . ST STRUCT . kx-prechal . SR OCTET . 0x10 . SM MP . c . LE .LE - +. .SD . ST STRUCT . kx-cookie . SR OCTET . 0x11 @@ -212,31 +214,30 @@ consists of the two items . LE . LE .LE - +.P .T0 "Security considerations" - +.P This memo describes a cryptographic protocol for ensuring secrecy and integrity of communications between network hosts. From this point of view, it is entirely about security. - +.P Before deploying TrIPE on their own systems, administrators ought to satisfy themselves that the cryptographic algorithms used are sufficiently strong for their purposes, and that their implementation of the TrIPE software has come from a trustworthy source. They should also ensure that they have adequate procedures in place for transporting public keys without a risk of them being modified by adversaries. - +.P .T0 "References" - .BS IPSEC-EVAL .BR IPSEC Kent, S., Atkinson, R., `Security Architecture for the Internet Protocol', RFC 2401, November 1998. - +. .BR IPSEC-EVAL Ferguson, N., Schneier, B., `A Cryptographic Evaluation of IPsec', December 1999. - +. .BR REQ Bradner, S., `Key words for use in RFCs to Indicate Requirement Levels', BCP 14, RFC 2119, March 1997. diff --git a/doc/tmac.rfc b/doc/tmac.rfc index 191f4868..03609550 100644 --- a/doc/tmac.rfc +++ b/doc/tmac.rfc @@ -9,6 +9,8 @@ . if \n(.g \{\ . fam P . \} +. ps 10 +. vs 12 .\} .el \{\ . po 0 @@ -57,7 +59,7 @@ .de I .Ff I I "\\$1" "\\$2" .. -.de P +.de PF .Ff P P "\\$1" "\\$2" .. .de C @@ -79,6 +81,19 @@ .Ff (HI I "\\$1" "\\$2" .. . +.\"----- Paragraphs --------------------------------------------------------- +. +.ie t \{\ +. de P +. sp .67 +.. +.\} +.el \{\ +. de P +. sp 1 +.. +.\} +. .\"----- Titling ------------------------------------------------------------ . .\" .TL left right @@ -86,7 +101,7 @@ .de TL .B .tl '\\$1''\\$2' -.P +.PF .. . .\" .TT number author title @@ -102,7 +117,7 @@ .ce \&\\$4 .ps -.P +.PF .fi .in +3m .. @@ -125,7 +140,7 @@ . el \&\\$3.\ \ \c .\} \&\\$2 -.P +.PF .ps .br .. @@ -170,6 +185,7 @@ .\" Puts in the header for a bibliography item. .de BR .ne 2 +.P .ti -\\n(bwu [\\$1]\h'\\n(bwu-\\w'[\\$1]'u'\c .. @@ -259,18 +275,18 @@ .\" .DI name .\" Starts a definition item for `name' .de DI -.br +.P .B \h'-1i'\\$1\c .ie \w'\\$1\h'2n''u<1i \h'1i-\w'\\$1'u'\c .el .br -.P +.PF .. . .\" .LI [tag] .\" Starts a new list item .de LI -.br +.P .ie '\\$1'' .ds LL \\*L .el .ds LL \\$1 \h'-\w'\\*(LL\h'1n''u'\\*(LL\h'1n'\c @@ -281,6 +297,7 @@ .\" .QS .\" Starts a display. .de QS +.P .in +4n .ll -4n .. diff --git a/doc/tripe-admin.5 b/doc/tripe-admin.5 index f762692e..d39866e0 100644 --- a/doc/tripe-admin.5 +++ b/doc/tripe-admin.5 @@ -45,34 +45,125 @@ provides information requested in the command. An .B OK response contains no further data. A .B FAIL -code is followed by a human-readable explanation of why the command +code is followed by a machine-readable explanation of why the command failed. .PP -In addition, there are two types of asynchronous `responses', which +In addition, there are three types of asynchronous messages which aren't associated with any particular command. The .B WARN -response contains a human-readable message warning of an error +message contains a machine-readable message warning of an error encountered while processing a command, unexpected or unusual behaviour by a peer, or a possible attack by an adversary. Under normal conditions, the server shouldn't emit any warnings. The .B TRACE -response contains a human-readable tracing message containing diagnostic +message contains a human-readable tracing message containing diagnostic information. Trace messages are controlled using the .B \-T command-line option to the server, or the .B TRACE administration command (see below). Support for tracing can be disabled when the package is being configured, and may not be available in your -version. -.SS "Command reference" +version. Finally, the +.B NOTE +message is a machine-readable notification about some routine but +interesting event such as creation or destruction of peers. +.PP +The presence of asynchronous messages can be controlled using the +.B WATCH +command. +.SS "Network addresses" +A network address is a sequence of words. The first is a token +identifying the network address family. The length of an address and +the meanings of the subsequent words depend on the address family. +Address family tokens are not case-sensitive on input; on output, they +are always in upper-case. +.PP +At present, only one address family is understood. +.TP +.BI "INET " address " " port +An Internet socket, naming an IPv4 address and UDP port. On output, the +address is always in numeric dotted-quad form, and the port is given as +a plain number. On input, DNS hostnames and symbolic port names are +permitted. Name resolution does not block the main server, but will +block the requesting client. This hopefully makes life simpler for +stupid clients. Complex clients which don't wish to be held up can open +extra connections or do the resolution themselves.) +.PP +If, on input, no recognised address family token is found, the following +words are assumed to represent an +.B INET +address. +.SH "COMMAND REFERENCE" The commands provided are: .TP +.BI "ADD " peer " " address\fR... +Adds a new peer. The peer is given the name +.IR peer ; +the peer's public key is assumed to be in the file +.B keyring.pub +(or whatever alternative file was specified in the +.B \-K +option on the command line). The +.I address +is the network address (see above for the format) at which the peer can +be contacted. +.TP +.BI "ADDR " peer +Emits an +.B INFO +line reporting the IP address and port number stored for +.IR peer . +.TP +.B "DAEMON" +Causes the server to disassociate itself from its terminal and become a +background task. This only works once. A warning is issued. +.TP .B "HELP" Causes the server to emit an .B INFO line for each command it supports. Each line lists the command name, followed by the names of the arguments. This may be helpful as a memory aid for interactive use, or for program clients probing for features. +.TP +.BI "IFNAME " peer +Emits an +.B INFO +line containing the name of the network interface used to collect IP +packets which are to be encrypted and sent to +.IR peer . +Used by configuration scripts so that they can set up routing tables +appropriately after adding new peers. +.TP +.BI "KILL " peer +Causes the server to forget all about +.IR peer . +All keys are destroyed, and no more packets are sent. No notification +is sent to the peer: if it's important that the peer be notified, you +must think of a way to do that yourself. +.TP +.B "LIST" +For each currently-known peer, an +.B INFO +line is written containing the peer's name, as given to +.BR ADD . +.TP +.B "PORT" +Emits an +.B INFO +line containing just the number of the UDP port used by the +.B tripe +server. If you've allowed your server to allocate a port dynamically, +this is how to find out which one it chose. +.TP +.B "QUIT" +Instructs the server to exit immediately. A warning is sent. +.TP +.BI "STATS " peer +Emits a number of +.B INFO +lines, each containing one or more statistics in the form +.IB name = value \fR. +The statistics-gathering is experimental and subject to change. .TP .BR "TRACE " [\fIoptions\fP] A trace argument consists of a string of letters (listed below) @@ -145,72 +236,435 @@ without one of .B x or .BR m . +.TP +.B A +All of the above. .RE .TP -.B "PORT" -Emits an +.BR "WATCH " [\fIoptions\fP] +Enables or disables asynchronous messages +.IR "for the current connection only" . +This command has no effect on other connections. A watch argument +consists of a string of letters (listed below) selecting message types, +optionally interspersed with +.RB ` + ' +to enable, or +.RB ` \- ' +to disable, the subsequently listed types, similar to +.B trace +above. The default watch state for the connection the server opens +automatically on stdin/stdout is to show warnings and trace messages; +other connections show no asynchronous messages. (This is done in order +to guarantee that a program reading the server's stdout does not miss +any warnings.) +.RS +.PP +Currently, the following watch options are supported: +.TP +.B t +.B TRACE +messages. +.TP +.B n +.B NOTE +messages. +.TP +.B w +.B WARN +messages. +.TP +.B a +All of the above. +.RE +.TP +.B "VERSION" +Causes the server to emit an .B INFO -line containing just the number of the UDP port used by the +line stating its software version, as two words: the server name, and +its version string. The server name .B tripe -server. If you've allowed your server to allocate a port dynamically, -this is how to find out which one it chose. +is reserved to the Straylight/Edgeware implementation. +.SH "ERROR MESSAGES" +The following +.B FAIL +messages are sent to clients as a result of errors during command +processing. .TP -.B "DAEMON" -Causes the server to disassociate itself from its terminal and become a -background task. This only works once. A warning is issued. +.BI "already-daemon" +(For +.BR DAEMON .) +The +.B tripe +server is already running as a daemon. .TP -.B "LIST" -For each currently-known peer, an -.B INFO -line is written containing the peer's name, as given to -.BR ADD . -.TP -.BI "IFNAME " peer -Emits an -.B INFO -line containing the name of the network interface used to collect IP -packets which are to be encrypted and sent to -.IR peer . -Used by configuration scripts so that they can set up routing tables -appropriately after adding new peers. +.BI "bad-syntax \-\- " message +(For any command.) The command couldn't be understood: e.g., the number +of arguments was wrong. .TP -.BI "ADDR " peer -Emits an -.B INFO -line reporting the IP address and port number stored for +.BI "bad-trace-option " char +(For +.BR TRACE .) +An unknown trace option was requested. +.TP +.BI "bad-watch-option " char +(For +.BR WATCH .) +An unknown watch option was requested. +.TP +.BI "daemon-error \-\- " message +(For +.BR DAEMON .) +An error occurred during the attempt to become a daemon, as reported by +.IR message . +.TP +.BI "invalid-port " number +(For +.BR ADD .) +The given port number is out of range. +.TP +.BI "peer-create-fail " peer +(For +.BR ADD .) +Adding +.I peer +failed for some reason. A warning should have been emitted explaining +why. +.TP +.BI "peer-exists " peer +(For +.BR ADD .) +There is already a peer named .IR peer . .TP -.BI "STATS " peer -Emits a number of -.B INFO -lines, each containing one or more statistics in the form -.IB name = value \fR. -The statistics-gathering is experimental and subject to change. +.BI "resolve-error " hostname +(For +.BR ADD .) +The DNS name +.I hostname +could not be resolved. +.TP +.BI "resolver-timeout " hostname +(For +.BR ADD .) +The DNS name +.I hostname +took too long to resolve. +.TP +.BI "unknown-command " token +The command +.B token +was not recognised. +.TP +.BI "unknown-peer " name +(For +.BR ADDR , +.BR IFNAME , +.BR KILL , +and +.BR STATS .) +There is no peer called +.IR name . +.TP +.BI "unknown-service " service +(For +.BR ADD .) +The service name +.I service +couldn't be found in +.BR /etc/services . +.SH "NOTIFICATIONS" +The following notifications are sent to clients who request them. +.TP +.BI "ADD " peer " " address \fR... +A new peer has been added. The peer's name is +.I peer +and its network address is +.IR address . +.TP +.BI "DAEMON" +The server has forked off into the sunset and become a daemon. .TP .BI "KILL " peer -Causes the server to forget all about -.IR peer . -All keys are destroyed, and no more packets are sent. No notification -is sent to the peer: if it's important that the peer be notified, you -must think of a way to do that yourself. +The peer +.I peer +has been killed. .TP -.BI "ADD " "peer addr port" -Adds a new peer. The peer is given the name -.IR peer ; -the peer's public key is assumed to be in the file -.B keyring.pub -(or whatever alternative file was specified in the -.B \-K -option on the command line). The peer's +.BI "KXDONE " peer +Key exchange with +.I peer +finished successfully. +.TP +.BI "KXSTART " peer +Key exchange with +.I peer +has begun or restarted. If key exchange keeps failing, this message +will be repeated periodically. +.SH "WARNINGS" +There are many possible warnings. They are categorized according to +their first tokens. +.SS "ABORT warnings" +These all indicate that the .B tripe -implementation may be contacted at the given UDP port and IP address. +server has become unable to continue. If enabled, the server will dump +core in its configuration directory. .TP -.B "QUIT" -Instructs the server to exit immediately. A warning is sent. +.BI "ABORT repeated-select-errors" +The main event loop is repeatedly failing. If the server doesn't quit, +it will probably waste all available CPU doing nothing. +.SS "ADMIN warnings" +These indicate a problem with the administration socket interface. +.TP +.BI "ADMIN accept-error \-\- " message +There was an error while attempting to accept a connection from a new +client. +.TP +.BI "ADMIN client-read-error \-\- " message +There was an error sending data to a client. The connection to the +client has been closed. +.SS "KEYMGMT warnings" +These indicate a problem with the keyring files, or the keys stored in +them. +.TP +.BI "KEYMGMT bad-private-key \-\- " message +The private key could not be read, or failed a consistency check. If +there was a problem with the file, usually there will have been +.B key-file-error +warnings before this. +.TP +.BI "KEYMGMT bad-public-keyring \-\- " message +The public keyring couldn't be read. Usually, there will have been +.B key-file-error +warnings before this. +.TP +.BI "KEYMGMT key-file-error " file ":" line " \-\- " message +Reports a specific error with the named keyring file. This probably +indicates a bug in +.BR key (1). +.TP +.BI "KEYMGMT public-key " tag " " tokens\fR... +These messages all indicate a problem with the public key named +.IR tag . +.TP +.BI "KEYMGMT public-key " tag " algorithm-mismatch" +The algorithms specified on the public key don't match the ones for our +private key. All the peers in a network have to use the same +algorithms. +.TP +.BI "KEYMGMT public-key " tag " bad \-\- " message +The public key couldn't be read, or is invalid. +.TP +.BI "KEYMGMT public-key " tag " bad-public-group-element" +The public key is invalid. This may indicate a malicious attempt to +introduce a bogus key. +.TP +.BI "KEYMGMT public-key " tag " bad-algorithm-selection" +The algorithms listed on the public key couldn't be understood. The +algorithm selection attributes are probably malformed and need fixing. +.TP +.BI "KEYMGMT public-key " tag " incorrect-group" +The public key doesn't use the same group as our private key. All the +peers in a network have to use the same group. +.TP +.BI "KEYMGMT public-key " tag " not-found" +The public key for peer +.I tag +wasn't in the public keyring. +.TP +.BI "KEYMGMT public-key " tag " unknown-type" +The type of the public key isn't understood. Maybe you need to upgrade +your copy of +.BR tripe . +(Even if you do, you'll have to regenerate your keys.) +.SS "KX warnings" +These indicate problems during key-exchange. Many indicate either a bug +in the server (either yours or the remote one), or some kind of attack +in progress. All name a +.I peer +as the second token: this is the peer the packet is apparently from, +though it may have been sent by an attacker instead. +.PP +In the descriptions below, +.I msgtoken +is one of the tokens +.BR pre-challenge , +.BR cookie , +.BR challenge , +.BR reply , +.BR switch-rq , +or +.BR switch-ok . +.TP +.BI "KX " peer " bad-expected-reply-log" +The challenges +.B tripe +uses in its protocol contain a check value which proves that the +challenge is honest. This message indicates that the check value +supplied is wrong: someone is attempting to use bogus challenges to +persuade your +.B tripe +server to leak private key information. No chance! +.TP +.BI "KX " peer " decrypt-failed \fR[\fBreply\fR|\fBswitch-ok\fR]" +A symmetrically-encrypted portion of a key-exchange message failed to +decrypt. +.TP +.BI "KX " peer " invalid " msgtoken +A key-exchange message was malformed. This almost certainly indicates a +bug somewhere. +.TP +.BI "KX " peer " incorrect \fR[\fBcookie\fR|\fBswitch-rq\fR|\fBswitch-ok\fR]" +A message didn't contain the right magic data. This may be a replay of +some old exchange, or random packets being sent in an attempt to waste +CPU. +.TP +.BI "KX " peer " public-key-expired" +The peer's public key has expired. It's maintainer should have given +you a replacement before now. +.TP +.BI "KX " peer " sending-cookie" +We've received too many bogus pre-challenge messages. Someone is trying +to flood us with key-exchange messages and make us waste CPU on doing +hard asymmetric crypto sums. +.TP +.BI "KX " peer " unexpected " msgtoken +The message received wasn't appropriate for this stage of the key +exchange process. This may mean that one of our previous packets got +lost. For +.BR pre-challenge , +it may simply mean that the peer has recently restarted. +.TP +.BI "KX " peer " unknown-challenge" +The peer is asking for an answer to a challenge which we don't know +about. This may mean that we've been inundated with challenges from +some malicious source +.I who can read our messages +and discarded the valid one. +.TP +.BI "KX " peer " unknown-message 0x" nn +An unknown key-exchange message arrived. +.SS "PEER warnings" +These are largely concerned with management of peers and the low-level +details of the network protocol. The second word is usually the name of +a peer, or +.RB ` \- ' +if none is relevant. +.TP +.BI "PEER \- unexpected-source " address\fR... +A packet arrived from +.I address +(a network address \(en see above), but no peer is known at that +address. This may indicate a misconfiguration, or simply be a result of +one end of a connection being set up before the other. +.TP +.BI "PEER " peer " bad-packet no-type" +An empty packet arrived. This is very strange. +.TP +.BI "PEER " peer " bad-packet unknown-category 0x" nn +The message category +.I nn +(in hex) isn't understood. Probably a strange random packet from +somewhere; could be an unlikely bug. +.TP +.BI "PEER " peer " bad-packet unknown-type 0x" nn +The message type +.I nn +(in hex) isn't understood. Probably a strange random packet from +somewhere; could be an unlikely bug. +.TP +.BI "PEER " peer " decrypt-failed" +An encrypted IP packet failed to decrypt. It may have been mangled in +transit, or may be a very old packet from an expired previous session +key. There is usually a considerable overlap in the validity periods of +successive session keys, so this shouldn't occur unless the key exchange +takes ages or fails. +.TP +.BI "PEER " peer " packet-build-failed" +There wasn't enough space in our buffer to put the packet we wanted to +send. Shouldn't happen. +.TP +.BI "PEER \- socket-read-error \-\- " message +An error occurred trying to read an incoming packet. +.TP +.BI "PEER " peer " socket-write-error \-\- " message +An error occurred attempting to send a network packet. We lost that +one. +.SS "SERVER warnings" +These indicate problems concerning the server process as a whole. +.TP +.BI "SERVER ignore signal " name +A signal arrived, but the server ignored it. Currently this happens for +.B SIGHUP +because that's a popular way of telling daemons to re-read their +configuration files. Since +.B tripe +re-reads its keyrings automatically and has no other configuration +files, it's not relevant, but it seemed better to ignore the signal than +let the server die. +.TP +.BI "SERVER quit signal " \fR[\fInn\fR|\fIname\fR] +A signal arrived and +.B tripe +is going to quit. +.TP +.BI "SERVER quit admin-request" +A client of the administration interface issued a +.B QUIT +command. +.TP +.BI "SERVER select-error \-\- " message +An error occurred in the server's main event loop. This is bad: if it +happens too many times, the server will abort. +.SS "SYMM warnings" +These are concerned with the symmetric encryption and decryption +process. +.TP +.BI "SYMM replay old-sequence" +A packet was received with an old sequence number. It may just have +been delayed or duplicated, or it may have been an attempt at a replay +attack. +.TP +.BI "SYMM replay duplicated-sequence" +A packet was received with a sequence number we've definitely seen +before. It may be an accidental duplication because the 'net is like +that, or a deliberate attempt at a replay. +.SS "TUN warnings" +These concern the workings of the system-specific tunnel driver. The +second word is the name of the tunnel interface in question, or +.RB ` \- ' +if none. +.TP +.BI "TUN \- bsd no-tunnel-devices" +The driver couldn't find an available tunnel device. Maybe if you +create some more +.BI /dev/tun nn +files, it will work. +.TP +.BI "TUN - open-error " device " \-\- " message +An attempt to open the tunnel device file +.I device +failed. +.TP +.BI "TUN " ifname " read-error \-\- " message +Reading from the tunnel device failed. +.TP +.BI "TUN \- linux config-error \-\- " message +Configuring the Linux TUN/TAP interface failed. +.TP +.BI "TUN \- unet config-error \-\- " message +Configuring the Linux Unet interface failed. Unet is obsolete and +shouldn't be used any more. +.TP +.BI "TUN \- unet getinfo-error \-\- " message +Reading information about the Unet interface failed. Unet is obsolete +and shouldn't be used any more. +.TP +.BI "TUN \- unet ifname-too-long \-\- " message +The Unet interface's name overflowed, so we couldn't read it properly. +Unet is obsolete and shouldn't be used any more. .SH "SEE ALSO" .BR tripectl (1), .BR tripe (8). .PP -.IR "The Trivial IP Encryption Protocol" , +.IR "The Trivial IP Encryption Protocol" . .SH "AUTHOR" Mark Wooding, diff --git a/doc/tripe.8 b/doc/tripe.8 index 929f0191..373271a7 100644 --- a/doc/tripe.8 +++ b/doc/tripe.8 @@ -148,6 +148,11 @@ version number to standard output and exits with status 0. .B "\-u, \-\-usage" Writes a brief usage summary to standard output and exits with status 0. .TP +.B "\-\-tunnel" +Writes a string to standard output describing the configured tunnelling +method and exits with status 0. This is intended for the use of the +start-up script, so that it can check that it will actually work. +.TP .B "\-D, \-\-daemon" Dissociates from its terminal and starts running in the background after completing the initialization procedure described above. If running as diff --git a/ethereal/packet-tripe.c b/ethereal/packet-tripe.c index afeb1bcc..aaad0ec9 100644 --- a/ethereal/packet-tripe.c +++ b/ethereal/packet-tripe.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: packet-tripe.c,v 1.4 2004/04/18 18:08:11 mdw Exp $ + * $Id$ * * TrIPE protocol dissector for Ethereal * @@ -38,15 +38,9 @@ #include #include -#include -#include - -#ifdef ETHEREAL_BUGGERED -# define plugin_address_table_t void -# define plugin_address_table_init(x) -#else -# include -#endif +#include +#include +#include #include "tripe-protocol.h" @@ -132,13 +126,15 @@ static void dissect_tripe(tvbuff_t *b, packet_info *p, proto_tree *t) proto_item *ti; proto_tree *tt; guint8 ty; - gint off = tvb_raw_offset(b); + gint off = 0; guint32 seq; /* --- Initialize the summary cells --- */ if (check_col(p->cinfo, COL_PROTOCOL)) col_set_str(p->cinfo, COL_PROTOCOL, "TrIPE"); + if (check_col(p->cinfo, COL_INFO)) + col_clear(p->cinfo, COL_INFO); ty = tvb_get_guint8(b, 0); if (check_col(p->cinfo, COL_INFO)) { col_clear(p->cinfo, COL_INFO); @@ -286,111 +282,111 @@ void proto_register_tripe(void) }; static hf_register_info hfs[] = { - &hf_tripe_cat, { + { &hf_tripe_cat, { "Message category", "tripe.cat", FT_UINT8, BASE_HEX, 0, MSG_CATMASK - }, - &hf_tripe_packet_type, { + } }, + { &hf_tripe_packet_type, { "Packet message type", "tripe.packet.type", FT_UINT8, BASE_HEX, 0, MSG_TYPEMASK, "This is the TrIPE packet type subcode." - }, - &hf_tripe_ct, { + } }, + { &hf_tripe_ct, { "Encrypted ciphertext", "tripe.ct", FT_BYTES, BASE_NONE, 0, 0, "This is an encrypted message." - }, - &hf_tripe_ct_seq, { + } }, + { &hf_tripe_ct_seq, { "Ciphertext sequence number", "tripe.ct.seq", FT_UINT32, BASE_DEC, 0, 0, "This is the unique sequence number for the ciphertext." - }, - &hf_tripe_ct_iv, { + } }, + { &hf_tripe_ct_iv, { "Ciphertext initialization vector", "tripe.ct.iv", FT_BYTES, BASE_NONE, 0, 0, "This is the initialization vector used for the actual encryption." - }, - &hf_tripe_ct_ct, { + } }, + { &hf_tripe_ct_ct, { "Actual encrypted data", "tripe.ct.ct", FT_BYTES, BASE_NONE, 0, 0, "This is the encrypted message. Reading it ought to be hard." - }, - &hf_tripe_ct_tag, { + } }, + { &hf_tripe_ct_tag, { "Message authentication code", "tripe.ct.tag", FT_BYTES, BASE_NONE, 0, 0, "This is the message authentication code tag for the ciphertext." - }, - &hf_tripe_kx_type, { + } }, + { &hf_tripe_kx_type, { "Key-exchange message type", "tripe.kx.type", FT_UINT8, BASE_HEX, vs_kxtype, MSG_TYPEMASK, "This is the TrIPE key-exchange type subcode." - }, - &hf_tripe_kx_mychal.hf, { + } }, + { &hf_tripe_kx_mychal.hf, { "Sender's challenge data", "tripe.kx.mychal", FT_BYTES, BASE_NONE, 0, 0, "This is the sender's challenge." - }, - &hf_tripe_kx_mychal.hf_len, { + } }, + { &hf_tripe_kx_mychal.hf_len, { "Challenge length", "tripe.kx.mychal.len", FT_UINT16, BASE_DEC, 0, 0, "This is the length of the sender's challenge." - }, - &hf_tripe_kx_mychal.hf_val, { + } }, + { &hf_tripe_kx_mychal.hf_val, { "Challenge", "tripe.kx.mychal.val", FT_BYTES, BASE_NONE, 0, 0, "This is the value of the sender's challenge." - }, - &hf_tripe_kx_mychal.hfx_len, { + } }, + { &hf_tripe_kx_mychal.hfx_len, { "Challenge x length", "tripe.kx.mychal.x.len", FT_UINT16, BASE_DEC, 0, 0, "This is the length of the sender's challenge x-coordinate." - }, - &hf_tripe_kx_mychal.hfy_val, { + } }, + { &hf_tripe_kx_mychal.hfy_val, { "Challenge x value", "tripe.kx.mychal.x.val", FT_BYTES, BASE_NONE, 0, 0, "This is the value of the sender's challenge x-coordinate." - }, - &hf_tripe_kx_mychal.hfy_len, { + } }, + { &hf_tripe_kx_mychal.hfy_len, { "Challenge y length", "tripe.kx.mychal.y.len", FT_UINT16, BASE_DEC, 0, 0, "This is the length of the sender's challenge x-coordinate." - }, - &hf_tripe_kx_mychal.hfx_val, { + } }, + { &hf_tripe_kx_mychal.hfx_val, { "Challenge y value", "tripe.kx.mychal.y.val", FT_BYTES, BASE_NONE, 0, 0, "This is the value of the sender's challenge x-coordinate." - }, - &hf_tripe_kx_mycookie, { + } }, + { &hf_tripe_kx_mycookie, { "Sender's hashed cookie", "tripe.kx.mycookie", FT_BYTES, BASE_NONE, 0, 0, "This is the hash of the sender's challenge." - }, - &hf_tripe_kx_yourcookie, { + } }, + { &hf_tripe_kx_yourcookie, { "Recipient's hashed cookie", "tripe.kx.yourcookie", FT_BYTES, BASE_NONE, 0, 0, "This is the hash of the recipient's challenge." - }, - &hf_tripe_kx_check.hf, { + } }, + { &hf_tripe_kx_check.hf, { "Challenge check-value", "tripe.kx.check", FT_BYTES, BASE_NONE, 0, 0, "This is an encrypted check-value which proves that the sender " "knows the answer to the challenge, and that it is therefore honest." - }, - &hf_tripe_kx_check.hf_len, { + } }, + { &hf_tripe_kx_check.hf_len, { "Check-value length", "tripe.kx.check.len", FT_UINT16, BASE_DEC, 0, 0, "This is the length of the encrypted check-value." - }, - &hf_tripe_kx_check.hf_val, { + } }, + { &hf_tripe_kx_check.hf_val, { "Check-value data", "tripe.kx.check.val", FT_BYTES, BASE_NONE, 0, 0, "This is the actual encrypted check-value." - }, - &hf_tripe_huh, { + } }, + { &hf_tripe_huh, { "Unknown data", "tripe.huh", FT_BYTES, BASE_NONE, 0, 0, "I don't know what's meant to appear here." - }, + } }, }; static gint *tts[] = { @@ -429,9 +425,8 @@ G_MODULE_EXPORT void plugin_reg_handoff(void) proto_reg_handoff_tripe(); } -G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat) +G_MODULE_EXPORT void plugin_register(void) { - plugin_address_table_init(pat); if (proto_tripe == -1) proto_register_tripe(); } diff --git a/keyexch.c b/keyexch.c index 18594cf3..7c0217c5 100644 --- 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@. * @@ -85,7 +85,14 @@ #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); } diff --git a/keymgmt.c b/keymgmt.c index 79945f41..e1388e04 100644 --- a/keymgmt.c +++ b/keymgmt.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keymgmt.c,v 1.7 2004/04/19 08:49:40 mdw Exp $ + * $Id$ * * Key loading and storing * @@ -185,12 +185,12 @@ static const char *algs_get(algswitch *a, key_file *kf, key *k) if ((p = key_getattr(kf, k, "cipher")) == 0) p = "blowfish-cbc"; if ((a->c = gcipher_byname(p)) == 0) - FAIL("unknown cipher"); + FAIL("unknown-cipher"); if ((p = key_getattr(kf, k, "hash")) == 0) p = "rmd160"; if ((a->h = ghash_byname(p)) == 0) - FAIL("unknown hash function"); + FAIL("unknown-hash"); if ((p = key_getattr(kf, k, "mgf")) == 0) { dstr_reset(&d); @@ -198,7 +198,7 @@ static const char *algs_get(algswitch *a, key_file *kf, key *k) p = d.buf; } if ((a->mgf = gcipher_byname(p)) == 0) - FAIL("unknown MGF cipher"); + FAIL("unknown-mgf-cipher"); if ((p = key_getattr(kf, k, "mac")) != 0) { dstr_reset(&d); @@ -206,20 +206,20 @@ static const char *algs_get(algswitch *a, key_file *kf, key *k) if ((q = strchr(d.buf, '/')) != 0) *q++ = 0; if ((a->m = gmac_byname(d.buf)) == 0) - FAIL("unknown message authentication code"); + FAIL("unknown-mac"); if (!q) a->tagsz = a->m->hashsz; else { unsigned long n = strtoul(q, &q, 0); - if (*q) FAIL("bad tag length string"); - if (n%8 || n > ~(size_t)0) FAIL("bad tag length"); + if (*q) FAIL("bad-tag-length-string"); + if (n%8 || n > ~(size_t)0) FAIL("bad-tag-length"); a->tagsz = n/8; } } else { dstr_reset(&d); dstr_putf(&d, "%s-hmac", a->h->name); if ((a->m = gmac_byname(d.buf)) == 0) - FAIL("failed to derive HMAC from hash function"); + FAIL("no-hmac-for-hash"); a->tagsz = a->h->hashsz/2; } @@ -301,7 +301,7 @@ static int algs_samep(const algswitch *a, const algswitch *aa) */ static void keymoan(const char *file, int line, const char *msg, void *p) - { a_warn("%s:%i: error: %s", file, line, msg); } + { a_warn("KEYMGMT key-file-error %s:%i -- %s", file, line, msg); } /* --- @loadpriv@ --- * * @@ -471,7 +471,7 @@ int km_interval(void) T( trace(T_KEYMGMT, "keymgmt: private keyring updated: reloading..."); ) DRESET(&d); if (loadpriv(&d)) - a_warn("%s -- ignoring changes", d.buf); + a_warn("KEYMGMT bad-private-key -- %s", d.buf); else reload = 1; } @@ -483,7 +483,7 @@ int km_interval(void) kf = kf_pub; DRESET(&d); if (loadpub(&d)) - a_warn("%s -- ignoring changes", d.buf); + a_warn("KEYMGMT bad-public-keyring -- %s", d.buf); else { reload = 1; key_close(kf); @@ -558,7 +558,7 @@ int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp) /* --- Find the key --- */ if (key_qtag(kf_pub, tag, &t, &k, &kd)) { - a_warn("public key `%s' not found in keyring `%s'", tag, kr_pub); + a_warn("KEYMGMT public-key %s not-found", tag); goto done; } @@ -568,14 +568,14 @@ int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp) if (strcmp((*ko)->ty, k->type) == 0) goto tymatch; } - a_warn("public key `%s' has unknown type `%s'", t.buf, k->type); + a_warn("KEYMGMT public-key %s unknown-type %s", t.buf, k->type); goto done; tymatch:; /* --- Load the key --- */ if ((e = (*ko)->loadpub(kd, &g, &p, &t)) != 0) { - a_warn("error reading public key `%s': %s", t.buf, e); + a_warn("KEYMGMT public-key %s bad -- %s", t.buf, e); goto done; } @@ -586,25 +586,25 @@ tymatch:; */ if (!group_samep(gg, g)) { - a_warn("public key `%s' has incorrect group", t.buf); + a_warn("KEYMGMT public-key %s incorrect-group", t.buf); goto done; } /* --- Check the public group element --- */ if (group_check(gg, p)) { - a_warn("public key `%s' has bad public group element", t.buf); + a_warn("KEYMGMT public-key %s bad-public-group-element", t.buf); goto done; } /* --- Check the algorithms --- */ if ((e = algs_get(&a, kf_pub, k)) != 0) { - a_warn("public key `%s' has bad algorithm selection: %s", t.buf, e); + a_warn("KEYMGMT public-key %s bad-algorithm-selection %s", t.buf, e); goto done; } - if (!algs_samep(&a, &algs)) { - a_warn("public key `%s' specifies different algorithms", t.buf); + if (!algs_samep(&a, &algs)) { + a_warn("KEYMGMT public-key %s algorithm-mismatch", t.buf); goto done; } diff --git a/keyset.c b/keyset.c index 8893e606..cdd0c999 100644 --- a/keyset.c +++ b/keyset.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keyset.c,v 1.11 2004/04/18 18:08:11 mdw Exp $ + * $Id$ * * Handling of symmetric keysets * @@ -269,7 +269,7 @@ static int dosequence(keyset *ks, uint32 seq) uint32 n; if (seq < ks->iseq) { - a_warn("received packet has old sequence number (possible replay)"); + a_warn("SYMM replay old-sequence"); return (-1); } if (seq >= ks->iseq + KS_SEQWINSZ) { @@ -282,7 +282,7 @@ static int dosequence(keyset *ks, uint32 seq) } seqbit = 1 << (seq - ks->iseq); if (ks->iwin & seqbit) { - a_warn("received packet repeats old sequence number"); + a_warn("SYMM replay duplicated-sequence"); return (-1); } ks->iwin |= seqbit; diff --git a/mallory.c b/mallory.c index 5078b9b5..970e18e7 100644 --- a/mallory.c +++ b/mallory.c @@ -619,14 +619,14 @@ static void help(FILE *fp) putc('\n', fp); usage(fp); fputs("\n\ -Options: - --h, --help Show this help text. --v, --version Show the version number. --u, --usage Show terse usage summary. - --k, --keyring=FILE Fetch keys from FILE. - +Options:\n\ +\n\ +-h, --help Show this help text.\n\ +-v, --version Show the version number.\n\ +-u, --usage Show terse usage summary.\n\ +\n\ +-k, --keyring=FILE Fetch keys from FILE.\n\ +\n\ Directives:\n\ peer:NAME:LOCAL-PORT:REMOTE-ADDR:REMOTE-PORT\n\ include:FILE\n\ diff --git a/peer.c b/peer.c index 87ea4e9e..1469a3a8 100644 --- a/peer.c +++ b/peer.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: peer.c,v 1.11 2004/04/08 01:36:17 mdw Exp $ + * $Id$ * * Communication with the peer * @@ -63,7 +63,7 @@ static void p_read(int fd, unsigned mode, void *v) sz = sizeof(addr); n = recvfrom(fd, buf_i, sizeof(buf_i), 0, &a.sa, &sz); if (n < 0) { - a_warn("error reading socket: %s", strerror(errno)); + a_warn("PEER - socket-read-error -- %s", strerror(errno)); return; } @@ -75,8 +75,8 @@ static void p_read(int fd, unsigned mode, void *v) p->peer.sin.sin_port == a.sin.sin_port) goto found; } - a_warn("packet from unexpected peer: %s:%u", - inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port)); + a_warn("PEER - unexpected-source INET %s %u", + inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port)); return; found: @@ -90,20 +90,20 @@ found: p->st.sz_in += n; buf_init(&b, buf_i, n); if ((ch = buf_getbyte(&b)) < 0) { - a_warn("bad packet from `%s': no type byte", p->name); + a_warn("PEER %s bad-packet no-type", p->name); return; } switch (ch & MSG_CATMASK) { case MSG_PACKET: if (ch & MSG_TYPEMASK) { - a_warn("unknown packet type from `%s'", p->name); + a_warn("PEER %s bad-packet unknown-type 0x%02x", p->name, ch); p->st.n_reject++; return; } buf_init(&bb, buf_o, sizeof(buf_o)); if (ksl_decrypt(&p->ks, MSG_PACKET, &b, &bb)) { p->st.n_reject++; - a_warn("couldn't decrypt inbound packet from `%s'", p->name); + a_warn("PEER %s decrypt-failed", p->name); return; } if (BOK(&bb)) { @@ -112,7 +112,7 @@ found: tun_inject(&p->t, &bb); } else { p->st.n_reject++; - a_warn("packet build failed"); + a_warn("PEER %s packet-build-failed", p->name); } break; case MSG_KEYEXCH: @@ -120,7 +120,7 @@ found: break; default: p->st.n_reject++; - a_warn("bad packet from `%s': unknown packet type", p->name); + a_warn("PEER %s bad-packet unknown-category 0x%02x", p->name, ch); break; } } @@ -155,14 +155,14 @@ buf *p_txstart(peer *p, unsigned msg) void p_txend(peer *p) { if (!BOK(&p->b)) { - a_warn("packet build failed"); + a_warn("PEER %s packet-build-failed", p->name); return; } IF_TRACING(T_PEER, trace_block(T_PACKET, "peer: sending packet", BBASE(&p->b), BLEN(&p->b)); ) if (sendto(sock.fd, BBASE(&p->b), BLEN(&p->b), 0, &p->peer.sa, p->sasz) < 0) - a_warn("packet send to `%s' failed: %s", p->name, strerror(errno)); + a_warn("PEER %s socket-write-error -- %s", p->name, strerror(errno)); else { p->st.n_out++; p->st.sz_out += BLEN(&p->b); @@ -335,6 +335,17 @@ peer *p_create(const char *name, struct sockaddr *sa, size_t sz) if (peers) peers->prev = p; peers = p; + switch (p->peer.sa.sa_family) { + case AF_INET: + a_notify("ADD %s INET %s %u", + name, + inet_ntoa(p->peer.sin.sin_addr), + (unsigned)ntohs(p->peer.sin.sin_port)); + break; + default: + a_notify("ADD %s UNKNOWN", name); + break; + } return (p); tidy_1: @@ -385,6 +396,7 @@ peer *p_find(const char *name) void p_destroy(peer *p) { T( trace(T_PEER, "peer: destroying peer `%s'", p->name); ) + a_notify("KILL %s", p->name); ksl_free(&p->ks); kx_free(&p->kx); tun_destroy(&p->t); diff --git a/setup b/setup index a74f9dae..ed80e2b0 100755 --- a/setup +++ b/setup @@ -6,5 +6,5 @@ mkaclocal libtoolize autoheader autoconf -automake +automake -a mkdir -p build diff --git a/tripe-init.in b/tripe-init.in index 8c4730e5..b02b8269 100755 --- a/tripe-init.in +++ b/tripe-init.in @@ -10,11 +10,19 @@ set -e [ -f @initconfig@ ] && . @initconfig@ : ${prefix=@prefix@} ${exec_prefix=@exec_prefix@} : ${bindir=@bindir@} ${sbindir=@sbindir@} -: ${TRIPEDIR=@configdir@} +: ${TRIPEDIR=@configdir@} ${tripesock=@socketdir@/tripesock} +: ${pidfile=@pidfile@} : ${tripe=$sbindir/tripe} ${tripectl=$bindir/tripectl} PATH=/usr/bin:/usr/sbin:/bin:/sbin:$bindir export PATH TRIPEDIR +# --- Give up if there's no key --- + +if test ! -f $TRIPEDIR/keyring || test ! -f $TRIPEDIR/keyring.pub; then + echo >&2 "Not starting/stopping TrIPE: keyring files missing" + exit 0 +fi + # --- Check it will work, or at least stands a fighting chance --- # # Having loads of different tunnel types doesn't help any. @@ -98,13 +106,13 @@ esac case "$1" in start) echo -n "Starting TrIPE VPN daemon:" - if $tripectl help >/dev/null 2>/dev/null; then + if $tripectl version >/dev/null 2>/dev/null; then echo " already running" exit 0 fi $tripectl -D -s -p$tripe \ -f${logfile-@logfile@} \ - -P${pidfile-@pidfile@} \ + -P$pidfile \ ${keytag+-S-t}$keytag \ ${addr+-S-b}$addr \ ${port+-S-p}${port} \ @@ -135,8 +143,19 @@ case "$1" in ;; stop) echo -n "Stopping TrIPE VPN daemon:" - $tripectl quit - echo " done" + if test ! -S $tripesock; then + echo " not running" + elif $tripectl quit >/dev/null 2>&1; then + echo " done" + elif test ! -f $pidfile; then + echo " stale socket found: removing" + rm -f $tripesock + elif kill `cat $pidfile`; then + echo " done (killed violently)" + else + echo " it doesn't want do die!" + exit 1 + fi ;; status) for i in `$tripectl list`; do diff --git a/tripe.c b/tripe.c index 0ba169b2..78a3d726 100644 --- a/tripe.c +++ b/tripe.c @@ -95,6 +95,7 @@ Options:\n\ -h, --help Display this help text.\n\ -v, --version Display version number.\n\ -u, --usage Display pointless usage message.\n\ + --tunnel Display IP tunnelling technique and exit.\n\ \n\ -D, --daemon Run in the background.\n\ -d, --directory=DIR Switch to directory DIR [default " CONFIGDIR "].\n\ @@ -273,8 +274,13 @@ int main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); tun_init(); p_init(baddr, port); - if (!(f & f_daemon)) - a_create(STDIN_FILENO, STDOUT_FILENO); + if (!(f & f_daemon)) { +#ifndef NTRACE + a_create(STDIN_FILENO, STDOUT_FILENO, AF_TRACE | AF_WARN); +#else + a_create(STDIN_FILENO, STDOUT_FILENO, AF_WARN); +#endif + } if (g != (gid_t)-1) { if (setgid(g) || (getuid() == 0 && setgroups(1, &g))) { die(EXIT_FAILURE, "couldn't setgid to %u: %s", @@ -308,11 +314,11 @@ int main(int argc, char *argv[]) if (!sel_select(&sel)) selerr = 0; else if (errno != EINTR && errno != EAGAIN) { - a_warn("select failed: %s", strerror(errno)); + a_warn("SERVER select-error -- %s", strerror(errno)); selerr++; if (selerr > 8) { - a_warn("too many select errors: bailing out"); - a_quit(); + a_warn("ABORT repeated-select-errors"); + abort(); } } } diff --git a/tripe.h b/tripe.h index 7de033d3..320a2ca5 100644 --- a/tripe.h +++ b/tripe.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tripe.h,v 1.20 2004/04/18 18:08:11 mdw Exp $ + * $Id$ * * Main header file for TrIPE * @@ -292,7 +292,7 @@ typedef struct stats { unsigned long sz_in, sz_out; /* Size of all data in and out */ unsigned long sz_kxin, sz_kxout; /* Size of key exchange messages */ unsigned long sz_ipin, sz_ipout; /* Size of encapsulated IP packets */ - time_t t_start, t_last; /* Time peer created, last recv */ + time_t t_start, t_last, t_kx; /* Time peer created, last pk, kx */ unsigned long n_reject; /* Number of rejected packets */ unsigned long n_in, n_out; /* Number of packets in and out */ unsigned long n_kxin, n_kxout; /* Number of key exchange packets */ @@ -345,6 +345,17 @@ typedef struct admin { #define AF_DEAD 1u /* Destroy this admin block */ #define AF_LOCK 2u /* Don't destroy it yet */ +#define AF_NOTE 4u /* Catch notifications */ +#ifndef NTRACE + #define AF_TRACE 8u /* Catch tracing */ +#endif +#define AF_WARN 16u /* Catch warning messages */ + +#ifndef NTRACE +# define AF_ALLMSGS (AF_NOTE | AF_TRACE | AF_WARN) +#else +# define AF_ALLMSGS (AF_NOTE | AF_WARN) +#endif /*----- Global variables --------------------------------------------------*/ @@ -651,16 +662,29 @@ extern int ksl_decrypt(keyset **/*ksroot*/, unsigned /*ty*/, extern void a_warn(const char */*fmt*/, ...); +/* --- @a_notify@ --- * + * + * Arguments: @const char *fmt@ = pointer to format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Sends a notification to interested admin connections. + */ + +extern void a_notify(const char */*fmt*/, ...); + /* --- @a_create@ --- * * * Arguments: @int fd_in, fd_out@ = file descriptors to use + * @unsigned f@ = initial flags to set * * Returns: --- * * Use: Creates a new admin connection. */ -extern void a_create(int /*fd_in*/, int /*fd_out*/); +extern void a_create(int /*fd_in*/, int /*fd_out*/, unsigned /*f*/); /* --- @a_quit@ --- * * diff --git a/tun-bsd.c b/tun-bsd.c index c9b8f7f0..620ea987 100644 --- a/tun-bsd.c +++ b/tun-bsd.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tun-bsd.c,v 1.3 2004/04/08 01:36:17 mdw Exp $ + * $Id$ * * Tunnel interface for 4.4BSD-derived systems * @@ -55,7 +55,7 @@ void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("tunnel read failed (%s): %s", tun_ifname(t), strerror(errno)); + a_warn("TUN %s read-error -- %s", tun_ifname(t), strerror(errno)); return; } IF_TRACING(T_TUNNEL, { @@ -107,10 +107,10 @@ int tun_create(tunnel *t, peer *p) T( trace(T_TUNNEL, "tunnel device %u busy: skipping", n); ) break; case ENOENT: - a_warn("no suitable tunnel devices found"); + a_warn("TUN - bsd no-tunnel-devices"); return (-1); default: - a_warn("error opening `%s': %s (skipping)", buf, strerror(errno)); + a_warn("TUN - open-error %s -- %s", buf, strerror(errno)); break; } n++; diff --git a/tun-linux.c b/tun-linux.c index c30784d7..6aa5adb4 100644 --- a/tun-linux.c +++ b/tun-linux.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tun-linux.c,v 1.3 2004/04/08 01:36:17 mdw Exp $ + * $Id$ * * Tunnel interface based on Linux TUN/TAP driver * @@ -57,7 +57,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("tunnel read failed (%s): %s", t->ifn, strerror(errno)); + a_warn("TUN %s read-error -- %s", t->ifn, strerror(errno)); return; } IF_TRACING(T_TUNNEL, { @@ -100,15 +100,14 @@ int tun_create(tunnel *t, peer *p) struct ifreq iff; if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { - a_warn("open `/dev/net/tun' failed: %s", strerror(errno)); + a_warn("TUN - open-error /dev/net/tun -- %s", strerror(errno)); return (-1); } fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); iff.ifr_name[0] = 0; iff.ifr_flags = IFF_TUN; if ((f = ioctl(fd, TUNSETIFF, &iff)) < 0) { - a_warn("couldn't set configure new TUN/TAP interface: %s", - strerror(errno)); + a_warn("TUN - linux config-error -- %s", strerror(errno)); close(fd); return (-1); } diff --git a/tun-unet.c b/tun-unet.c index 8d0225a3..1cbdf2be 100644 --- a/tun-unet.c +++ b/tun-unet.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tun-unet.c,v 1.6 2004/04/08 01:36:17 mdw Exp $ + * $Id$ * * Tunnel interface based on Linux Usernet * @@ -59,7 +59,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("tunnel read failed (%s): %s", tun_ifname(t), strerror(errno)); + a_warn("TUN %s read-error -- %s", tun_ifname(t), strerror(errno)); return; } IF_TRACING(T_TUNNEL, { @@ -101,13 +101,13 @@ int tun_create(tunnel *t, peer *p) int f; if ((fd = open("/dev/unet", O_RDWR)) < 0) { - a_warn("open `/dev/unet' failed: %s", strerror(errno)); + a_warn("TUN - open-error /dev/unet -- %s", strerror(errno)); return (-1); } fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); if ((f = ioctl(fd, UNIOCGIFFLAGS)) < 0 || ioctl(fd, UNIOCSIFFLAGS, f | IFF_POINTOPOINT)) { - a_warn("couldn't set point-to-point flag: %s", strerror(errno)); + a_warn("TUN - unet config-error -- %s", strerror(errno)); close(fd); return (-1); } @@ -131,11 +131,11 @@ const char *tun_ifname(tunnel *t) static char b[UNET_NAMEMAX]; struct unet_info uni; if (ioctl(t->f.fd, UNIOCGINFO, &uni)) { - a_warn("ioctl(UNIOCGINFO) failed: %s", strerror(errno)); + a_warn("TUN - unet getinfo-error -- %s", strerror(errno)); return (""); } if (strlen(uni.uni_ifname) + 1 > sizeof(b)) { - a_warn("interface name too long!"); + a_warn("TUN - unet ifname-too-long"); return (""); } strcpy(b, uni.uni_ifname); -- [mdw]