X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/9d23d98214827786cccd9699c87327f93f855778..b2776fdf2a98ea586bbdad50eca4ed95e967b0d7:/pixie.c diff --git a/pixie.c b/pixie.c index ecbab8f..af6483a 100644 --- a/pixie.c +++ b/pixie.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: pixie.c,v 1.8 2001/01/25 22:19:31 mdw Exp $ + * $Id$ * * Passphrase pixie for Catacomb * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,70 +15,18 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb 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 Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: pixie.c,v $ - * Revision 1.8 2001/01/25 22:19:31 mdw - * Make flags be unsigned. - * - * Revision 1.7 2000/12/06 20:33:27 mdw - * Make flags be macros rather than enumerations, to ensure that they're - * unsigned. - * - * Revision 1.6 2000/10/08 12:06:46 mdw - * Change size passed to socket function to be a @size_t@. Insert missing - * type name for flag declaration. - * - * Revision 1.5 2000/07/29 22:05:22 mdw - * Miscellaneous tidyings: - * - * * Change the timeout to something more appropriate for real use. - * - * * Check assumptions about object types when binding the socket. In - * particular, don't zap the socket if it's really something else. - * - * * In @p_request@, return a failure if the shell command returned - * nonzero. Fix a bug in @p_get@ which incorrectly passes on a success - * code when this happens. - * - * * Dispose of the locked memory in client mode to avoid being - * antisocial. - * - * * Also in client mode, don't report closure from the server if we're - * running noninteractively. - * - * * Insert a missing option letter into the usage string. - * - * * Change to the root directory after forking in daemon mode. - * - * Revision 1.4 2000/06/17 11:50:53 mdw - * New pixie protocol allowing application to request passphrases and send - * them to the pixie. Use the secure arena interface for the input - * buffer. Extend the input buffer. Other minor fixes. - * - * Revision 1.3 1999/12/22 22:14:40 mdw - * Only produce initialization message if verbose. - * - * Revision 1.2 1999/12/22 22:13:42 mdw - * Fix bug in passphrase flushing loop. - * - * Revision 1.1 1999/12/22 15:58:41 mdw - * Passphrase pixie support. - * - */ - /*----- Header files ------------------------------------------------------*/ #include "config.h" @@ -162,7 +110,7 @@ static void log(const char *p, ...) d.len += strftime(d.buf, d.sz, "%Y-%m-%d %H:%M:%S ", tm); } va_start(ap, p); - dstr_vputf(&d, p, ap); + dstr_vputf(&d, p, &ap); va_end(ap); if (flags & F_SYSLOG) @@ -206,7 +154,7 @@ static void p_free(phrase *p) { if (p->t) sel_rmtimer(&p->timer); - free(p->tag); + xfree(p->tag); l_free(&lm, p->p); p->next->prev = p->prev; p->prev->next = p->next; @@ -249,7 +197,7 @@ static void *p_alloc(size_t sz) return (p); if (P_ROOT->next == P_ROOT) return (0); - if (verbose) { + if (verbose) { log("flushing passphrase `%s' to free up needed space", P_ROOT->next->tag); } @@ -437,7 +385,7 @@ static int p_request(const char *msg, const char *tag, char *buf, size_t sz) if (dup2(fd[1], STDOUT_FILENO) < 0) _exit(127); close(fd[0]); - execl("/bin/sh", "sh", "-c", d.buf, (void *)0); + execl("/bin/sh", "sh", "-c", d.buf, (char *)0); _exit(127); } @@ -648,7 +596,7 @@ static void pixserv_write(pixserv *px, const char *p, ...) va_list ap; va_start(ap, p); - dstr_vputf(&d, p, ap); + dstr_vputf(&d, p, &ap); write(px->fd, d.buf, d.len); va_end(ap); dstr_destroy(&d); @@ -677,7 +625,7 @@ static unsigned long pixserv_timeout(const char *p) case 'h': t *= 60; case 'm': t *= 60; case 's': if (q[1] != 0) - default: t = 0; + default: t = 0; case 0: break; } return (t); @@ -686,6 +634,7 @@ static unsigned long pixserv_timeout(const char *p) /* --- @pixserv_line@ --- * * * Arguments: @char *s@ = pointer to the line read + * @size_t len@ = length of the line * @void *p@ = pointer to server block * * Returns: --- @@ -693,7 +642,7 @@ static unsigned long pixserv_timeout(const char *p) * Use: Handles a line read from the client. */ -static void pixserv_line(char *s, void *p) +static void pixserv_line(char *s, size_t len, void *p) { pixserv *px = p; char *q, *qq; @@ -888,7 +837,8 @@ static void pixserv_accept(int fd, unsigned mode, void *p) if (mode != SEL_READ) return; if ((nfd = accept(fd, (struct sockaddr *)&sun, &sunsz)) < 0) { - if (verbose) + if (verbose && errno != EAGAIN && errno != EWOULDBLOCK && + errno != ECONNABORTED && errno != EPROTO && errno != EINTR) log("new connection failed: %s", strerror(errno)); return; } @@ -1074,24 +1024,23 @@ static unsigned c_flags = 0; #define cf_uclose 1u #define cf_sclose 2u +#define cf_cooked 4u /* --- Line handler functions --- */ -static void c_uline(char *s, void *p) +static void c_uline(char *s, size_t len, void *p) { - size_t sz; if (!s) { selbuf_destroy(&c_client); shutdown(c_server.reader.fd, 1); c_flags |= cf_uclose; } else { - sz = strlen(s); - s[sz++] = '\n'; - write(c_server.reader.fd, s, sz); + s[len++] = '\n'; + write(c_server.reader.fd, s, len); } } -static void c_sline(char *s, void *p) +static void c_sline(char *s, size_t len, void *p) { if (!s) { selbuf_destroy(&c_server); @@ -1100,8 +1049,23 @@ static void c_sline(char *s, void *p) selbuf_destroy(&c_client); } exit(0); - } else + } + if (!(c_flags & cf_cooked)) puts(s); + else { + char *q = str_getword(&s); + if (strcmp(q, "FAIL") == 0) + die(1, "%s", s); + else if (strcmp(q, "INFO") == 0 || + strcmp(q, "ITEM") == 0) + puts(s); + else if (strcmp(q, "OK") == 0) { + if (s && *s) puts(s); + } else if (strcmp(q, "MISSING") == 0) + ; + else + moan("unexpected output: %s %s", q, s); + } } /* --- @pix_client@ --- * @@ -1145,14 +1109,16 @@ static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[]) DPUTC(&d, '\n'); write(fd, d.buf, d.len); shutdown(fd, 1); - c_flags |= cf_uclose; + c_flags |= cf_uclose | cf_cooked; dstr_destroy(&d); - } + } /* --- And repeat --- */ - for (;;) - sel_select(&sel); + for (;;) { + if (sel_select(&sel)) + die(EXIT_FAILURE, "select error: %s", strerror(errno)); + } } /*----- Main code ---------------------------------------------------------*/ @@ -1170,8 +1136,9 @@ static void usage(FILE *fp) { pquis(fp, "\ Usage:\n\ - $ [-qvfidl] [-c command] [-t timeout] [-s socket]\n\ - $ [-s socket] -C [command args...]\n\ + $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\ + $ [-s SOCKET] -C [COMMAND ARGS...]\n\ + $ [-s SOCKET] -P[P] TAG\n\ "); } @@ -1194,6 +1161,9 @@ protect important keys. Options provided:\n\ -u, --usage Show a (very) terse usage summary.\n\ \n\ -C, --client Connect to a running pixie as a client.\n\ +-P, --passphrase Request passphrase TAG and print to stdout.\n\ +-PP, --verify-passphrase\n\ + Verify passphrase TAG and print to stdout.\n\ \n\ -q, --quiet Emit fewer log messages.\n\ -v, --version Emit more log messages.\n\ @@ -1240,6 +1210,8 @@ int main(int argc, char *argv[]) #define f_stdin 4u #define f_daemon 8u #define f_syslog 16u +#define f_fetch 32u +#define f_verify 64u /* --- Initialize libraries --- */ @@ -1267,6 +1239,8 @@ int main(int argc, char *argv[]) { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "client", 0, 0, 'C' }, + { "passphrase", 0, 0, 'P' }, + { "verify-passphrase", 0, 0, '+' }, { "socket", OPTF_ARGREQ, 0, 's' }, { "command", OPTF_ARGREQ, 0, 'c' }, { "fetch", 0, 0, 'f' }, @@ -1279,10 +1253,10 @@ int main(int argc, char *argv[]) /* --- Magic terminator --- */ - { 0, 0, 0, 0 } + { 0, 0, 0, 0 } }; - int i = mdwopt(argc, argv, "hVuqvCs:c:ft:idl", opts, 0, 0, 0); + int i = mdwopt(argc, argv, "hVuqvCPs:c:ft:idl", opts, 0, 0, 0); if (i < 0) break; @@ -1311,6 +1285,17 @@ int main(int argc, char *argv[]) break; case 'C': f |= f_client; + f &= ~f_fetch; + break; + case 'P': + if (!(f & f_fetch)) + f |= f_fetch; + else + f |= f_verify; + break; + case '+': + f |= f_fetch | f_verify; + f &= ~f_client; break; case 's': path = optarg; @@ -1344,11 +1329,26 @@ int main(int argc, char *argv[]) } } - if (f & f_bogus || (optind < argc && !(f & f_client))) { + if (f & f_bogus || + (optind < argc && !(f & (f_client|f_fetch))) || + ((f & f_fetch) && optind != argc - 1)) { usage(stderr); exit(1); } + /* --- Handle request for a passphrase --- */ + + if (f & f_fetch) { + char *buf = l_alloc(&lm, 1024); + passphrase_connect(path); + if (passphrase_read(argv[optind], + (f & f_verify) ? PMODE_VERIFY : PMODE_READ, + buf, 1024)) + die(1, "failed to read passphrase: %s", strerror(errno)); + puts(buf); + return (0); + } + /* --- Set up the socket address --- */ sun = pixie_address(path, &sz); @@ -1389,8 +1389,11 @@ int main(int argc, char *argv[]) { static sig sigint, sigterm, sigquit, sighup; + struct sigaction sa; sig_init(&sel); - sig_add(&sigint, SIGINT, pix_sigdie, 0); + sigaction(SIGINT, 0, &sa); + if (sa.sa_handler != SIG_IGN) + sig_add(&sigint, SIGINT, pix_sigdie, 0); sig_add(&sigterm, SIGTERM, pix_sigdie, 0); sig_add(&sigquit, SIGQUIT, pix_sigflush, 0); sig_add(&sighup, SIGHUP, pix_sigflush, 0); @@ -1407,7 +1410,7 @@ int main(int argc, char *argv[]) /* --- Fork into the background if requested --- */ - if (f & f_daemon) { + if (f & f_daemon) { pid_t kid; if (((f & f_stdin) && @@ -1431,14 +1434,28 @@ int main(int argc, char *argv[]) chdir("/"); setsid(); - if (fork() > 0) + if (fork() != 0) _exit(0); } if (verbose) log("initialized ok"); - for (;;) - sel_select(&sel); + + { + int selerr = 0; + for (;;) { + if (!sel_select(&sel)) + selerr = 0; + else if (errno != EINTR && errno != EAGAIN) { + log("error from select: %s", strerror(errno)); + selerr++; + if (selerr > 8) { + log("too many consecutive select errors: bailing out"); + exit(EXIT_FAILURE); + } + } + } + } return (0); }