X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/6a2d21e45b210ca761ff900d9b77625e869524f2..2685767a6125c1620719c7de6234aedf41857b7e:/pixie.c diff --git a/pixie.c b/pixie.c index 1ee1bab..363f833 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.10 2001/02/21 20:03:54 mdw Exp $ * * Passphrase pixie for Catacomb * @@ -30,6 +30,46 @@ /*----- Revision history --------------------------------------------------* * * $Log: pixie.c,v $ + * Revision 1.10 2001/02/21 20:03:54 mdw + * Handle select errors (by bombing out). Cosmetic tweak. + * + * Revision 1.9 2001/02/03 16:06:44 mdw + * Don't set a handler for @SIGINT@ if it's ignored at startup. Add some + * error handling for the @select@ loop. + * + * 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 @@ -95,17 +135,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 -----------------------------------------------------*/ @@ -363,6 +401,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 +458,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 +597,7 @@ fail: memset(pp, 0, LBUFSZ); l_free(&lm, pp); } - return (0); + return (-1); #undef LBUFSZ } @@ -574,7 +613,7 @@ typedef struct pixserv { unsigned f; } pixserv; -enum { px_stdin = 1 }; +#define px_stdin 1u #define PIXSERV_TIMEOUT 30 @@ -851,7 +890,7 @@ 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; @@ -957,11 +996,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 +1009,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 +1035,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,8 +1077,10 @@ 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 --- */ @@ -1058,8 +1107,8 @@ static void c_sline(char *s, void *p) selbuf_destroy(&c_client); } exit(0); - } else - puts(s); + } + puts(s); } /* --- @pix_client@ --- * @@ -1077,6 +1126,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 +1152,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 +1179,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 +1244,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 +1398,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 +1440,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); }