Passphrase pixie support.
[u/mdw/catacomb] / pixie-common.c
diff --git a/pixie-common.c b/pixie-common.c
new file mode 100644 (file)
index 0000000..59b7c5c
--- /dev/null
@@ -0,0 +1,231 @@
+/* -*-c-*-
+ *
+ * $Id: pixie-common.c,v 1.1 1999/12/22 15:58:41 mdw Exp $
+ *
+ * Common code for Pixie client and server (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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: pixie-common.c,v $
+ * Revision 1.1  1999/12/22 15:58:41  mdw
+ * Passphrase pixie support.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <pwd.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+
+#include "pixie.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pixie_address@ --- *
+ *
+ * Arguments:  @const char *sock@ = pointer to socket name
+ *             @size_t *psz@ = where to write the address size
+ *
+ * Returns:    Pointer to filled-in Unix-domain socket address.
+ *
+ * Use:                Returns a Unix-domain socket address to use to find the
+ *             passphrase pixie.
+ */
+
+struct sockaddr_un *pixie_address(const char *sock, size_t *psz)
+{
+  dstr d = DSTR_INIT;
+
+  /* --- Get the default socket path if none specified --- */
+
+  if (!sock)
+    sock = getenv("CATACOMB_PIXIE_SOCKET");
+  if (!sock)
+    sock = "%h/.catacomb/pixie";
+
+  /* --- Substitute interesting sequences in the path --- */
+
+  {
+    const char *q, *qq;
+
+    q = sock;
+    for (;;) {
+      qq = strchr(q, '%');
+      if (!qq || !qq[1]) {
+       DPUTS(&d, q);
+       break;
+      }
+      DPUTM(&d, q, qq - q);
+      q = qq + 1;
+      switch (*q) {
+       case 'u':
+         qq = getenv("USER");
+         if (!qq)
+           qq = getenv("LOGNAME");
+         if (!qq) {
+           struct passwd *pw = getpwuid(getuid());
+           if (pw)
+             qq = pw->pw_name;
+           else
+             qq = "<unknown>";
+         }
+         DPUTS(&d, qq);
+         break;
+       case 'h':
+         qq = getenv("HOME");
+         if (!qq) {
+           struct passwd *pw = getpwuid(getuid());
+           if (pw)
+             qq = pw->pw_dir;
+           else
+             qq = "<unknown>";
+         }
+         DPUTS(&d, qq);
+         break;
+       default:
+         DPUTC(&d, '%');
+         DPUTC(&d, *q);
+         break;
+      }
+      q++;
+    }
+    DPUTZ(&d);
+  }
+
+  /* --- Allocate and initialize the socket address --- */
+
+  {
+    struct sockaddr_un *sun;
+    size_t bsz = offsetof(struct sockaddr_un, sun_path);
+    *psz = bsz + d.len + 1;
+    sun = xmalloc(bsz + d.len + 1);
+    memset(sun, 0, bsz);
+    sun->sun_family = AF_UNIX;
+    memcpy(sun->sun_path, d.buf, d.len + 1);
+    dstr_destroy(&d);
+    return (sun);
+  }
+}
+
+/* --- @pixie_fdline@ --- *
+ *
+ * Arguments:  @int fd@ = file descriptor to read from
+ *             @char *buf@ = pointer to buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads a line from a file descriptor.  The read is done one
+ *             character at a time.  If the entire line won't fit, the end
+ *             is truncated.  The line is null terminated.
+ */
+
+void pixie_fdline(int fd, char *buf, size_t sz)
+{
+  char *p = buf;
+  char *q = p + sz - 1;
+
+  for (;;) {
+    char c;
+    if (read(fd, &c, 1) < 1)
+      break;
+    if (c == '\n')
+      break;
+    if (p < q)
+      *p++ = c;
+  }
+  *p = 0;
+}
+
+/* --- @pixie_getpass@ --- *
+ *
+ * Arguments:  @const char *prompt@ = pointer to prompt string
+ *             @char *buf@ = pointer to buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    Zero if it worked OK, nonzero otherwise.
+ *
+ * Use:                Reads a passphrase from the terminal or some other requested
+ *             source.
+ */
+
+int pixie_getpass(const char *prompt, char *buf, size_t sz)
+{
+  const char *pfd = getenv("CATACOMB_PASSPHRASE_FD");
+  int fd = 0;
+
+  /* --- See whether a terminal is what's wanted --- */
+
+  if (pfd) {
+    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));
+    pixie_fdline(fd, buf, sz);
+    tcsetattr(fd, TCSAFLUSH, &ota);
+    write(fd, &nl, 1);
+    close(fd);
+  }
+  return (0);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail_1:
+  close(fd);
+fail_0:
+  return (-1);
+}
+
+
+/*----- That's all, folks -------------------------------------------------*/