X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/8ed35e02a3f3d9151794e82d9b7ad68bceb04713..813d2de98ea1bc45a68c3262c1df87f0834bd0ab:/server/admin.c diff --git a/server/admin.c b/server/admin.c index 16ab8a35..e39658ef 100644 --- a/server/admin.c +++ b/server/admin.c @@ -9,19 +9,18 @@ * * 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 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 3 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. + * 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. + * along with TrIPE. If not, see . */ /*----- Header files ------------------------------------------------------*/ @@ -237,7 +236,7 @@ static void a_flush(int fd, unsigned mode, void *v) * * Arguments: @dstr *d@ = where to leave the formatted message * @const char *fmt@ = pointer to format string - * @va_list ap@ = arguments in list + * @va_list *ap@ = arguments in list * * Returns: --- * @@ -262,17 +261,17 @@ static void a_flush(int fd, unsigned mode, void *v) * * "[!]..." ... -- @dstr_putf@-like string as single token */ -void a_vformat(dstr *d, const char *fmt, va_list ap) +void a_vformat(dstr *d, const char *fmt, va_list *ap) { dstr dd = DSTR_INIT; while (fmt) { if (*fmt == '*') { if (d->len) dstr_putc(d, ' '); - dstr_vputf(d, fmt + 1, &ap); + dstr_vputf(d, fmt + 1, ap); } else if (*fmt == '?') { if (strcmp(fmt, "?ADDR") == 0) { - const addr *a = va_arg(ap, const addr *); + const addr *a = va_arg(*ap, const addr *); switch (a->sa.sa_family) { case AF_INET: u_quotify(d, "INET"); @@ -283,21 +282,18 @@ void a_vformat(dstr *d, const char *fmt, va_list ap) 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; + const octet *p = va_arg(*ap, const octet *); + size_t n = va_arg(*ap, size_t); + codec *b64 = base64_class.encoder(CDCF_NOEQPAD, "", 0); 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--; + b64->ops->code(b64, p, n, d); + b64->ops->code(b64, 0, 0, d); + b64->ops->destroy(b64); } else if (strcmp(fmt, "?TOKENS") == 0) { - const char *const *av = va_arg(ap, const char *const *); + const char *const *av = va_arg(*ap, const char *const *); while (*av) u_quotify(d, *av++); } else if (strcmp(fmt, "?PEER") == 0) - u_quotify(d, p_name(va_arg(ap, peer *))); + u_quotify(d, p_name(va_arg(*ap, peer *))); else if (strcmp(fmt, "?ERRNO") == 0) { dstr_putf(d, " E%d", errno); u_quotify(d, strerror(errno)); @@ -306,11 +302,12 @@ void a_vformat(dstr *d, const char *fmt, va_list ap) } else { if (*fmt == '!') fmt++; DRESET(&dd); - dstr_vputf(&dd, fmt, &ap); + dstr_vputf(&dd, fmt, ap); u_quotify(d, dd.buf); } - fmt = va_arg(ap, const char *); + fmt = va_arg(*ap, const char *); } + dstr_putz(d); dstr_destroy(&dd); } @@ -331,7 +328,7 @@ void a_format(dstr *d, const char *fmt, ...) va_list ap; va_start(ap, fmt); - a_vformat(d, fmt, ap); + a_vformat(d, fmt, &ap); va_end(ap); } @@ -341,7 +338,7 @@ void a_format(dstr *d, const char *fmt, ...) * @const char *status@ = status code to report * @const char *tag@ = tag string, or null * @const char *fmt@ = pointer to format string - * @va_list ap@ = arguments in list + * @va_list *ap@ = arguments in list * @...@ = other arguments * * Returns: --- @@ -350,7 +347,7 @@ void a_format(dstr *d, const char *fmt, ...) */ static void a_vwrite(admin *a, const char *status, const char *tag, - const char *fmt, va_list ap) + const char *fmt, va_list *ap) { dstr d = DSTR_INIT; @@ -369,11 +366,11 @@ static void a_write(admin *a, const char *status, const char *tag, va_list ap; va_start(ap, fmt); - a_vwrite(a, status, tag, fmt, ap); + a_vwrite(a, status, tag, fmt, &ap); va_end(ap); } -/* --- @a_ok@, @a_info@, @a_fail@ --- * +/* --- @a_ok@, @a_fail@ --- * * * Arguments: @admin *a@ = connection * @const char *fmt@ = format string @@ -386,21 +383,32 @@ static void a_write(admin *a, const char *status, const char *tag, static void a_ok(admin *a) { a_write(a, "OK", 0, A_END); } -static void a_info(admin *a, const char *fmt, ...) +static void a_fail(admin *a, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - a_vwrite(a, "INFO", 0, fmt, ap); + a_vwrite(a, "FAIL", 0, fmt, &ap); va_end(ap); } -static void a_fail(admin *a, const char *fmt, ...) +/* --- @a_info@ --- * + * + * Arguments: @admin *a@ = connection + * @const char *fmt@ = format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Report information to an admin client. + */ + +void a_info(admin *a, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - a_vwrite(a, "FAIL", 0, fmt, ap); + a_vwrite(a, "INFO", 0, fmt, &ap); va_end(ap); } @@ -411,7 +419,7 @@ static void a_fail(admin *a, const char *fmt, ...) * @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 + * @va_list *ap@ = arguments in list * @...@ = other arguments * * Returns: --- @@ -445,7 +453,7 @@ static void a_rawalert(unsigned f_and, unsigned f_eq, const char *status, } static void a_valert(unsigned f_and, unsigned f_eq, const char *status, - const char *fmt, va_list ap) + const char *fmt, va_list *ap) { dstr d = DSTR_INIT; @@ -462,7 +470,7 @@ static void a_alert(unsigned f_and, unsigned f_eq, const char *status, va_list ap; va_start(ap, fmt); - a_valert(f_and, f_eq, status, fmt, ap); + a_valert(f_and, f_eq, status, fmt, &ap); va_end(ap); } @@ -482,11 +490,11 @@ void a_warn(const char *fmt, ...) va_start(ap, fmt); if (flags & F_INIT) - a_valert(0, 0, "WARN", fmt, ap); + a_valert(0, 0, "WARN", fmt, &ap); else { dstr d = DSTR_INIT; fprintf(stderr, "%s: ", QUIS); - a_vformat(&d, fmt, ap); + a_vformat(&d, fmt, &ap); dstr_putc(&d, '\n'); dstr_write(&d, stderr); dstr_destroy(&d); @@ -526,7 +534,7 @@ void a_notify(const char *fmt, ...) va_list ap; va_start(ap, fmt); - a_valert(AF_NOTE, AF_NOTE, "NOTE", fmt, ap); + a_valert(AF_NOTE, AF_NOTE, "NOTE", fmt, &ap); va_end(ap); } @@ -696,7 +704,7 @@ static void a_bginfo(admin_bgop *bg, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - a_vwrite(bg->a, "INFO", bg->tag, fmt, ap); + a_vwrite(bg->a, "INFO", bg->tag, fmt, &ap); va_end(ap); } @@ -704,7 +712,7 @@ static void a_bgfail(admin_bgop *bg, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - a_vwrite(bg->a, "FAIL", bg->tag, fmt, ap); + a_vwrite(bg->a, "FAIL", bg->tag, fmt, &ap); va_end(ap); } @@ -1012,12 +1020,14 @@ static void a_resolved(struct hostent *h, void *v) { admin_resop *r = v; - T( trace(T_ADMIN, "admin: resop %s resolved", BGTAG(r)); ) - TIMER; + QUICKRAND; if (!h) { + T( trace(T_ADMIN, "admin: resop %s failed: %s", + BGTAG(r), hstrerror(h_errno)); ) a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END); r->func(r, ARES_FAIL); } else { + T( trace(T_ADMIN, "admin: resop %s ok", BGTAG(r)); ) memcpy(&r->sa.sin.sin_addr, h->h_addr, sizeof(struct in_addr)); r->func(r, ARES_OK); } @@ -1102,7 +1112,6 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, goto fail; } r->sa.sin.sin_family = AF_INET; - r->sasz = sizeof(r->sa.sin); r->addr = xstrdup(av[i]); if (!av[i + 1]) pt = TRIPE_PORT; @@ -1215,7 +1224,6 @@ static void a_doadd(admin_resop *r, int rc) T( trace(T_ADMIN, "admin: done add op %s", BGTAG(add)); ) if (rc == ARES_OK) { - add->peer.sasz = add->r.sasz; add->peer.sa = add->r.sa; if (p_findbyaddr(&add->r.sa)) a_bgfail(&add->r.bg, "peer-addr-exists", "?ADDR", &add->r.sa, A_END); @@ -1228,6 +1236,7 @@ static void a_doadd(admin_resop *r, int rc) } if (add->peer.tag) xfree(add->peer.tag); + if (add->peer.privtag) xfree(add->peer.privtag); xfree(add->peer.name); } @@ -1277,14 +1286,12 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) OPTTIME("-keepalive", t, { add->peer.t_ka = t; }) OPT("-cork", { add->peer.f |= KXF_CORK; }) OPTARG("-key", arg, { - if (add->peer.tag) - xfree(add->peer.tag); + if (add->peer.tag) xfree(add->peer.tag); add->peer.tag = xstrdup(arg); }) OPT("-mobile", { add->peer.f |= PSF_MOBILE; }) OPTARG("-priv", arg, { - if (add->peer.privtag) - xfree(add->peer.privtag); + if (add->peer.privtag) xfree(add->peer.privtag); add->peer.privtag = xstrdup(arg); }) }); @@ -1661,7 +1668,24 @@ static void acmd_warn(admin *a, unsigned ac, char *av[]) { alertcmd(a, AF_WARN, AF_WARN, "WARN", av); } static void acmd_port(admin *a, unsigned ac, char *av[]) - { a_info(a, "%u", p_port(), A_END); a_ok(a); } +{ + int i; + + if (ac) { + for (i = 0; i < NADDRFAM; i++) + if (mystrieq(av[0], aftab[i].name)) goto found; + a_fail(a, "unknown-address-family", "%s", av[0], A_END); + return; + found: + assert(udpsock[i].fd >= 0); + } else { + for (i = 0; i < NADDRFAM; i++) + if (udpsock[i].fd >= 0) goto found; + abort(); + } + a_info(a, "%u", p_port(i), A_END); + a_ok(a); +} static void acmd_daemon(admin *a, unsigned ac, char *av[]) { @@ -1708,7 +1732,7 @@ static void acmd_algs(admin *a, unsigned ac, char *av[]) { peer *p; const kdata *kd; - const group *g; + const dhgrp *g; const algswitch *algs; if (!ac) @@ -1717,31 +1741,24 @@ static void acmd_algs(admin *a, unsigned ac, char *av[]) if ((p = a_findpeer(a, av[0])) == 0) return; kd = p->kx.kpriv; } - g = kd->g; + g = kd->grp; algs = &kd->algs; - a_info(a, - "kx-group=%s", g->ops->name, - "kx-group-order-bits=%lu", (unsigned long)mp_bits(g->r), - "kx-group-elt-bits=%lu", (unsigned long)g->nbits, - A_END); + g->ops->grpinfo(g, a); a_info(a, "hash=%s", algs->h->name, "mgf=%s", algs->mgf->name, "hash-sz=%lu", (unsigned long)algs->h->hashsz, A_END); a_info(a, - "cipher=%s", algs->c->name, - "cipher-keysz=%lu", (unsigned long)algs->cksz, - "cipher-blksz=%lu", (unsigned long)algs->c->blksz, - A_END); - a_info(a, - "cipher-data-limit=%lu", (unsigned long)algs->expsz, + "bulk-transform=%s", algs->bulk->ops->name, + "bulk-overhead=%lu", + (unsigned long)algs->bulk->ops->overhead(algs->bulk), A_END); + algs->bulk->ops->alginfo(algs->bulk, a); a_info(a, - "mac=%s", algs->m->name, - "mac-keysz=%lu", (unsigned long)algs->mksz, - "mac-tagsz=%lu", (unsigned long)algs->tagsz, + "cipher-data-limit=%lu", + (unsigned long)algs->bulk->ops->expsz(algs->bulk), A_END); a_ok(a); } @@ -1785,35 +1802,43 @@ static void acmd_getchal(admin *a, unsigned ac, char *av[]) static void acmd_checkchal(admin *a, unsigned ac, char *av[]) { - base64_ctx b64; + codec *b64 = base64_class.decoder(CDCF_NOEQPAD); + int err; buf b; dstr d = DSTR_INIT; - base64_init(&b64); - base64_decode(&b64, av[0], strlen(av[0]), &d); - 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_END); - else - a_ok(a); + if ((err = b64->ops->code(b64, av[0], strlen(av[0]), &d)) != 0 || + (err = b64->ops->code(b64, 0, 0, &d)) != 0) + a_fail(a, "bad-base64", "%s", codec_strerror(err), A_END); + else { + buf_init(&b, d.buf, d.len); + if (c_check(&b) || BBAD(&b) || BLEFT(&b)) + a_fail(a, "invalid-challenge", A_END); + else + a_ok(a); + } + b64->ops->destroy(b64); dstr_destroy(&d); } static void acmd_greet(admin *a, unsigned ac, char *av[]) { peer *p; - base64_ctx b64; + int err; + codec *b64; dstr d = DSTR_INIT; - if ((p = a_findpeer(a, av[0])) != 0) { - base64_init(&b64); - base64_decode(&b64, av[1], strlen(av[1]), &d); - base64_decode(&b64, 0, 0, &d); + if ((p = a_findpeer(a, av[0])) == 0) return; + b64 = base64_class.decoder(CDCF_NOEQPAD); + if ((err = b64->ops->code(b64, av[1], strlen(av[1]), &d)) != 0 || + (err = b64->ops->code(b64, 0, 0, &d)) != 0) + a_fail(a, "bad-base64", "%s", codec_strerror(err), A_END); + else { p_greet(p, d.buf, d.len); - dstr_destroy(&d); a_ok(a); } + b64->ops->destroy(b64); + dstr_destroy(&d); } static void acmd_addr(admin *a, unsigned ac, char *av[]) @@ -1844,6 +1869,9 @@ static void acmd_peerinfo(admin *a, unsigned ac, char *av[]) a_info(a, "private-key=%s", ptag, "current-private-key=%s", p->kx.kpriv->tag, A_END); a_info(a, "keepalive=%lu", ps->t_ka, A_END); + a_info(a, "corked=%s", BOOL(p->kx.f&KXF_CORK), + "mobile=%s", BOOL(ps->f&PSF_MOBILE), + A_END); a_ok(a); } } @@ -1968,11 +1996,12 @@ static const acmd acmdtab[] = { { "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 }, + { "port", "[FAMILY]", 0, 1, acmd_port }, { "quit", 0, 0, 0, acmd_quit }, { "reload", 0, 0, 0, acmd_reload }, { "servinfo", 0, 0, 0, acmd_servinfo }, { "setifname", "PEER NEW-NAME", 2, 2, acmd_setifname }, + { "stats", "PEER", 1, 1, acmd_stats }, { "svcclaim", "SERVICE VERSION", 2, 2, acmd_svcclaim }, { "svcensure", "SERVICE [VERSION]", 1, 2, acmd_svcensure }, { "svcfail", "JOBID TOKENS...", 1, 0xffff, acmd_svcfail }, @@ -1983,7 +2012,6 @@ static const acmd acmdtab[] = { { "svcrelease", "SERVICE", 1, 1, acmd_svcrelease }, { "svcsubmit", "[OPTIONS] SERVICE TOKENS...", 2, 0xffff, acmd_svcsubmit }, - { "stats", "PEER", 1, 1, acmd_stats }, #ifndef NTRACE { "trace", "[OPTIONS]", 0, 1, acmd_trace }, #endif @@ -2140,7 +2168,7 @@ static void a_line(char *p, size_t len, void *vp) char *av[16 + 1]; size_t ac; - TIMER; + QUICKRAND; if (a->f & AF_DEAD) return; if (!p) { @@ -2222,7 +2250,7 @@ static void a_accept(int fd, unsigned mode, void *v) { int nfd; struct sockaddr_un sun; - size_t sz = sizeof(sun); + socklen_t sz = sizeof(sun); if ((nfd = accept(fd, (struct sockaddr *)&sun, &sz)) < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK && @@ -2352,7 +2380,6 @@ 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);