From: Mark Wooding Date: Sat, 22 Jun 2013 15:23:56 +0000 (+0100) Subject: key/pixie-common.c, progs/pixie.c: Handle error returns better. X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/commitdiff_plain/70a5dedfb44f242c012190f1fa9240241fa0f35f key/pixie-common.c, progs/pixie.c: Handle error returns better. This was rather bad, really. It's still not perfect, by a long way. --- diff --git a/key/pixie-common.c b/key/pixie-common.c index f24b576..2975c20 100644 --- a/key/pixie-common.c +++ b/key/pixie-common.c @@ -181,6 +181,9 @@ void pixie_fdline(int fd, char *buf, size_t sz) int pixie_getpass(const char *prompt, char *buf, size_t sz) { const char *pfd = getenv("CATACOMB_PASSPHRASE_FD"); + struct termios ta; + struct termios ota; + char nl = '\n'; int fd = 0; /* --- See whether a terminal is what's wanted --- */ @@ -189,28 +192,25 @@ int pixie_getpass(const char *prompt, char *buf, size_t sz) fd = atoi(pfd); pixie_fdline(fd, buf, sz); } else { - struct termios ta; - struct termios ota; - char nl = '\n'; - if ((fd = open("/dev/tty", O_RDWR)) < 0) goto fail_0; if (tcgetattr(fd, &ta) < 0) goto fail_1; ota = ta; ta.c_lflag &= ~(ECHO | ISIG); - if (tcsetattr(fd, TCSAFLUSH, &ta)) - goto fail_1; - write(fd, prompt, strlen(prompt)); + if (tcsetattr(fd, TCSAFLUSH, &ta)) goto fail_1; + if (write(fd, prompt, strlen(prompt)) < 0) goto fail_2; pixie_fdline(fd, buf, sz); tcsetattr(fd, TCSAFLUSH, &ota); - write(fd, &nl, 1); + if (write(fd, &nl, 1) < 0) goto fail_1; close(fd); } return (0); /* --- Tidy up if things went wrong --- */ +fail_2: + tcsetattr(fd, TCSAFLUSH, &ota); fail_1: close(fd); fail_0: @@ -273,7 +273,7 @@ int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz) /* --- Send the request --- */ dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag); - write(fd, d.buf, d.len); + if (write(fd, d.buf, d.len) < 0) return (-1); dstr_destroy(&d); /* --- Sort out the result --- */ @@ -325,9 +325,10 @@ void pixie_set(int fd, const char *tag, const char *phrase) */ dstr_putf(&d, "SET %s -- ", tag); - write(fd, d.buf, d.len); - write(fd, phrase, sz); - write(fd, &nl, 1); + if (write(fd, d.buf, d.len) < 0 || + write(fd, phrase, sz) < 0 || + write(fd, &nl, 1) < 0) + return; dstr_destroy(&d); /* --- Pick up the pieces --- */ @@ -358,7 +359,7 @@ void pixie_cancel(int fd, const char *tag) /* --- Send the request --- */ dstr_putf(&d, "FLUSH %s\n", tag); - write(fd, d.buf, d.len); + if (write(fd, d.buf, d.len) < 0) return; dstr_destroy(&d); /* --- Sort out the result --- */ @@ -371,4 +372,3 @@ again: } /*----- That's all, folks -------------------------------------------------*/ - diff --git a/progs/pixie.c b/progs/pixie.c index cb22c0a..79162a8 100644 --- a/progs/pixie.c +++ b/progs/pixie.c @@ -587,21 +587,27 @@ static void pixserv_expire(struct timeval *tv, void *p) * @const char *p@ = pointer to skeleton string * @...@ = other arguments to fill in * - * Returns: --- + * Returns: Zero on success, @-1@ on error. * * Use: Formats a string and emits it to the output file. */ -static void PRINTF_LIKE(2, 3) pixserv_write(pixserv *px, const char *p, ...) +static int PRINTF_LIKE(2, 3) pixserv_write(pixserv *px, const char *p, ...) { dstr d = DSTR_INIT; va_list ap; + int rc; va_start(ap, p); dstr_vputf(&d, p, &ap); - write(px->fd, d.buf, d.len); + rc = write(px->fd, d.buf, d.len); va_end(ap); dstr_destroy(&d); + if (rc < 0) { + pxlog("failed to write to client: %s (closing)", strerror(errno)); + return (-1); + } + return (0); } /* --- @pixserv_timeout@ --- * @@ -654,13 +660,7 @@ static void pixserv_line(char *s, size_t len, void *p) if (!(px->f & px_stdin)) sel_rmtimer(&px->timer); - if (!s) { - if (px->fd != px->b.reader.fd) - close(px->fd); - selbuf_destroy(&px->b); - close(px->b.reader.fd); - return; - } + if (!s) goto close; /* --- Fiddle the timeout --- */ @@ -681,7 +681,7 @@ static void pixserv_line(char *s, size_t len, void *p) /* --- Handle a help request --- */ if (strcmp(q, "help") == 0) { - pixserv_write(px, "\ + if (pixserv_write(px, "\ INFO Commands supported:\n\ INFO HELP\n\ INFO LIST\n\ @@ -691,7 +691,8 @@ INFO FLUSH [tag]\n\ INFO SET tag [expire] -- phrase\n\ INFO QUIT\n\ OK\n\ -"); +")) + goto close; } /* --- List the passphrases --- */ @@ -700,16 +701,18 @@ OK\n\ phrase *p; for (p = p_head; p; p = p->next) { - if (!p->t) - pixserv_write(px, "ITEM %s no-expire\n", p->tag); - else { + if (!p->t) { + if (pixserv_write(px, "ITEM %s no-expire\n", p->tag)) goto close; + } else { struct timeval tv; gettimeofday(&tv, 0); TV_SUB(&tv, &p->timer.tv, &tv); - pixserv_write(px, "ITEM %s %lu\n", p->tag, (unsigned long)tv.tv_sec); + if (pixserv_write(px, "ITEM %s %lu\n", + p->tag, (unsigned long)tv.tv_sec)) + goto close; } } - pixserv_write(px, "OK\n"); + if (pixserv_write(px, "OK\n")) goto close; } /* --- Request a passphrase --- */ @@ -728,13 +731,14 @@ OK\n\ rc = p_get(&p, q, mode, t > timeout ? timeout : t); switch (rc) { case 0: - pixserv_write(px, "OK %s\n", p); + if (pixserv_write(px, "OK %s\n", p)) goto close; break; case -1: - pixserv_write(px, "FAIL error reading passphrase\n"); + if (pixserv_write(px, "FAIL error reading passphrase\n")) + goto close; break; case +1: - pixserv_write(px, "MISSING\n"); + if (pixserv_write(px, "MISSING\n")) goto close; break; } } @@ -745,7 +749,7 @@ OK\n\ else if (strcmp(q, "flush") == 0) { q = str_getword(&s); p_flush(q); - pixserv_write(px, "OK\n"); + if (pixserv_write(px, "OK\n")) goto close; } /* --- Set a passphrase --- */ @@ -753,24 +757,25 @@ OK\n\ else if (strcmp(q, "set") == 0) { char *tag; unsigned long t; - if ((tag = str_getword(&s)) == 0) - pixserv_write(px, "FAIL missing tag\n"); - else if ((q = str_getword(&s)) == 0) - pixserv_write(px, "FAIL no passphrase\n"); - else { + if ((tag = str_getword(&s)) == 0) { + if (pixserv_write(px, "FAIL missing tag\n")) goto close; + } else if ((q = str_getword(&s)) == 0) { + if (pixserv_write(px, "FAIL no passphrase\n")) goto close; + } else { if (strcmp(q, "--") != 0) { t = pixserv_timeout(q); q = str_getword(&s); } else t = pixserv_timeout(0); - if (!q) - pixserv_write(px, "FAIL no passphrase\n"); - else if (strcmp(q, "--") != 0) - pixserv_write(px, "FAIL rubbish found before passphrase\n"); - else { + if (!q) { + if (pixserv_write(px, "FAIL no passphrase\n")) goto close; + } else if (strcmp(q, "--") != 0) { + if (pixserv_write(px, "FAIL rubbish found before passphrase\n")) + goto close; + } else { p_flush(tag); p_add(tag, s, t); - pixserv_write(px, "OK\n"); + if (pixserv_write(px, "OK\n")) goto close; } } } @@ -778,17 +783,26 @@ OK\n\ /* --- Shut the server down --- */ else if (strcmp(q, "quit") == 0) { - if (verbose) + if (verbose) { pxlog("%s client requested shutdown", px->f & px_stdin ? "local" : "remote"); - pixserv_write(px, "OK\n"); + } + if (pixserv_write(px, "OK\n")) goto close; exit(0); } /* --- Report an error for other commands --- */ - else - pixserv_write(px, "FAIL unknown command `%s'\n", q); + else { + if (pixserv_write(px, "FAIL unknown command `%s'\n", q)) goto close; + } + return; + +close: + if (px->fd != px->b.reader.fd) + close(px->fd); + selbuf_destroy(&px->b); + close(px->b.reader.fd); } /* --- @pixserv_create@ --- * @@ -994,7 +1008,10 @@ static void pix_setup(struct sockaddr_un *sun, size_t sz) } else { if (verbose) pxlog("server already running; shutting it down"); - write(fd, "QUIT\n", 5); + if (write(fd, "QUIT\n", 5) < 0) { + die(EXIT_FAILURE, "failed to shut down old server: %s", + strerror(errno)); + } sleep(1); close(fd); } @@ -1038,7 +1055,8 @@ static void c_uline(char *s, size_t len, void *p) c_flags |= cf_uclose; } else { s[len++] = '\n'; - write(c_server.reader.fd, s, len); + if (write(c_server.reader.fd, s, len) < 0) + die(EXIT_FAILURE, "failed to read from stdin: %s", strerror(errno)); } } @@ -1109,8 +1127,8 @@ static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[]) DPUTS(&d, *argv++); } DPUTC(&d, '\n'); - write(fd, d.buf, d.len); - shutdown(fd, 1); + if (write(fd, d.buf, d.len) < 0 || shutdown(fd, 1)) + die(EXIT_FAILURE, "failed to write command: %s", strerror(errno)); c_flags |= cf_uclose | cf_cooked; dstr_destroy(&d); } @@ -1433,7 +1451,7 @@ int main(int argc, char *argv[]) } } #endif - chdir("/"); + DISCARD(chdir("/")); setsid(); if (fork() != 0)