key/pixie-common.c, progs/pixie.c: Handle error returns better.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 22 Jun 2013 15:23:56 +0000 (16:23 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 28 Jun 2013 23:31:54 +0000 (00:31 +0100)
This was rather bad, really.  It's still not perfect, by a long way.

key/pixie-common.c
progs/pixie.c

index f24b576..2975c20 100644 (file)
@@ -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");
 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 --- */
   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 {
     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 ((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);
     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 --- */
 
     close(fd);
   }
   return (0);
 
   /* --- Tidy up if things went wrong --- */
 
+fail_2:
+  tcsetattr(fd, TCSAFLUSH, &ota);
 fail_1:
   close(fd);
 fail_0:
 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);
   /* --- 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 --- */
   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);
    */
 
   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 --- */
   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);
   /* --- 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 --- */
   dstr_destroy(&d);
 
   /* --- Sort out the result --- */
@@ -371,4 +372,3 @@ again:
 }
 
 /*----- That's all, folks -------------------------------------------------*/
 }
 
 /*----- That's all, folks -------------------------------------------------*/
-
index cb22c0a..79162a8 100644 (file)
@@ -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
  *
  *             @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.
  */
 
  *
  * 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;
 {
   dstr d = DSTR_INIT;
   va_list ap;
+  int rc;
 
   va_start(ap, p);
   dstr_vputf(&d, p, &ap);
 
   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);
   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@ --- *
 }
 
 /* --- @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 (!(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 --- */
 
 
   /* --- 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) {
   /* --- 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\
 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\
 INFO SET tag [expire] -- phrase\n\
 INFO QUIT\n\
 OK\n\
-");
+"))
+      goto close;
   }
 
   /* --- List the passphrases --- */
   }
 
   /* --- List the passphrases --- */
@@ -700,16 +701,18 @@ OK\n\
     phrase *p;
 
     for (p = p_head; p; p = p->next) {
     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);
        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 --- */
   }
 
   /* --- Request a passphrase --- */
@@ -728,13 +731,14 @@ OK\n\
       rc = p_get(&p, q, mode, t > timeout ? timeout : t);
       switch (rc) {
        case 0:
       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:
          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:
          break;
        case +1:
-         pixserv_write(px, "MISSING\n");
+         if (pixserv_write(px, "MISSING\n")) goto close;
          break;
       }
     }
          break;
       }
     }
@@ -745,7 +749,7 @@ OK\n\
   else if (strcmp(q, "flush") == 0) {
     q = str_getword(&s);
     p_flush(q);
   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 --- */
   }
 
   /* --- Set a passphrase --- */
@@ -753,24 +757,25 @@ OK\n\
   else if (strcmp(q, "set") == 0) {
     char *tag;
     unsigned long t;
   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 (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);
        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) {
   /* --- 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");
       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 --- */
 
     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@ --- *
 }
 
 /* --- @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");
       } 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);
       }
        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';
     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');
       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);
   }
     c_flags |= cf_uclose | cf_cooked;
     dstr_destroy(&d);
   }
@@ -1433,7 +1451,7 @@ int main(int argc, char *argv[])
       }
     }
 #endif
       }
     }
 #endif
-    chdir("/");
+    DISCARD(chdir("/"));
     setsid();
 
     if (fork() != 0)
     setsid();
 
     if (fork() != 0)