From f43df819b3b11fa95a68f6feb58070268d40b1a8 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Sun, 19 Feb 2006 15:03:19 +0000 Subject: [PATCH] Correctly tokenize output to admin clients. Organization: Straylight/Edgeware From: Mark Wooding This is a wide ranging change, and there may well be bugs in some of the message reporting code. --- admin.c | 309 ++++++++++++++++++++++++++++------------------ chal.c | 14 +-- doc/tripe-admin.5 | 58 +++++---- keyexch.c | 50 ++++---- keymgmt.c | 38 ++++-- keyset.c | 28 +---- peer.c | 75 +++++------ servutil.c | 43 ++----- tripe.c | 4 +- tripe.h | 21 +--- tun-bsd.c | 6 +- tun-linux.c | 8 +- tun-slip.c | 20 +-- tun-unet.c | 10 +- 14 files changed, 366 insertions(+), 318 deletions(-) diff --git a/admin.c b/admin.c index da7ccad6..bc2bdf3b 100644 --- a/admin.c +++ b/admin.c @@ -112,7 +112,7 @@ again: goto again; if (errno != EAGAIN && errno != EWOULDBLOCK) { a_destroy(a); - a_warn("ADMIN client-read-error -- %s", strerror(errno)); + a_warn("ADMIN", "client-write-error", "?ERRNO", A_END); return (-1); } } @@ -231,6 +231,95 @@ static void a_flush(int fd, unsigned mode, void *v) /*----- Utility functions -------------------------------------------------*/ +/* --- @quotify@ --- * + * + * Arguments: @dstr *d@ = where to write the answer + * @const char *p@ = string to quotify + * + * Returns: --- + * + * Use: Quotes the given string if necessary, according to our + * quoting rules. + */ + +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, '\"'); + } +} + +/* --- @a_vformat@ --- * + * + * Arguments: @dstr *d@ = where to leave the formatted message + * @const char *fmt@ = pointer to format string + * @va_list ap@ = arguments in list + * + * Returns: --- + * + * Use: Main message token formatting driver. + */ + +static void a_vformat(dstr *d, const char *fmt, va_list ap) +{ + dstr dd = DSTR_INIT; + + while (fmt) { + if (*fmt == '*') { + dstr_putc(d, ' '); + dstr_vputf(d, fmt + 1, &ap); + } else if (*fmt == '?') { + if (strcmp(fmt, "?ADDR") == 0) { + const addr *a = va_arg(ap, const addr *); + switch (a->sa.sa_family) { + case AF_INET: + quotify(d, "INET"); + quotify(d, inet_ntoa(a->sin.sin_addr)); + dstr_putf(d, " %u", (unsigned)ntohs(a->sin.sin_port)); + break; + default: + abort(); + } + } else if (strcmp(fmt, "?B64") == 0) { + const octet *p = va_arg(ap, const octet *); + size_t n = va_arg(ap, size_t); + base64_ctx b64; + dstr_putc(d, ' '); + base64_init(&b64); + b64.indent = ""; + b64.maxline = 0; + base64_encode(&b64, p, n, d); + base64_encode(&b64, 0, 0, d); + while (d->len && d->buf[d->len - 1] == '=') d->len--; + } else if (strcmp(fmt, "?PEER") == 0) + quotify(d, p_name(va_arg(ap, peer *))); + else if (strcmp(fmt, "?ERRNO") == 0) { + dstr_putf(d, " E%d", errno); + quotify(d, strerror(errno)); + } else + abort(); + } else { + if (*fmt == '!') fmt++; + DRESET(&dd); + dstr_vputf(&dd, fmt, &ap); + quotify(d, dd.buf); + } + fmt = va_arg(ap, const char *); + } + + dstr_destroy(&dd); +} + /* --- @a_write@, @a_vwrite@ --- * * * Arguments: @admin *a@ = admin connection to write to @@ -249,17 +338,10 @@ static void a_vwrite(admin *a, const char *status, const char *tag, const char *fmt, va_list ap) { dstr d = DSTR_INIT; - if (tag) dstr_puts(&d, "BG"); dstr_puts(&d, status); - if (tag) { - dstr_putc(&d, ' '); - dstr_puts(&d, tag); - } - if (fmt) { - dstr_putc(&d, ' '); - dstr_vputf(&d, fmt, &ap); - } + if (tag) quotify(&d, tag); + a_vformat(&d, fmt, ap); dstr_putc(&d, '\n'); dosend(a, d.buf, d.len); dstr_destroy(&d); @@ -285,7 +367,7 @@ static void a_write(admin *a, const char *status, const char *tag, * Use: Convenience functions for @a_write@. */ -static void a_ok(admin *a) { a_write(a, "OK", 0, 0); } +static void a_ok(admin *a) { a_write(a, "OK", 0, A_END); } static void a_info(admin *a, const char *fmt, ...) { @@ -350,8 +432,7 @@ static void a_valert(unsigned f_and, unsigned f_eq, const char *tag, if (!(flags & F_INIT)) return; - if (fmt) - dstr_vputf(&d, fmt, &ap); + a_vformat(&d, fmt, ap); a_rawalert(f_and, f_eq, tag, fmt ? d.buf : 0, fmt ? d.len : 0); dstr_destroy(&d); } @@ -385,9 +466,12 @@ void a_warn(const char *fmt, ...) if (flags & F_INIT) a_valert(0, 0, "WARN", fmt, ap); else { + dstr d = DSTR_INIT; fprintf(stderr, "%s: ", QUIS); - vfprintf(stderr, fmt, ap); - fputc('\n', stderr); + a_vformat(&d, fmt, ap); + dstr_putc(&d, '\n'); + dstr_write(&d, stderr); + dstr_destroy(&d); } va_end(ap); } @@ -471,7 +555,7 @@ static void a_sigdie(int sig, void *v) p = buf; break; } - a_warn("SERVER quit signal %s", p); + a_warn("SERVER", "quit", "signal", "%s", p, A_END); a_quit(); } @@ -487,7 +571,7 @@ static void a_sigdie(int sig, void *v) static void a_sighup(int sig, void *v) { - a_warn("SERVER ignore signal SIGHUP"); + a_warn("SERVER", "ignore", "signal", "SIGHUP", A_END); } /* --- @a_parsetime@ --- * @@ -528,7 +612,7 @@ static peer *a_findpeer(admin *a, const char *pn) peer *p; if ((p = p_find(pn)) == 0) - a_fail(a, "unknown-peer %s", pn); + a_fail(a, "unknown-peer", "%s", pn, A_END); return (p); } @@ -574,7 +658,7 @@ static void a_bgrelease(admin_bgop *bg) */ static void a_bgok(admin_bgop *bg) - { a_write(bg->a, "OK", bg->tag, 0); } + { a_write(bg->a, "OK", bg->tag, A_END); } static void a_bginfo(admin_bgop *bg, const char *fmt, ...) { @@ -621,7 +705,7 @@ static void a_bgadd(admin *a, admin_bgop *bg, const char *tag, a->bg = bg; a_lock(a); T( trace(T_ADMIN, "admin: add bgop %s", BGTAG(bg)); ) - if (tag) a_write(a, "DETACH", tag, 0); + if (tag) a_write(a, "DETACH", tag, A_END); } /*----- Name resolution operations ----------------------------------------*/ @@ -643,7 +727,7 @@ static void a_resolved(struct hostent *h, void *v) T( trace(T_ADMIN, "admin: resop %s resolved", BGTAG(r)); ) TIMER; if (!h) { - a_bgfail(&r->bg, "resolve-error %s", r->addr); + a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END); r->func(r, ARES_FAIL); } else { memcpy(&r->sa.sin.sin_addr, h->h_addr, sizeof(struct in_addr)); @@ -669,7 +753,7 @@ static void a_restimer(struct timeval *tv, void *v) admin_resop *r = v; T( trace(T_ADMIN, "admin: resop %s timeout", BGTAG(r)); ) - a_bgfail(&r->bg, "resolver-timeout %s\n", r->addr); + a_bgfail(&r->bg, "resolver-timeout", "%s", r->addr, A_END); r->func(r, ARES_FAIL); bres_abort(&r->r); xfree(r->addr); @@ -725,7 +809,7 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, r->func = func; if (mystrieq(av[i], "inet")) i++; if (ac - i != 2) { - a_fail(a, "bad-addr-syntax [inet] ADDRESS PORT"); + a_fail(a, "bad-addr-syntax", "[inet] ADDRESS PORT", A_END); goto fail; } r->sa.sin.sin_family = AF_INET; @@ -735,13 +819,13 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, if (*p) { struct servent *s = getservbyname(av[i + 1], "udp"); if (!s) { - a_fail(a, "unknown-service %s", av[i + 1]); + a_fail(a, "unknown-service", "%s", av[i + 1], A_END); goto fail; } pt = ntohs(s->s_port); } if (pt == 0 || pt >= 65536) { - a_fail(a, "invalid-port %lu", pt); + a_fail(a, "invalid-port", "%lu", pt, A_END); goto fail; } r->sa.sin.sin_port = htons(pt); @@ -802,9 +886,9 @@ static void a_doadd(admin_resop *r, int rc) add->peer.sasz = add->r.sasz; add->peer.sa = add->r.sa; if (p_find(add->peer.name)) - a_bgfail(&add->r.bg, "peer-exists %s", add->peer.name); + a_bgfail(&add->r.bg, "peer-exists", "%s", add->peer.name, A_END); else if (!p_create(&add->peer)) - a_bgfail(&add->r.bg, "peer-create-fail %s", add->peer.name); + a_bgfail(&add->r.bg, "peer-create-fail", "%s", add->peer.name, A_END); else a_bgok(&add->r.bg); } @@ -839,7 +923,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) /* --- Make sure someone's not got there already --- */ if (p_find(av[0])) { - a_fail(a, "peer-exists %s", av[0]); + a_fail(a, "peer-exists", "%s", av[0], A_END); goto fail; } @@ -856,7 +940,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) if (!av[++i]) goto bad_syntax; for (j = 0;; j++) { if (!tunnels[j]) { - a_fail(a, "unknown-tunnel %s", av[i]); + a_fail(a, "unknown-tunnel", "%s", av[i], A_END); goto fail; } if (mystrieq(av[i], tunnels[j]->name)) { @@ -868,7 +952,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) long t; if (!av[++i]) goto bad_syntax; if ((t = a_parsetime(av[i])) < 0) { - a_fail(a, "bad-time-spec %s", av[i]); + a_fail(a, "bad-time-spec", "%s", av[i], A_END); goto fail; } add->peer.t_ka = t; @@ -888,7 +972,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) /* --- Clearing up --- */ bad_syntax: - a_fail(a, "bad-syntax -- add PEER [OPTIONS] ADDR ..."); + a_fail(a, "bad-syntax", "add", "PEER [OPTIONS] ADDR ...", A_END); fail: xfree(add->peer.name); xfree(add); @@ -934,15 +1018,15 @@ static void a_pong(int rc, void *v) gettimeofday(&tv, 0); tv_sub(&tv, &tv, &pg->pingtime); millis = (double)tv.tv_sec * 1000 + (double)tv.tv_usec/1000; - a_bginfo(&pg->bg, "ping-ok %.1f", millis); + a_bginfo(&pg->bg, "ping-ok", "%.1f", millis, A_END); a_bgok(&pg->bg); break; case PING_TIMEOUT: - a_bginfo(&pg->bg, "ping-timeout"); + a_bginfo(&pg->bg, "ping-timeout", A_END); a_bgok(&pg->bg); break; case PING_PEERDIED: - a_bginfo(&pg->bg, "ping-peer-died"); + a_bginfo(&pg->bg, "ping-peer-died", A_END); a_bgok(&pg->bg); break; default: @@ -982,7 +1066,7 @@ static void a_ping(admin *a, unsigned ac, char *av[], } else if (mystrieq(av[i], "-timeout")) { if (!av[++i]) goto bad_syntax; if ((t = a_parsetime(av[i])) < 0) { - a_fail(a, "bad-time-spec %s", av[i]); + a_fail(a, "bad-time-spec", "%s", av[i], A_END); return; } } else if (mystrieq(av[i], "--")) { @@ -1002,13 +1086,13 @@ static void a_ping(admin *a, unsigned ac, char *av[], T( trace(T_ADMIN, "admin: ping op %s: %s to %s", BGTAG(pg), cmd, p_name(p)); ) if (p_pingsend(p, &pg->ping, msg, t, a_pong, pg)) { - a_bgfail(&pg->bg, "ping-send-failed"); + a_bgfail(&pg->bg, "ping-send-failed", A_END); a_bgrelease(&pg->bg); } return; bad_syntax: - a_fail(a, "bad-syntax -- %s [OPTIONS] PEER", cmd); + a_fail(a, "bad-syntax", "%s", cmd, "[OPTIONS] PEER", cmd, A_END); return; } @@ -1043,8 +1127,8 @@ static int traceish(admin *a, unsigned ac, char *av[], if (!ac || strcmp(av[0], "?") == 0) { const trace_opt *t; for (t = tt; t->ch; t++) { - a_info(a, "%c%c %s", - t->ch, (*ff & t->f) == t->f ? '+' : ' ', t->help); + a_info(a, "*%c%c %s", + t->ch, (*ff & t->f) == t->f ? '+' : ' ', t->help, A_END); } } else { unsigned sense = 1; @@ -1064,7 +1148,7 @@ static int traceish(admin *a, unsigned ac, char *av[], goto tropt_ok; } } - a_fail(a, "bad-%s-option %c", what, *p); + a_fail(a, "bad-%s-option", what, "%c", *p, A_END); return (0); tropt_ok:; break; @@ -1093,23 +1177,6 @@ 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[]) { @@ -1132,20 +1199,20 @@ static void acmd_warn(admin *a, unsigned ac, char *av[]) static void acmd_port(admin *a, unsigned ac, char *av[]) { - a_info(a, "%u", p_port()); + a_info(a, "%u", p_port(), A_END); a_ok(a); } static void acmd_daemon(admin *a, unsigned ac, char *av[]) { if (flags & F_DAEMON) - a_fail(a, "already-daemon"); + a_fail(a, "already-daemon", A_END); else { - a_notify("DAEMON"); + a_notify("DAEMON", A_END); if (a_stdin) a_destroy(a_stdin); if (u_daemon()) - a_fail(a, "daemon-error -- %s", strerror(errno)); + a_fail(a, "daemon-error", "?ERRNO", A_END); else { flags |= F_DAEMON; a_ok(a); @@ -1157,7 +1224,7 @@ static void acmd_list(admin *a, unsigned ac, char *av[]) { peer *p; for (p = p_first(); p; p = p_next(p)) - a_info(a, "%s", p_name(p)); + a_info(a, "%s", p_name(p), A_END); a_ok(a); } @@ -1166,7 +1233,7 @@ static void acmd_ifname(admin *a, unsigned ac, char *av[]) peer *p; if ((p = a_findpeer(a, av[0])) != 0) { - a_info(a, "%s", p_ifname(p)); + a_info(a, "%s", p_ifname(p), A_END); a_ok(a); } } @@ -1177,7 +1244,7 @@ static void acmd_getchal(admin *a, unsigned ac, char *av[]) buf_init(&b, buf_i, PKBUFSZ); c_new(&b); - a_info(a, "%s", b64_encode(BBASE(&b), BLEN(&b))); + a_info(a, "?B64", BBASE(&b), (size_t)BLEN(&b), A_END); a_ok(a); } @@ -1192,7 +1259,7 @@ static void acmd_checkchal(admin *a, unsigned ac, char *av[]) base64_decode(&b64, 0, 0, &d); buf_init(&b, d.buf, d.len); if (c_check(&b) || BBAD(&b) || BLEFT(&b)) - a_fail(a, "invalid-challenge"); + a_fail(a, "invalid-challenge", A_END); else a_ok(a); dstr_destroy(&d); @@ -1222,9 +1289,7 @@ static void acmd_addr(admin *a, unsigned ac, char *av[]) if ((p = a_findpeer(a, av[0])) != 0) { ad = p_addr(p); assert(ad->sa.sa_family == AF_INET); - a_info(a, "INET %s %u", - inet_ntoa(ad->sin.sin_addr), - (unsigned)ntohs(ad->sin.sin_port)); + a_info(a, "?ADDR", ad, A_END); a_ok(a); } } @@ -1236,17 +1301,17 @@ 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_info(a, "keepalive=%lu", ps->t_ka); + a_info(a, "tunnel=%s", ps->tops->name, A_END); + a_info(a, "keepalive=%lu", ps->t_ka, A_END); a_ok(a); } } static void acmd_servinfo(admin *a, unsigned ac, char *av[]) { - a_info(a, "implementation=edgeware-tripe"); - a_info(a, "version=%s", VERSION); - a_info(a, "daemon=%s", BOOL(flags & F_DAEMON)); + a_info(a, "implementation=edgeware-tripe", A_END); + a_info(a, "version=%s", VERSION, A_END); + a_info(a, "daemon=%s", BOOL(flags & F_DAEMON), A_END); a_ok(a); } @@ -1259,21 +1324,21 @@ static void acmd_stats(admin *a, unsigned ac, char *av[]) return; st = p_stats(p); - 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, "start-time=%s", timestr(st->t_start), A_END); + a_info(a, "last-packet-time=%s", timestr(st->t_last), A_END); + a_info(a, "last-keyexch-time=%s", timestr(st->t_kx), A_END); + a_info(a, "packets-in=%lu bytes-in=%lu", st->n_in, st->sz_in, A_END); a_info(a, "packets-out=%lu bytes-out=%lu", - st->n_out, st->sz_out); + st->n_out, st->sz_out, A_END); a_info(a, "keyexch-packets-in=%lu keyexch-bytes-in=%lu", - st->n_kxin, st->sz_kxin); + st->n_kxin, st->sz_kxin, A_END); a_info(a, "keyexch-packets-out=%lu keyexch-bytes-out=%lu", - st->n_kxout, st->sz_kxout); + st->n_kxout, st->sz_kxout, A_END); a_info(a, "ip-packets-in=%lu ip-bytes-in=%lu", - st->n_ipin, st->sz_ipin); + st->n_ipin, st->sz_ipin, A_END); a_info(a, "ip-packets-out=%lu ip-bytes-out=%lu", - st->n_ipout, st->sz_ipout); - a_info(a, "rejected-packets=%lu", st->n_reject); + st->n_ipout, st->sz_ipout, A_END); + a_info(a, "rejected-packets=%lu", st->n_reject, A_END); a_ok(a); } @@ -1300,7 +1365,7 @@ static void acmd_reload(admin *a, unsigned ac, char *av[]) static void acmd_quit(admin *a, unsigned ac, char *av[]) { - a_warn("SERVER quit admin-request"); + a_warn("SERVER", "quit", "admin-request", A_END); a_ok(a); a_unlock(a); a_quit(); @@ -1308,7 +1373,7 @@ static void acmd_quit(admin *a, unsigned ac, char *av[]) static void acmd_version(admin *a, unsigned ac, char *av[]) { - a_info(a, "%s %s", PACKAGE, VERSION); + a_info(a, "%s", PACKAGE, "%s", VERSION, A_END); a_ok(a); } @@ -1316,7 +1381,7 @@ static void acmd_tunnels(admin *a, unsigned ac, char *av[]) { int i; for (i = 0; tunnels[i]; i++) - a_info(a, "%s", tunnels[i]->name); + a_info(a, "%s", tunnels[i]->name, A_END); a_ok(a); } @@ -1332,42 +1397,45 @@ typedef struct acmd { static void acmd_help(admin */*a*/, unsigned /*ac*/, char */*av*/[]); static const acmd acmdtab[] = { - { "add", "add PEER [OPTIONS] ADDR ...", - 2, 0xffff, acmd_add }, - { "addr", "addr PEER", 1, 1, acmd_addr }, - { "checkchal", "checkchal CHAL", 1, 1, acmd_checkchal }, - { "daemon", "daemon", 0, 0, acmd_daemon }, - { "eping", "eping [OPTIONS] PEER", 1, 0xffff, acmd_eping }, - { "forcekx", "forcekx PEER", 1, 1, acmd_forcekx }, - { "getchal", "getchal", 0, 0, acmd_getchal }, - { "greet", "greet PEER CHAL", 2, 2, acmd_greet }, - { "help", "help", 0, 0, acmd_help }, - { "ifname", "ifname PEER", 1, 1, acmd_ifname }, - { "kill", "kill PEER", 1, 1, acmd_kill }, - { "list", "list", 0, 0, acmd_list }, - { "notify", "notify MESSAGE ...", 1, 0xffff, acmd_notify }, - { "peerinfo", "peerinfo PEER", 1, 1, acmd_peerinfo }, - { "ping", "ping [OPTIONS] PEER", 1, 0xffff, acmd_ping }, - { "port", "port", 0, 0, acmd_port }, - { "quit", "quit", 0, 0, acmd_quit }, - { "reload", "reload", 0, 0, acmd_reload }, - { "servinfo", "servinfo", 0, 0, acmd_servinfo }, - { "stats", "stats PEER", 1, 1, acmd_stats }, + { "add", "PEER [OPTIONS] ADDR ...", 2, 0xffff, acmd_add }, + { "addr", "PEER", 1, 1, acmd_addr }, + { "checkchal", "CHAL", 1, 1, acmd_checkchal }, + { "daemon", 0, 0, 0, acmd_daemon }, + { "eping", "[OPTIONS] PEER", 1, 0xffff, acmd_eping }, + { "forcekx", "PEER", 1, 1, acmd_forcekx }, + { "getchal", 0, 0, 0, acmd_getchal }, + { "greet", "PEER CHAL", 2, 2, acmd_greet }, + { "help", 0, 0, 0, acmd_help }, + { "ifname", "PEER", 1, 1, acmd_ifname }, + { "kill", "PEER", 1, 1, acmd_kill }, + { "list", 0, 0, 0, acmd_list }, + { "notify", "MESSAGE ...", 1, 0xffff, acmd_notify }, + { "peerinfo", "PEER", 1, 1, acmd_peerinfo }, + { "ping", "[OPTIONS] PEER", 1, 0xffff, acmd_ping }, + { "port", 0, 0, 0, acmd_port }, + { "quit", 0, 0, 0, acmd_quit }, + { "reload", 0, 0, 0, acmd_reload }, + { "servinfo", 0, 0, 0, acmd_servinfo }, + { "stats", "PEER", 1, 1, acmd_stats }, #ifndef NTRACE - { "trace", "trace [OPTIONS]", 0, 1, acmd_trace }, + { "trace", "[OPTIONS]", 0, 1, acmd_trace }, #endif - { "tunnels", "tunnels", 0, 0, acmd_tunnels }, - { "version", "version", 0, 0, acmd_version }, - { "warn", "warn MESSAGE ...", 1, 0xffff, acmd_warn }, - { "watch", "watch [OPTIONS]", 0, 1, acmd_watch }, + { "tunnels", 0, 0, 0, acmd_tunnels }, + { "version", 0, 0, 0, acmd_version }, + { "warn", "MESSAGE ...", 1, 0xffff, acmd_warn }, + { "watch", "[OPTIONS]", 0, 1, acmd_watch }, { 0, 0, 0, 0, 0 } }; static void acmd_help(admin *a, unsigned ac, char *av[]) { const acmd *c; - for (c = acmdtab; c->name; c++) - a_info(a, "%s", c->help); + for (c = acmdtab; c->name; c++) { + if (c->help) + a_info(a, "%s", c->name, "*%s", c->help, A_END); + else + a_info(a, "%s", c->name, A_END); + } a_ok(a); } @@ -1522,9 +1590,12 @@ static void a_line(char *p, size_t len, void *vp) for (c = acmdtab; c->name; c++) { if (mystrieq(av[0], c->name)) { ac--; - if (c->argmin > ac || ac > c->argmax) - a_fail(a, "bad-syntax -- %s", c->help); - else { + if (c->argmin > ac || ac > c->argmax) { + if (!c->help) + a_fail(a, "bad-syntax", "%s", c->name, "", A_END); + else + a_fail(a, "bad-syntax", "%s", c->name, "%s", c->help, A_END); + } else { a_lock(a); c->func(a, ac, av + 1); a_unlock(a); @@ -1532,7 +1603,7 @@ static void a_line(char *p, size_t len, void *vp) return; } } - a_fail(a, "unknown-command %s", av[0]); + a_fail(a, "unknown-command", "%s", av[0], A_END); } /* --- @a_create@ --- * @@ -1587,7 +1658,7 @@ 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("ADMIN accept-error -- %s", strerror(errno)); + a_warn("ADMIN", "accept-error", "?ERRNO", A_END); return; } a_create(nfd, nfd, 0); diff --git a/chal.c b/chal.c index a8cd4a43..5258cf9c 100644 --- a/chal.c +++ b/chal.c @@ -109,12 +109,12 @@ int c_check(buf *b) int ok; if ((p = buf_get(b, sz)) == 0) { - a_warn("CHAL invalid-challenge"); + a_warn("CHAL", "invalid-challenge", A_END); goto fail; } IF_TRACING(T_CHAL, trace_block(T_CRYPTO, "chal: check challenge", p, sz); ) if (!mac) { - a_warn("CHAL impossible-challenge"); + a_warn("CHAL", "impossible-challenge", A_END); goto fail; } h = GM_INIT(mac); @@ -122,16 +122,12 @@ int c_check(buf *b) ok = (memcmp(GH_DONE(h, 0), p + 4, algs.tagsz) == 0); GH_DESTROY(h); if (!ok) { - a_warn("CHAL incorrect-tag"); + a_warn("CHAL", "incorrect-tag", A_END); goto fail; } seq = LOAD32(p); - switch (seq_check(&iseq, LOAD32(p))) { - case SEQ_OK: break; - case SEQ_OLD: a_warn("CHAL replay old-sequence"); goto fail; - case SEQ_REPLAY: a_warn("CHAL replay duplicated-sequence"); goto fail; - default: abort(); - } + if (seq_check(&iseq, LOAD32(p), "CHAL")) + goto fail; T( trace(T_CHAL, "chal: checked challenge %lu", (unsigned long)seq); ) return (0); diff --git a/doc/tripe-admin.5 b/doc/tripe-admin.5 index 4afa6a9f..5d07d690 100644 --- a/doc/tripe-admin.5 +++ b/doc/tripe-admin.5 @@ -554,11 +554,11 @@ The .B tripe server is already running as a daemon. .TP -.BI "bad-addr-syntax \-\- " message +.BI "bad-addr-syntax " message (For commands accepting socket addresses.) The address couldn't be understood. .TP -.BI "bad-syntax \-\- " message +.BI "bad-syntax " cmd " " message (For any command.) The command couldn't be understood: e.g., the number of arguments was wrong. .TP @@ -584,7 +584,7 @@ An unknown trace option was requested. .BR WATCH .) An unknown watch option was requested. .TP -.BI "daemon-error \-\- " message +.BI "daemon-error " ecode " " message (For .BR DAEMON .) An error occurred during the attempt to become a daemon, as reported by @@ -692,6 +692,22 @@ command. .SH "WARNINGS" There are many possible warnings. They are categorized according to their first tokens. +.PP +Many of these warnings report system errors. These are reported as a +pair of tokens, described below as +.I ecode +and +.IR message . +The +.I ecode +is a string of the form +.BI E number +giving the +.BR errno (3) +value of the error; the +.I message +is the `human-readable' form of the message, as reported by +.BR strerror (3). .SS "ABORT warnings" These all indicate that the .B tripe @@ -704,11 +720,11 @@ 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 +.BI "ADMIN accept-error " ecode " " message There was an error while attempting to accept a connection from a new client. .TP -.BI "ADMIN client-read-error \-\- " message +.BI "ADMIN client-write-error " ecode " " message There was an error sending data to a client. The connection to the client has been closed. .SS "CHAL warnings" @@ -738,18 +754,18 @@ Challenge received was old, but maybe not actually a replay. Try again. These indicate a problem with the keyring files, or the keys stored in them. .TP -.BI "KEYMGMT bad-private-key \-\- " message +.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 +.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 +.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). @@ -763,7 +779,7 @@ 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 +.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" @@ -905,10 +921,10 @@ Either there's a bug, or the bad guys are playing tricks on you. 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 +.BI "PEER \- socket-read-error " ecode " " message An error occurred trying to read an incoming packet. .TP -.BI "PEER " peer " socket-write-error \-\- " message +.BI "PEER " peer " socket-write-error " ecode " " message An error occurred attempting to send a network packet. We lost that one. .TP @@ -952,7 +968,7 @@ A client of the administration interface issued a .B QUIT command. .TP -.BI "SERVER select-error \-\- " message +.BI "SERVER select-error " ecode " " 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" @@ -980,15 +996,15 @@ create some more .BI /dev/tun nn files, it will work. .TP -.BI "TUN - open-error " device " \-\- " message +.BI "TUN - " tun-name " open-error " device " " ecode " " message An attempt to open the tunnel device file .I device failed. .TP -.BI "TUN \- linux config-error \-\- " message +.BI "TUN \- linux config-error " ecode " " message Configuring the Linux TUN/TAP interface failed. .TP -.BI "TUN " ifname " read-error \-\- " message +.BI "TUN " ifname " " tun-name " read-error " ecode " " message Reading from the tunnel device failed. .TP .BI "TUN " ifname " slip bad-escape" @@ -1005,7 +1021,7 @@ The SLIP driver encountered an escaped `end' marker. This probably means that someone's been sending it junk. The erroneous packet is discarded, and we hope that we've rediscovered synchronization. .TP -.BI "TUN \- slip fork-error \-\- " message +.BI "TUN \- slip fork-error " ecode " " message The SLIP driver encountered an error forking a child process while allocating a new dynamic interface. .TP @@ -1016,23 +1032,23 @@ or use dynamic SLIP interface allocation. .BI "TUN " ifname " slip overflow" The SLIP driver gave up reading a packet because it got too large. .TP -.BI "TUN \- slip pipe-error \-\- " message +.BI "TUN \- slip pipe-error " ecode " " message The SLIP driver encountered an error creating pipes while allocating a new dynamic interface. .TP -.BI "TUN \- slip read-ifname-failed \-\- " message +.BI "TUN \- slip read-ifname-failed " ecode " " message The SLIP driver encountered an error reading the name of a dynamically allocated interface. Maybe the allocation script is broken. .TP -.BI "TUN \- unet config-error \-\- " message +.BI "TUN \- unet config-error " ecode " " message Configuring the Linux Unet interface failed. Unet is obsolete and shouldn't be used any more. .TP -.BI "TUN \- unet getinfo-error \-\- " message +.BI "TUN \- unet getinfo-error " ecode " " 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 +.BI "TUN \- unet ifname-too-long" The Unet interface's name overflowed, so we couldn't read it properly. Unet is obsolete and shouldn't be used any more. .SS "USER warnings" diff --git a/keyexch.c b/keyexch.c index e62809ef..ea4748e2 100644 --- a/keyexch.c +++ b/keyexch.c @@ -430,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("KX %s bad-expected-reply-log", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "bad-expected-reply-log", A_END); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: computed challenge = %s", gestr(gg, y)); })) @@ -464,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("KX %s unexpected %s", p_name(kx->p), pkname[msg]); + a_warn("KX", "?PEER", kx->p, "unexpected", "%s", pkname[msg], A_END); goto bad; } @@ -474,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("KX %s invalid %s", p_name(kx->p), pkname[msg]); + a_warn("KX", "?PEER", kx->p, "invalid", "%s", pkname[msg], A_END); goto bad; } @@ -491,7 +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)); + a_warn("KX", "?PEER", p_name, "sending-cookie", A_END); b = p_txstart(kx->p, MSG_KEYEXCH | KX_COOKIE); G_TOBUF(gg, b, kx->c); h = GH_INIT(algs.h); @@ -506,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("KX %s incorrect cookie", p_name(kx->p)); + a_warn("KX", "?PEER", "incorrect", "cookie", A_END); goto bad; } @@ -727,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("KX %s incorrect cookie", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "incorrect", "cookie", A_END); goto bad; } if ((kxc = kxc_byhc(kx, hc_in)) == 0) { - a_warn("KX %s unknown-challenge", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unknown-challenge", A_END); goto bad; } @@ -739,7 +739,7 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in, if (!kxc->r) { if (!ck) { - a_warn("KX %s unexpected switch-rq", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "switch-rq", A_END); goto bad; } if ((r = getreply(kx, kxc->c, ck)) == 0) @@ -752,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("KX %s decrypt-failed reply", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "decrypt-failed", "reply", A_END); goto bad; } buf_init(b, BBASE(&bb), BLEN(&bb)); r = G_CREATE(gg); if (G_FROMBUF(gg, b, r)) { - a_warn("KX %s invalid reply", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END); 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("KX %s incorrect reply", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "incorrect", "reply", A_END); goto bad; } @@ -822,20 +822,20 @@ static int doreply(keyexch *kx, buf *b) kxchal *kxc; if (kx->s != KXS_CHAL && kx->s != KXS_COMMIT) { - a_warn("KX %s unexpected-reply", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "reply", A_END); 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("KX %s invalid reply", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END); goto bad; } if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_REPLY, hc_in, hc_out, ck, b)) == 0) goto bad; if (BLEFT(b)) { - a_warn("KX %s invalid reply", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END); goto bad; } if (kx->s == KXS_CHAL) { @@ -865,7 +865,7 @@ static void kxfinish(keyexch *kx) ks_activate(kxc->ks); settimer(kx, ks_tregen(kxc->ks)); kx->s = KXS_SWITCH; - a_notify("KXDONE %s", p_name(kx->p)); + a_notify("KXDONE", "?PEER", kx->p, A_END); p_stats(kx->p)->t_kx = time(0); } @@ -886,21 +886,21 @@ 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("KX %s invalid switch-rq", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "switch-rq", A_END); 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("KX %s invalid switch-rq", p_name(kx->p)); + a_warn("KX", "?PEER", "invalid", "switch-rq", A_END); 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("KX %s incorrect switch-rq", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "incorrect", "switch-rq", A_END); goto bad; } switch (kx->s) { @@ -934,18 +934,18 @@ static int doswitchok(keyexch *kx, buf *b) buf bb; if (kx->s < KXS_COMMIT) { - a_warn("KX %s unexpected switch-ok", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "switch-ok", A_END); 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("KX %s decrypt-failed switch-ok", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "decrypt-failed", "switch-ok", A_END); goto bad; } buf_init(b, BBASE(&bb), BLEN(&bb)); if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) { - a_warn("KX %s invalid switch-ok", p_name(kx->p)); + a_warn("KX", "?PEER", "invalid", "switch-ok", A_END); goto bad; } IF_TRACING(T_KEYEXCH, { @@ -953,7 +953,7 @@ static int doswitchok(keyexch *kx, buf *b) hswok, algs.hashsz); }) if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) { - a_warn("KX %s incorrect switch-ok", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "incorrect", "switch-ok", A_END); goto bad; } if (kx->s < KXS_SWITCH) @@ -1059,7 +1059,7 @@ static int checkpub(keyexch *kx) now = time(0); if (KEY_EXPIRED(now, kx->texp_kpub)) { stop(kx); - a_warn("KX %s public-key-expired", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "public-key-expired", A_END); G_COPY(gg, kx->kpub, gg->i); kx->f &= ~KXF_PUBKEY; return (-1); @@ -1088,7 +1088,7 @@ void kx_start(keyexch *kx, int forcep) if (forcep || !VALIDP(kx, now)) { stop(kx); start(kx, now); - a_notify("KXSTART %s", p_name(kx->p)); + a_notify("KXSTART", "?PEER", kx->p, A_END); } resend(kx); } @@ -1139,7 +1139,7 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) rc = doswitchok(kx, b); break; default: - a_warn("KX %s unknown-message 0x%02x", p_name(kx->p), msg); + a_warn("KX", "?PEER", kx->p, "unknown-message", "0x%02x", msg, A_END); rc = -1; break; } diff --git a/keymgmt.c b/keymgmt.c index c7199e56..7163ddda 100644 --- a/keymgmt.c +++ b/keymgmt.c @@ -301,7 +301,13 @@ 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("KEYMGMT key-file-error %s:%i -- %s", file, line, msg); } +{ + a_warn("KEYMGMT", + "key-file-error", + "%s:%i", file, line, + "%s", msg, + A_END); +} /* --- @loadpriv@ --- * * @@ -471,7 +477,7 @@ int km_reload(void) T( trace(T_KEYMGMT, "keymgmt: private keyring updated: reloading..."); ) DRESET(&d); if (loadpriv(&d)) - a_warn("KEYMGMT bad-private-key -- %s", d.buf); + a_warn("KEYMGMT", "bad-private-key", "%s", d.buf, A_END); else reload = 1; } @@ -483,7 +489,7 @@ int km_reload(void) kf = kf_pub; DRESET(&d); if (loadpub(&d)) - a_warn("KEYMGMT bad-public-keyring -- %s", d.buf); + a_warn("KEYMGMT", "bad-public-keyring", "%s", d.buf, A_END); else { reload = 1; key_close(kf); @@ -558,7 +564,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("KEYMGMT public-key %s not-found", tag); + a_warn("KEYMGMT", "public-key", "%s", tag, "not-found", A_END); goto done; } @@ -568,14 +574,17 @@ int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp) if (strcmp((*ko)->ty, k->type) == 0) goto tymatch; } - a_warn("KEYMGMT public-key %s unknown-type %s", t.buf, k->type); + a_warn("KEYMGMT", + "public-key", "%s", t.buf, + "unknown-type", "%s", k->type, + A_END); goto done; tymatch:; /* --- Load the key --- */ if ((e = (*ko)->loadpub(*kd, &g, &p, &t)) != 0) { - a_warn("KEYMGMT public-key %s bad -- %s", t.buf, e); + a_warn("KEYMGMT", "public-key", "%s", t.buf, "bad", "%s", e, A_END); goto done; } @@ -586,25 +595,34 @@ tymatch:; */ if (!group_samep(gg, g)) { - a_warn("KEYMGMT public-key %s incorrect-group", t.buf); + a_warn("KEYMGMT", "public-key", "%s", t.buf, "incorrect-group", A_END); goto done; } /* --- Check the public group element --- */ if (group_check(gg, p)) { - a_warn("KEYMGMT public-key %s bad-public-group-element", t.buf); + a_warn("KEYMGMT", + "public-key", "%s", t.buf, + "bad-public-group-element", + A_END); goto done; } /* --- Check the algorithms --- */ if ((e = algs_get(&a, kf_pub, k)) != 0) { - a_warn("KEYMGMT public-key %s bad-algorithm-selection %s", t.buf, e); + a_warn("KEYMGMT", + "public-key", "%s", t.buf, + "bad-algorithm-selection", e, + A_END); goto done; } if (!algs_samep(&a, &algs)) { - a_warn("KEYMGMT public-key %s algorithm-mismatch", t.buf); + a_warn("KEYMGMT", + "public-key", "%s", t.buf, + "algorithm-mismatch", + A_END); goto done; } diff --git a/keyset.c b/keyset.c index 9b804ea6..bb2397fc 100644 --- a/keyset.c +++ b/keyset.c @@ -250,30 +250,6 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq) return (0); } -/* --- @dosequence@ --- * - * - * Arguments: @keyset *ks@ = pointer to a keyset - * @uint32 seq@ = a sequence number from a packet - * - * Returns: Zero if the sequence number is OK, nonzero if it's not. - * - * Use: Checks a sequence number. The data in the keyset which keeps - * track of valid sequence numbers is updated if the sequence - * number given is good. It's assumed that the sequence number - * has already been checked for authenticity. - */ - -static int dosequence(keyset *ks, uint32 seq) -{ - switch (seq_check(&ks->iseq, seq)) { - case SEQ_OK: break; - case SEQ_OLD: a_warn("SYMM replay old-sequence"); return (-1); - case SEQ_REPLAY: a_warn("SYMM replay duplicated-sequence"); return (-1); - default: abort(); - } - return (0); -} - /*----- Operations on a single keyset -------------------------------------*/ /* --- @ks_drop@ --- * @@ -468,7 +444,7 @@ int ks_decrypt(keyset *ks, unsigned ty, buf *b, buf *bb) if (!KEYOK(ks, now) || buf_ensure(bb, BLEN(b)) || dodecrypt(ks, ty, b, bb, &seq) || - dosequence(ks, seq)) + seq_check(&ks->iseq, seq, "SYMM")) return (-1); return (0); } @@ -612,7 +588,7 @@ int ksl_decrypt(keyset **ksroot, unsigned ty, buf *b, buf *bb) ks->seq); ) ks->f &= ~KSF_LISTEN; } - return (dosequence(ks, seq)); + return (seq_check(&ks->iseq, seq, "SYMM")); } } T( trace(T_KEYSET, "keyset: no matching keys, or incorrect MAC"); ) diff --git a/peer.c b/peer.c index 6b746ddb..50dec936 100644 --- a/peer.c +++ b/peer.c @@ -100,7 +100,7 @@ static void p_ponged(peer *p, unsigned msg, buf *b) if (buf_getu32(b, &id) || (magic = buf_get(b, sizeof(pg->magic))) == 0 || BLEFT(b)) { - a_warn("PEER %s malformed-%s", p->spec.name, p_pingtype(msg)); + a_warn("PEER", "?PEER", p, "malformed-%s", p_pingtype(msg), A_END); return; } @@ -108,13 +108,16 @@ static void p_ponged(peer *p, unsigned msg, buf *b) if (pg->id == id) goto found; } - a_warn("PEER %s unexpected-%s 0x%08lx", - p->spec.name, p_pingtype(msg), (unsigned long)id); + a_warn("PEER", + "?PEER", p, + "unexpected-%s", p_pingtype(msg), + "0x%08lx", (unsigned long)id, + A_END); return; found: if (memcmp(magic, pg->magic, sizeof(pg->magic)) != 0) { - a_warn("PEER %s corrupt-%s", p->spec.name, p_pingtype(msg)); + a_warn("PEER", "?PEER", p, "corrupt-%s", p_pingtype(msg), A_END); return; } p_pingdone(pg, PING_OK); @@ -146,7 +149,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("PEER - socket-read-error -- %s", strerror(errno)); + a_warn("PEER", "-", "socket-read-error", "?ERRNO", A_END); return; } @@ -162,13 +165,13 @@ static void p_read(int fd, unsigned mode, void *v) buf_init(&b, buf_i, n); buf_getbyte(&b); if (c_check(&b) || BLEFT(&b)) { - a_warn("PEER - invalid-greeting"); + a_warn("PEER", "-", "invalid-greeting", A_END); return; } - a_notify("GREET %s INET %s %u", - b64_encode(buf_i + 1, n - 1), - inet_ntoa(a.sin.sin_addr), - (unsigned)ntohs(a.sin.sin_port)); + a_notify("GREET", + "?B64", buf_i + 1, (size_t)(n - 1), + "?ADDR", &a, + A_END); return; } @@ -180,8 +183,7 @@ static void p_read(int fd, unsigned mode, void *v) p->spec.sa.sin.sin_port == a.sin.sin_port) goto found; } - a_warn("PEER - unexpected-source INET %s %u", - inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port)); + a_warn("PEER", "-", "unexpected-source", "?ADDR", &a, A_END); return; found: @@ -197,20 +199,24 @@ found: p->st.sz_in += n; buf_init(&b, buf_i, n); if ((ch = buf_getbyte(&b)) < 0) { - a_warn("PEER %s bad-packet no-type", p->spec.name); + a_warn("PEER", "?PEER", p, "bad-packet", "no-type", A_END); return; } switch (ch & MSG_CATMASK) { case MSG_PACKET: if (ch & MSG_TYPEMASK) { - a_warn("PEER %s bad-packet unknown-type 0x%02x", p->spec.name, ch); + a_warn("PEER", + "?PEER", p, + "bad-packet", + "unknown-type", "0x%02x", ch, + A_END); 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("PEER %s decrypt-failed", p->spec.name); + a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); return; } if (BOK(&bb)) { @@ -219,7 +225,7 @@ found: p->t->ops->inject(p->t, &bb); } else { p->st.n_reject++; - a_warn("PEER %s packet-build-failed", p->spec.name); + a_warn("PEER", "?PEER", p, "packet-build-failed", A_END); } break; case MSG_KEYEXCH: @@ -241,7 +247,7 @@ found: buf_init(&bb, buf_t, sizeof(buf_t)); if (ksl_decrypt(&p->ks, ch, &b, &bb)) { p->st.n_reject++; - a_warn("PEER %s decrypt-failed", p->spec.name); + a_warn("PEER", "?PEER", "decrypt-failed", A_END); return; } if (BOK(&bb)) { @@ -256,7 +262,7 @@ found: buf_init(&bb, buf_t, sizeof(buf_t)); if (ksl_decrypt(&p->ks, ch, &b, &bb)) { p->st.n_reject++; - a_warn("PEER %s decrypt-failed", p->spec.name); + a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); return; } if (BOK(&bb)) { @@ -268,7 +274,11 @@ found: break; default: p->st.n_reject++; - a_warn("PEER %s bad-packet unknown-category 0x%02x", p->spec.name, ch); + a_warn("PEER", + "?PEER", p, + "bad-packet", + "unknown-category" "0x%02x", ch, + A_END); break; } } @@ -305,15 +315,14 @@ static void p_setkatimer(peer *); static int p_dotxend(peer *p) { if (!BOK(&p->b)) { - a_warn("PEER %s packet-build-failed", p->spec.name); + a_warn("PEER", "?PEER", p, "packet-build-failed", A_END); return (0); } 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->spec.sa.sa, p->spec.sasz) < 0) { - a_warn("PEER %s socket-write-error -- %s", - p->spec.name, strerror(errno)); + a_warn("PEER", "?PEER", p, "socket-write-error", "?ERRNO", A_END); return (0); } else { p->st.n_out++; @@ -686,19 +695,13 @@ peer *p_create(peerspec *spec) if (peers) peers->prev = p; peers = p; - switch (p->spec.sa.sa.sa_family) { - case AF_INET: - a_notify("ADD %s %s INET %s %u", - spec->name, - p->t->ops->ifname(p->t), - inet_ntoa(p->spec.sa.sin.sin_addr), - (unsigned)ntohs(p->spec.sa.sin.sin_port)); - break; - default: - a_notify("ADD %s %s UNKNOWN", spec->name, p->t->ops->ifname(p->t)); - break; - } - a_notify("KXSTART %s", spec->name); /* Couldn't tell anyone before */ + a_notify("ADD", + "?PEER", p, + "%s", p->t->ops->ifname(p->t), + "?ADDR", &p->spec.sa, + A_END); + a_notify("KXSTART", "?PEER", p, A_END); + /* Couldn't tell anyone before */ return (p); tidy_1: @@ -762,7 +765,7 @@ void p_destroy(peer *p) ping *pg, *ppg; T( trace(T_PEER, "peer: destroying peer `%s'", p->spec.name); ) - a_notify("KILL %s", p->spec.name); + a_notify("KILL", "%s", p->spec.name, A_END); ksl_free(&p->ks); kx_free(&p->kx); p->t->ops->destroy(p->t); diff --git a/servutil.c b/servutil.c index f4ab92e3..92a5f775 100644 --- a/servutil.c +++ b/servutil.c @@ -91,32 +91,6 @@ const char *timestr(time_t t) return ((const char *)buf_t); } -/* --- @b64_encode@ --- * - * - * Arguments: @const void *p@ = pointer to some gorp - * @size_t sz@ = size of the gorp - * - * Returns: Pointer to base64-encoded version in @buf_t@. - */ - -const char *b64_encode(const void *p, size_t sz) -{ - base64_ctx b64; - dstr d = DSTR_INIT; - - base64_init(&b64); - b64.indent = ""; - b64.maxline = 0; - base64_encode(&b64, p, sz, &d); - base64_encode(&b64, 0, 0, &d); - while (d.len && d.buf[d.len - 1] == '=') d.len--; - assert(d.len < sizeof(buf_t)); - memcpy(buf_t, d.buf, d.len); - buf_t[d.len] = 0; - dstr_destroy(&d); - return ((const char *)buf_t); -} - /* --- @seq_reset@ --- * * * Arguments: @seqwin *s@ = sequence-checking window @@ -132,20 +106,23 @@ void seq_reset(seqwin *s) { s->seq = 0; s->win = 0; } * * Arguments: @seqwin *s@ = sequence-checking window * @uint32 q@ = sequence number to check + * @const char *service@ = service to report message from * - * Returns: A @SEQ_@ code. + * Returns: Zero on success, nonzero if the sequence number was bad. * * Use: Checks a sequence number against the window, updating things * as necessary. */ -int seq_check(seqwin *s, uint32 q) +int seq_check(seqwin *s, uint32 q, const char *service) { uint32 qbit; uint32 n; - if (q < s->seq) - return (SEQ_OLD); + if (q < s->seq) { + a_warn(service, "replay", "old-sequence", A_END); + return (-1); + } if (q >= s->seq + SEQ_WINSZ) { n = q - (s->seq + SEQ_WINSZ - 1); if (n < SEQ_WINSZ) @@ -155,8 +132,10 @@ int seq_check(seqwin *s, uint32 q) s->seq += n; } qbit = 1 << (q - s->seq); - if (s->win & qbit) - return (SEQ_REPLAY); + if (s->win & qbit) { + a_warn(service, "replay", "duplicated-sequence", A_END); + return (-1); + } s->win |= qbit; return (0); } diff --git a/tripe.c b/tripe.c index 202a843a..be37617a 100644 --- a/tripe.c +++ b/tripe.c @@ -344,10 +344,10 @@ int main(int argc, char *argv[]) if (!sel_select(&sel)) selerr = 0; else if (errno != EINTR && errno != EAGAIN) { - a_warn("SERVER select-error -- %s", strerror(errno)); + a_warn("SERVER", "select-error", "?ERRNO", A_END); selerr++; if (selerr > 8) { - a_warn("ABORT repeated-select-errors"); + a_warn("ABORT", "repeated-select-errors", A_END); abort(); } } diff --git a/tripe.h b/tripe.h index eec40939..25255f32 100644 --- a/tripe.h +++ b/tripe.h @@ -171,12 +171,6 @@ typedef struct seqwin { #define SEQ_WINSZ 32 /* Bits in sequence number window */ -#define SEQ_RESET(iseq) { - -#define SEQ_OK 0 /* Sequence number valid */ -#define SEQ_OLD -1 /* Sequence number too old */ -#define SEQ_REPLAY -2 /* Definitely replayed */ - /* --- A symmetric keyset --- * * * A keyset contains a set of symmetric keys for encrypting and decrypting @@ -747,6 +741,8 @@ extern int c_check(buf */*b*/); /*----- Administration interface ------------------------------------------*/ +#define A_END ((char *)0) + /* --- @a_warn@ --- * * * Arguments: @const char *fmt@ = pointer to format string @@ -1098,16 +1094,6 @@ extern const char *timestr(time_t /*t*/); extern int mystrieq(const char */*x*/, const char */*y*/); -/* --- @b64_encode@ --- * - * - * Arguments: @const void *p@ = pointer to some gorp - * @size_t sz@ = size of the gorp - * - * Returns: Pointer to base64-encoded version in @buf_t@. - */ - -extern const char *b64_encode(const void */*p*/, size_t /*sz*/); - /* --- @seq_reset@ --- * * * Arguments: @seqwin *s@ = sequence-checking window @@ -1123,6 +1109,7 @@ extern void seq_reset(seqwin */*s*/); * * Arguments: @seqwin *s@ = sequence-checking window * @uint32 q@ = sequence number to check + * @const char *service@ = service to report message from * * Returns: A @SEQ_@ code. * @@ -1130,7 +1117,7 @@ extern void seq_reset(seqwin */*s*/); * as necessary. */ -extern int seq_check(seqwin */*s*/, uint32 /*q*/); +extern int seq_check(seqwin */*s*/, uint32 /*q*/, const char */*service*/); /*----- That's all, folks -------------------------------------------------*/ diff --git a/tun-bsd.c b/tun-bsd.c index 22f01e6f..4e8c0bd8 100644 --- a/tun-bsd.c +++ b/tun-bsd.c @@ -76,7 +76,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("TUN %s read-error -- %s", t_ifname(t), strerror(errno)); + a_warn("TUN", "%s", t_ifname(t), "read-error", "?ERRNO", A_END); return; } IF_TRACING(T_TUNNEL, { @@ -125,10 +125,10 @@ static tunnel *t_create(peer *p) T( trace(T_TUNNEL, "tunnel device %u busy: skipping", n); ) break; case ENOENT: - a_warn("TUN - bsd no-tunnel-devices"); + a_warn("TUN", "-", "bsd", "no-tunnel-devices", A_END); return (0); default: - a_warn("TUN - open-error %s -- %s", buf, strerror(errno)); + a_warn("TUN", "-", "open-error", "%s", buf, "?ERRNO", A_END); break; } n++; diff --git a/tun-linux.c b/tun-linux.c index bf449300..3cfa5d72 100644 --- a/tun-linux.c +++ b/tun-linux.c @@ -68,7 +68,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("TUN %s read-error -- %s", t->ifn, strerror(errno)); + a_warn("TUN", "%s", t->ifn, "read-error", "?ERRNO", A_END); return; } IF_TRACING(T_TUNNEL, { @@ -108,7 +108,9 @@ static tunnel *t_create(peer *p) tunnel *t; if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { - a_warn("TUN - open-error /dev/net/tun -- %s", strerror(errno)); + a_warn("TUN", "-", "linux", + "open-error", "/dev/net/tun", "?ERRNO", + A_END); return (0); } fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); @@ -116,7 +118,7 @@ static tunnel *t_create(peer *p) iff.ifr_name[0] = 0; iff.ifr_flags = IFF_TUN | IFF_NO_PI; if ((f = ioctl(fd, TUNSETIFF, &iff)) < 0) { - a_warn("TUN - linux config-error -- %s", strerror(errno)); + a_warn("TUN", "-", "linux", "config-error", "?ERRNO", A_END); close(fd); return (0); } diff --git a/tun-slip.c b/tun-slip.c index 2b74a774..2efda890 100644 --- a/tun-slip.c +++ b/tun-slip.c @@ -100,11 +100,11 @@ static void t_read(int fd, unsigned mode, void *v) #endif errno == EAGAIN) return; - a_warn("TUN %s read-error -- %s", t->sl->name, strerror(errno)); + a_warn("TUN", "%s", t->sl->name, "read-error", "?ERRNO", A_END); return; } if (!n) { - a_warn("TUN %s slip eof", t->sl->name); + a_warn("TUN", "%s", t->sl->name, "slip", "eof", A_END); t->st = ST_EOF; sel_rmfile(&t->f); return; @@ -126,7 +126,7 @@ static void t_read(int fd, unsigned mode, void *v) if (st & ST_BAD) ; else if (st & ST_ESC) - a_warn("TUN %s slip escape-end", t->sl->name); + a_warn("TUN", "%s", t->sl->name, "slip", "escape-end", A_END); else if (q == t->buf) { T( trace(T_TUNNEL, "tun-slip: empty packet"); ) } else { @@ -143,7 +143,7 @@ static void t_read(int fd, unsigned mode, void *v) break; case SL_ESC: if ((st & ST_ESC) && !(st & ST_BAD)) { - a_warn("TUN %s slip bad-escape", t->sl->name); + a_warn("TUN", "%s", t->sl->name, "slip", "bad-escape", A_END); st |= ST_BAD; } else st |= ST_ESC; @@ -158,7 +158,7 @@ static void t_read(int fd, unsigned mode, void *v) goto emit; default: if ((st & ST_ESC) && !(st & ST_BAD)) { - a_warn("TUN %s slip bad-escape", t->sl->name); + a_warn("TUN", "%s", t->sl->name, "slip", "bad-escape", A_END); st |= ST_BAD; } emit: @@ -166,7 +166,7 @@ static void t_read(int fd, unsigned mode, void *v) if (q < ll) *q++ = o; else { - a_warn("TUN %s slip overflow", t->sl->name); + a_warn("TUN", "%s", t->sl->name, "slip", "overflow", A_END); st |= ST_BAD; } } @@ -282,18 +282,18 @@ static tunnel *t_create(peer *p) /* --- If no dynamic interfaces are available, give up --- */ if (!slipcmd) { - a_warn("TUN - slip no-slip-interfaces"); + a_warn("TUN", "-", "slip", "no-slip-interfaces", A_END); goto fail; } /* --- Fork off a child process to create a dynamic SLIP interface --- */ if (pipe(pin) || pipe(pout)) { - a_warn("TUN - slip pipe-error -- %s", strerror(errno)); + a_warn("TUN", "-", "slip", "pipe-error", "?ERRNO", A_END); goto fail; } if ((kid = fork()) < 0) { - a_warn("TUN - slip fork-error -- %s", strerror(errno)); + a_warn("TUN", "-", "slip", "fork-error", "?ERRNO", A_END); goto fail; } if (!kid) { @@ -313,7 +313,7 @@ static tunnel *t_create(peer *p) for (;;) { errno = EIO; if (read(pout[0], &ch, 1) != 1 || ch == SL_END) { - a_warn("TUN - slip read-ifname-failed -- %s", strerror(errno)); + a_warn("TUN", "-", "slip", "read-ifname-failed", "?ERRNO", A_END); goto fail; } if (ch == '\n') diff --git a/tun-unet.c b/tun-unet.c index c93803ee..c2b6e771 100644 --- a/tun-unet.c +++ b/tun-unet.c @@ -60,11 +60,11 @@ static const char *t_ifname(tunnel *t) static char b[UNET_NAMEMAX]; struct unet_info uni; if (ioctl(t->f.fd, UNIOCGINFO, &uni)) { - a_warn("TUN - unet getinfo-error -- %s", strerror(errno)); + a_warn("TUN", "-", "unet", "getinfo-error", "?ERRNO", A_END); return (""); } if (strlen(uni.uni_ifname) + 1 > sizeof(b)) { - a_warn("TUN - unet ifname-too-long"); + a_warn("TUN", "-", "unet", "ifname-too-long", A_END); return (""); } strcpy(b, uni.uni_ifname); @@ -90,7 +90,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("TUN %s read-error -- %s", t_ifname(t), strerror(errno)); + a_warn("TUN", "%s", t_ifname(t), "read-error", "?ERRNO", A_END); return; } IF_TRACING(T_TUNNEL, { @@ -130,13 +130,13 @@ static tunnel *t_create(peer *p) int f; if ((fd = open("/dev/unet", O_RDWR)) < 0) { - a_warn("TUN - open-error /dev/unet -- %s", strerror(errno)); + a_warn("TUN", "-", "unet", "open-error", "/dev/unet", "?ERRNO", A_END); return (0); } fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); if ((f = ioctl(fd, UNIOCGIFFLAGS)) < 0 || ioctl(fd, UNIOCSIFFLAGS, f | IFF_POINTOPOINT)) { - a_warn("TUN - unet config-error -- %s", strerror(errno)); + a_warn("TUN", "-", "unet", "config-error", "?ERRNO", A_END); close(fd); return (0); } -- [mdw]