Uprating of the passphrase pixie.
authormdw <mdw>
Tue, 5 Apr 2005 20:59:07 +0000 (20:59 +0000)
committermdw <mdw>
Tue, 5 Apr 2005 20:59:07 +0000 (20:59 +0000)
Makefile.m4
passphrase.c
passphrase.h
pixie-client.c [deleted file]
pixie-common.c
pixie.1
pixie.c

index df761d2..2b869f4 100644 (file)
@@ -220,7 +220,7 @@ libcatacomb_la_SOURCES = \
        grand.c keysz.c \
        lcrand.c fibrand.c rc4.c seal.c rand.c noise.c fipstest.c maurer.c \
        arena.c \
        grand.c keysz.c \
        lcrand.c fibrand.c rc4.c seal.c rand.c noise.c fipstest.c maurer.c \
        arena.c \
-       passphrase.c pixie-client.c pixie-common.c lmem.c \
+       passphrase.c pixie-common.c lmem.c \
        tlsprf.c sslprf.c \
        gfshare.c \
        MP_SOURCES karatsuba.h \
        tlsprf.c sslprf.c \
        gfshare.c \
        MP_SOURCES karatsuba.h \
@@ -280,7 +280,7 @@ hashsum_SOURCES = hashsum.c
 rspit_SOURCES = rspit.c
 factorial_SOURCES = factorial.c
 perftest_SOURCES = perftest.c
 rspit_SOURCES = rspit.c
 factorial_SOURCES = factorial.c
 perftest_SOURCES = perftest.c
-pixie_SOURCES = pixie.c pixie-common.c lmem.c arena.c
+pixie_SOURCES = pixie.c pixie-common.c lmem.c arena.c passphrase.c
 pixie_LDADD =
 mkphrase_SOURCES = mkphrase.c
 bittest_SOURCES = bittest.c
 pixie_LDADD =
 mkphrase_SOURCES = mkphrase.c
 bittest_SOURCES = bittest.c
index 0b8ddcf..410b7af 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-c-*-
  *
- * $Id: passphrase.c,v 1.6 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
  *
  * Reading of passphrases (Unix-specific)
  *
  *
  * Reading of passphrases (Unix-specific)
  *
@@ -50,28 +50,37 @@ static unsigned flags = 0;
 
 /*----- Main code ---------------------------------------------------------*/
 
 
 /*----- Main code ---------------------------------------------------------*/
 
-/* --- @pconn@ --- *
+/* --- @passphrase_connect@ ---
  *
  *
- * Arguments:  ---
+ * Arguments:  @const char *sock@ = socket name to connect to, or null for
+ *             default
  *
  * Returns:    Zero if OK, nonzero if it failed
  *
  * Use:                Attempts to connect to the passphrase pixie.
  */
 
  *
  * Returns:    Zero if OK, nonzero if it failed
  *
  * Use:                Attempts to connect to the passphrase pixie.
  */
 
-static int pconn(void)
+int passphrase_connect(const char *sock)
 {
   if (fd != -1)
 {
   if (fd != -1)
-    return (0);
-  if (flags & f_fail)
-    return (-1);
-  if ((fd = pixie_open(0)) < 0) {
+    close(fd);
+  if ((fd = pixie_open(sock)) < 0) {
     flags |= f_fail;
     return (-1);
   }
     flags |= f_fail;
     return (-1);
   }
+  flags &= ~f_fail;
   return (0);
 }
 
   return (0);
 }
 
+static int pconn(void)
+{
+  if (fd != -1)
+    return (0);
+  if (flags & f_fail)
+    return (-1);
+  return (passphrase_connect(0));
+}
+
 /* --- @passphrase_read@ --- *
  *
  * Arguments:  @const char *tag@ = pointer to passphrase tag string
 /* --- @passphrase_read@ --- *
  *
  * Arguments:  @const char *tag@ = pointer to passphrase tag string
index 85ec58e..611b7e1 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-c-*-
  *
- * $Id: passphrase.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
  *
  * Reading passphrases
  *
  *
  * Reading passphrases
  *
@@ -53,6 +53,18 @@ enum {
 
 /*----- Functions provided ------------------------------------------------*/
 
 
 /*----- Functions provided ------------------------------------------------*/
 
+/* --- @passphrase_connect@ ---
+ *
+ * Arguments:  @const char *sock@ = socket name to connect to, or null for
+ *                     default
+ *
+ * Returns:    Zero if OK, nonzero if it failed
+ *
+ * Use:                Attempts to connect to the passphrase pixie.
+ */
+
+extern int passphrase_connect(const char */*sock*/);
+
 /* --- @passphrase_read@ --- *
  *
  * Arguments:  @const char *tag@ = pointer to passphrase tag string
 /* --- @passphrase_read@ --- *
  *
  * Arguments:  @const char *tag@ = pointer to passphrase tag string
diff --git a/pixie-client.c b/pixie-client.c
deleted file mode 100644 (file)
index 73558ff..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simple passphrase pixie client (Unix-specific)
- *
- * (c) 1999 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------* 
- *
- * This file is part of Catacomb.
- *
- * Catacomb is free software; you can redistribute it and/or modify
- * 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pwd.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <mLib/dstr.h>
-#include <mLib/fdflags.h>
-#include <mLib/str.h>
-
-#include "passphrase.h"
-#include "pixie.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @pixie_open@ --- *
- *
- * Arguments:  @const char *sock@ = path to pixie socket
- *
- * Returns:    Less than zero if it failed, or file descriptor.
- *
- * Use:                Opens a connection to a passphrase pixie.
- */
-
-int pixie_open(const char *sock)
-{
-  struct sockaddr_un *sun;
-  size_t sz;
-  int fd;
-
-  /* --- Open the connection --- */
-
-  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
-    goto fail_0;
-  sun = pixie_address(sock, &sz);
-  if (connect(fd, (struct sockaddr *)sun, sz))
-    goto fail_1;
-  xfree(sun);
-  return (fd);
-
-  /* --- Tidy up if things went wrong --- */
-
-fail_1:
-  xfree(sun);
-  close(fd);
-fail_0:
-  return (-1);
-}
-
-/* --- @pixie_read@ --- *
- *
- * Arguments:  @int fd@ = connection to passphrase pixie
- *             @const char *tag@ = pointer to tag string
- *             @unsigned mode@ = reading mode
- *             @char *buf@ = pointer to destination buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    Zero if all went well, @-1@ if the read fails, @+1@ to
- *             request the passphrase from the user.
- *
- * Use:                Reads a passphrase from the pixie.
- */
-
-int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz)
-{
-  dstr d = DSTR_INIT;
-  char *p, *q;
-
-  /* --- Send the request --- */
-
-  dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag);
-  write(fd, d.buf, d.len);
-  dstr_destroy(&d);
-
-  /* --- Sort out the result --- */
-
-again:
-  pixie_fdline(fd, buf, sz);
-  p = buf;
-  if ((q = str_getword(&p)) == 0)
-    return (-1);
-  if (strcmp(q, "INFO") == 0)
-    goto again;
-  else if (strcmp(q, "MISSING") == 0)
-    return (+1);
-  else if (strcmp(q, "OK") != 0)
-    return (-1);
-
-  /* --- Return the final answer --- */
-
-  if (p)
-    memmove(buf, p, strlen(p) + 1);
-  else
-    *buf = 0;
-  return (0);
-}
-
-/* --- @pixie_set@ --- *
- *
- * Arguments:  @int fd@ = pixie file descriptor
- *             @const char *tag@ = pointer to tag string
- *             @const char *phrase@ = pointer to passphrase string
- *
- * Returns:    ---
- *
- * Use:                Sends a passphrase to the passphrase pixie.
- */
-
-void pixie_set(int fd, const char *tag, const char *phrase)
-{
-  dstr d = DSTR_INIT;
-  char buf[16];
-  size_t sz = strlen(phrase);
-  char nl = '\n';
-  char *p, *q;
-
-  /* --- Send the request --- *
-   *
-   * I didn't want to copy it out of the caller's buffer.  @writev@ may
-   * produce a copy, too, so I didn't do that either.
-   */
-
-  dstr_putf(&d, "SET %s -- ", tag);
-  write(fd, d.buf, d.len);
-  write(fd, phrase, sz);
-  write(fd, &nl, 1);
-  dstr_destroy(&d);
-
-  /* --- Pick up the pieces --- */
-
-again:
-  pixie_fdline(fd, buf, sizeof(buf));
-  p = buf;
-  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
-    goto again;
-}
-
-/* --- @pixie_cancel@ --- *
- *
- * Arguments:  @int fd@ = pixie file descriptor
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    ---
- *
- * Use:                Cancels a passphrase if it turns out to be bogus.
- */
-
-void pixie_cancel(int fd, const char *tag)
-{
-  dstr d = DSTR_INIT;
-  char buf[16];
-  char *p, *q;
-
-  /* --- Send the request --- */
-
-  dstr_putf(&d, "FLUSH %s\n", tag);
-  write(fd, d.buf, d.len);
-  dstr_destroy(&d);
-
-  /* --- Sort out the result --- */
-
-again:
-  pixie_fdline(fd, buf, sizeof(buf));
-  p = buf;
-  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
-    goto again;
-}
-
-/*----- That's all, folks -------------------------------------------------*/
index 6efd763..2395f52 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-c-*-
  *
- * $Id: pixie-common.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
  *
  * Common code for Pixie client and server (Unix-specific)
  *
  *
  * Common code for Pixie client and server (Unix-specific)
  *
@@ -46,6 +46,7 @@
 
 #include <mLib/alloc.h>
 #include <mLib/dstr.h>
 
 #include <mLib/alloc.h>
 #include <mLib/dstr.h>
+#include <mLib/str.h>
 
 #include "pixie.h"
 
 
 #include "pixie.h"
 
@@ -218,6 +219,158 @@ fail_0:
   return (-1);
 }
 
   return (-1);
 }
 
+/* --- @pixie_open@ --- *
+ *
+ * Arguments:  @const char *sock@ = path to pixie socket
+ *
+ * Returns:    Less than zero if it failed, or file descriptor.
+ *
+ * Use:                Opens a connection to a passphrase pixie.
+ */
+
+int pixie_open(const char *sock)
+{
+  struct sockaddr_un *sun;
+  size_t sz;
+  int fd;
+
+  /* --- Open the connection --- */
+
+  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+    goto fail_0;
+  sun = pixie_address(sock, &sz);
+  if (connect(fd, (struct sockaddr *)sun, sz))
+    goto fail_1;
+  xfree(sun);
+  return (fd);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail_1:
+  xfree(sun);
+  close(fd);
+fail_0:
+  return (-1);
+}
+
+/* --- @pixie_read@ --- *
+ *
+ * Arguments:  @int fd@ = connection to passphrase pixie
+ *             @const char *tag@ = pointer to tag string
+ *             @unsigned mode@ = reading mode
+ *             @char *buf@ = pointer to destination buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    Zero if all went well, @-1@ if the read fails, @+1@ to
+ *             request the passphrase from the user.
+ *
+ * Use:                Reads a passphrase from the pixie.
+ */
+
+int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz)
+{
+  dstr d = DSTR_INIT;
+  char *p, *q;
+
+  /* --- Send the request --- */
+
+  dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag);
+  write(fd, d.buf, d.len);
+  dstr_destroy(&d);
+
+  /* --- Sort out the result --- */
+
+again:
+  pixie_fdline(fd, buf, sz);
+  p = buf;
+  if ((q = str_getword(&p)) == 0)
+    return (-1);
+  if (strcmp(q, "INFO") == 0)
+    goto again;
+  else if (strcmp(q, "MISSING") == 0)
+    return (+1);
+  else if (strcmp(q, "OK") != 0)
+    return (-1);
+
+  /* --- Return the final answer --- */
+
+  if (p)
+    memmove(buf, p, strlen(p) + 1);
+  else
+    *buf = 0;
+  return (0);
+}
+
+/* --- @pixie_set@ --- *
+ *
+ * Arguments:  @int fd@ = pixie file descriptor
+ *             @const char *tag@ = pointer to tag string
+ *             @const char *phrase@ = pointer to passphrase string
+ *
+ * Returns:    ---
+ *
+ * Use:                Sends a passphrase to the passphrase pixie.
+ */
+
+void pixie_set(int fd, const char *tag, const char *phrase)
+{
+  dstr d = DSTR_INIT;
+  char buf[16];
+  size_t sz = strlen(phrase);
+  char nl = '\n';
+  char *p, *q;
+
+  /* --- Send the request --- *
+   *
+   * I didn't want to copy it out of the caller's buffer.  @writev@ may
+   * produce a copy, too, so I didn't do that either.
+   */
+
+  dstr_putf(&d, "SET %s -- ", tag);
+  write(fd, d.buf, d.len);
+  write(fd, phrase, sz);
+  write(fd, &nl, 1);
+  dstr_destroy(&d);
+
+  /* --- Pick up the pieces --- */
+
+again:
+  pixie_fdline(fd, buf, sizeof(buf));
+  p = buf;
+  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
+    goto again;
+}
+
+/* --- @pixie_cancel@ --- *
+ *
+ * Arguments:  @int fd@ = pixie file descriptor
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    ---
+ *
+ * Use:                Cancels a passphrase if it turns out to be bogus.
+ */
+
+void pixie_cancel(int fd, const char *tag)
+{
+  dstr d = DSTR_INIT;
+  char buf[16];
+  char *p, *q;
+
+  /* --- Send the request --- */
+
+  dstr_putf(&d, "FLUSH %s\n", tag);
+  write(fd, d.buf, d.len);
+  dstr_destroy(&d);
+
+  /* --- Sort out the result --- */
+
+again:
+  pixie_fdline(fd, buf, sizeof(buf));
+  p = buf;
+  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
+    goto again;
+}
 
 /*----- That's all, folks -------------------------------------------------*/
  
 
 /*----- That's all, folks -------------------------------------------------*/
  
diff --git a/pixie.1 b/pixie.1
index c63492b..bdffd05 100644 (file)
--- a/pixie.1
+++ b/pixie.1
@@ -26,6 +26,12 @@ pixie \- Catacomb passphrase pixie
 .IR socket ]
 .B \-C
 .RI [ "request args" ...]
 .IR socket ]
 .B \-C
 .RI [ "request args" ...]
+.br
+.B pixie
+.RB [ \-s
+.IR socket ]
+.BR \-P [ P ]
+.I tag
 .SH "DESCRIPTION"
 The passphrase pixie manages passphrases.  When it starts up, it creates
 a Unix-domain socket in a private directory.  Clients may connect to it
 .SH "DESCRIPTION"
 The passphrase pixie manages passphrases.  When it starts up, it creates
 a Unix-domain socket in a private directory.  Clients may connect to it
@@ -58,10 +64,24 @@ Print a terse usage summary and exit successfully.
 .B "\-C, \-\-client"
 Connect to a running pixie as a client.  If command-line arguments are
 supplied, they are concatenated with spaces between them and submitted
 .B "\-C, \-\-client"
 Connect to a running pixie as a client.  If command-line arguments are
 supplied, they are concatenated with spaces between them and submitted
-to the pixie as a request; a reply is read from the pixie and printed
-on stdout.  If no command-line arguments are given, requestss are read
-interactively from stdin and sent to the pixie; the pixie's responses
-are printed on stdout.
+to the pixie as a request; a reply is read from the pixie and formatted:
+information is written to standard output; errors are reported via
+standard error and the exit status.  If no command-line arguments are
+given, requestss are read interactively from stdin and sent to the
+pixie; the pixie's responses are printed on stdout uninterpreted.
+.TP
+.B "\-P, \-\-passphrase"
+Connect to a running pixie and request the passphrase with tag
+.IR tag .
+If no pixie is running then request the passphrase from the terminal.
+Print the result on standard output, followed by a newline.
+.TP
+.B "\-PP, \-\-verify-passphrase"
+Connect to a running pixie and request verification of the passphrase
+with tag 
+.IR tag .
+If no pixie is running, request the passphrase from the terminal.  Print
+the result on standard output, followed by a newline.
 .TP
 .B "\-q, \-\-quiet"
 Causes the pixie to emit fewer log messages.
 .TP
 .B "\-q, \-\-quiet"
 Causes the pixie to emit fewer log messages.
diff --git a/pixie.c b/pixie.c
index b7083f3..993b60f 100644 (file)
--- a/pixie.c
+++ b/pixie.c
@@ -1024,6 +1024,7 @@ static unsigned c_flags = 0;
 
 #define cf_uclose 1u
 #define cf_sclose 2u
 
 #define cf_uclose 1u
 #define cf_sclose 2u
+#define cf_cooked 4u
 
 /* --- Line handler functions --- */
 
 
 /* --- Line handler functions --- */
 
@@ -1049,7 +1050,22 @@ static void c_sline(char *s, size_t len, void *p)
     }
     exit(0);
   }
     }
     exit(0);
   }
-  puts(s);
+  if (!(c_flags & cf_cooked))
+    puts(s);
+  else {
+    char *q = str_getword(&s);
+    if (strcmp(q, "FAIL") == 0)
+      die(1, "%s", p);
+    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@ --- *
 }
 
 /* --- @pix_client@ --- *
@@ -1093,7 +1109,7 @@ 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);
     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);
   } 
 
     dstr_destroy(&d);
   } 
 
@@ -1122,6 +1138,7 @@ static void usage(FILE *fp)
 Usage:\n\
        $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\
        $ [-s SOCKET] -C [COMMAND ARGS...]\n\
 Usage:\n\
        $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\
        $ [-s SOCKET] -C [COMMAND ARGS...]\n\
+       $ [-s SOCKET] -P[P] TAG\n\
 ");
 }
 
 ");
 }
 
@@ -1144,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\
 -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\
 \n\
 -q, --quiet            Emit fewer log messages.\n\
 -v, --version          Emit more log messages.\n\
@@ -1190,6 +1210,8 @@ int main(int argc, char *argv[])
 #define f_stdin 4u
 #define f_daemon 8u
 #define f_syslog 16u
 #define f_stdin 4u
 #define f_daemon 8u
 #define f_syslog 16u
+#define f_fetch 32u
+#define f_verify 64u
 
   /* --- Initialize libraries --- */
 
 
   /* --- Initialize libraries --- */
 
@@ -1217,6 +1239,8 @@ int main(int argc, char *argv[])
       { "quiet",       0,              0,      'q' },
       { "verbose",     0,              0,      'v' },
       { "client",      0,              0,      'C' },
       { "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' },
       { "socket",      OPTF_ARGREQ,    0,      's' },
       { "command",     OPTF_ARGREQ,    0,      'c' },
       { "fetch",       0,              0,      'f' },
@@ -1232,7 +1256,7 @@ int main(int argc, char *argv[])
       { 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;
 
     if (i < 0)
       break;
 
@@ -1261,6 +1285,17 @@ int main(int argc, char *argv[])
        break;
       case 'C':
        f |= f_client;
        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;
        break;
       case 's':
        path = optarg;
@@ -1294,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);
   }
 
     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);
   /* --- Set up the socket address --- */
 
   sun = pixie_address(path, &sz);