X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/6a2d21e45b210ca761ff900d9b77625e869524f2..578a86d91941a0f722b87973d88e84ec2cf9a608:/pixie.c diff --git a/pixie.c b/pixie.c index 1ee1bab..2ce007d 100644 --- a/pixie.c +++ b/pixie.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: pixie.c,v 1.4 2000/06/17 11:50:53 mdw Exp $ + * $Id: pixie.c,v 1.14 2004/04/08 01:36:15 mdw Exp $ * * Passphrase pixie for Catacomb * @@ -27,25 +27,6 @@ * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: pixie.c,v $ - * 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" @@ -95,17 +76,15 @@ /*----- Static variables --------------------------------------------------*/ -static unsigned long timeout = 300; +static unsigned long timeout = 900; static sel_state sel; static unsigned verbose = 1; static const char *command = 0; static lmem lm; static unsigned flags = 0; -enum { - F_SYSLOG = 1, - F_FETCH = 2 -}; +#define F_SYSLOG 1u +#define F_FETCH 2u /*----- Event logging -----------------------------------------------------*/ @@ -131,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) @@ -363,6 +342,7 @@ static int p_request(const char *msg, const char *tag, char *buf, size_t sz) int fd[2]; pid_t kid; int r; + int rc; /* --- Substitute the prompt string into the command --- */ @@ -419,9 +399,9 @@ static int p_request(const char *msg, const char *tag, char *buf, size_t sz) *q = 0; } close(fd[0]); - waitpid(kid, 0, 0); + waitpid(kid, &rc, 0); dstr_destroy(&d); - if (r < 0) + if (r < 0 || rc != 0) goto fail_0; goto ok; @@ -558,7 +538,7 @@ fail: memset(pp, 0, LBUFSZ); l_free(&lm, pp); } - return (0); + return (-1); #undef LBUFSZ } @@ -574,7 +554,7 @@ typedef struct pixserv { unsigned f; } pixserv; -enum { px_stdin = 1 }; +#define px_stdin 1u #define PIXSERV_TIMEOUT 30 @@ -616,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); @@ -654,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: --- @@ -661,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; @@ -851,12 +832,13 @@ static void pixserv_accept(int fd, unsigned mode, void *p) { int nfd; struct sockaddr_un sun; - int sunsz = sizeof(sun); + size_t sunsz = sizeof(sun); 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; } @@ -957,11 +939,11 @@ static void pix_setup(struct sockaddr_un *sun, size_t sz) /* --- Set up the parent directory --- */ { - dstr d = DSTR_INIT; char *p = sun->sun_path; char *q = strrchr(p, '/'); if (q) { + dstr d = DSTR_INIT; struct stat st; DPUTM(&d, p, q - p); @@ -970,8 +952,11 @@ static void pix_setup(struct sockaddr_un *sun, size_t sz) mkdir(d.buf, 0700); if (stat(d.buf, &st)) die(1, "couldn't stat `%s': %s", d.buf, strerror(errno)); + if (!S_ISDIR(st.st_mode)) + die(1, "object `%s' isn't a directory", d.buf); if (st.st_mode & 0077) die(1, "parent directory `%s' has group or world access", d.buf); + dstr_destroy(&d); } } @@ -993,8 +978,13 @@ static void pix_setup(struct sockaddr_un *sun, size_t sz) die(1, "too many retries; giving up"); n--; if (connect(fd, (struct sockaddr *)sun, sz)) { + struct stat st; if (errno != ECONNREFUSED) die(1, "couldn't bind to address: %s", strerror(e)); + if (stat(sun->sun_path, &st)) + die(1, "couldn't stat `%s': %s", sun->sun_path, strerror(errno)); + if (!S_ISSOCK(st.st_mode)) + die(1, "object `%s' isn't a socket", sun->sun_path); if (verbose) log("stale socket found; removing it"); unlink(sun->sun_path); @@ -1030,26 +1020,26 @@ static void pix_setup(struct sockaddr_un *sun, size_t sz) /* --- Variables --- */ static selbuf c_server, c_client; -static c_flags = 0; -enum { cf_uclose = 1, cf_sclose = 2 }; +static unsigned c_flags = 0; + +#define cf_uclose 1u +#define cf_sclose 2u /* --- 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); @@ -1058,8 +1048,8 @@ static void c_sline(char *s, void *p) selbuf_destroy(&c_client); } exit(0); - } else - puts(s); + } + puts(s); } /* --- @pix_client@ --- * @@ -1077,6 +1067,10 @@ static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[]) { int fd; + /* --- Dispose of locked memory --- */ + + l_destroy(&lm); + /* --- Open the socket --- */ if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) @@ -1099,13 +1093,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; dstr_destroy(&d); } /* --- And repeat --- */ - for (;;) - sel_select(&sel); + for (;;) { + if (sel_select(&sel)) + die(EXIT_FAILURE, "select error: %s", strerror(errno)); + } } /*----- Main code ---------------------------------------------------------*/ @@ -1123,7 +1120,7 @@ static void usage(FILE *fp) { pquis(fp, "\ Usage:\n\ - $ [-qvidl] [-c command] [-t timeout] [-s socket]\n\ + $ [-qvfidl] [-c command] [-t timeout] [-s socket]\n\ $ [-s socket] -C [command args...]\n\ "); } @@ -1188,13 +1185,11 @@ int main(int argc, char *argv[]) size_t sz; unsigned f = 0; - enum { - f_bogus = 1, - f_client = 2, - f_stdin = 4, - f_daemon = 8, - f_syslog = 16 - }; +#define f_bogus 1u +#define f_client 2u +#define f_stdin 4u +#define f_daemon 8u +#define f_syslog 16u /* --- Initialize libraries --- */ @@ -1344,8 +1339,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); @@ -1383,16 +1381,31 @@ int main(int argc, char *argv[]) } } #endif + 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); }