tAdd an agent to provide the secret key over unix sockets - safe - password protected secret keeper
 (HTM) git clone git://git.z3bra.org/safe.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit fbcf01e90629b3b93917b7f79b83d7b7523383d0
 (DIR) parent 6c1d23a95e8c6b88d0c4a836c7e36bdc34da73da
 (HTM) Author: z3bra <contactatz3bradotorg>
       Date:   Thu, 23 May 2019 18:09:41 +0200
       
       Add an agent to provide the secret key over unix sockets
       
       Diffstat:
         M mkfile                              |      11 ++++++-----
         A safe-agent.c                        |     167 +++++++++++++++++++++++++++++++
       
       2 files changed, 173 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git a/mkfile b/mkfile
       t@@ -9,18 +9,19 @@ CFLAGS = -g -Wall -Wextra -pedantic
        LDFLAGS =
        LDLIBS = -lsodium
        
       -BIN = safe
       -SRC = ${BIN}.c readpassphrase.c
       -OBJ = ${SRC:%.c=%.o}
       +all:V: safe safe-agent
        
       -${BIN}: $OBJ
       +safe-agent: safe-agent.o readpassphrase.o
       +        $LD -o $target $prereq $LDFLAGS $LDLIBS
       +
       +safe: safe.o
                $LD -o $target $prereq $LDFLAGS $LDLIBS
        
        %.o: %.c
                $CC $CPPFLAGS $CFLAGS -c $stem.c
        
        clean:V:
       -        rm -f $OBJ ${BIN}
       +        rm -f *.o safe safe-agent
        
        install:V: ${BIN}
                mkdir -p ${DESTDIR}${PREFIX}/bin
 (DIR) diff --git a/safe-agent.c b/safe-agent.c
       t@@ -0,0 +1,167 @@
       +#include <sys/socket.h>
       +#include <sys/types.h>
       +#include <sys/un.h>
       +
       +#include <err.h>
       +#include <limits.h>
       +#include <stdint.h>
       +#include <stdlib.h>
       +#include <stdio.h>
       +#include <string.h>
       +#include <unistd.h>
       +
       +#include <sodium.h>
       +
       +#include "arg.h"
       +#include "readpassphrase.h"
       +
       +#define MDSIZ crypto_generichash_BYTES
       +#define SOCKET "/tmp/safe.sock"
       +
       +uint8_t *passphrase;
       +uint32_t pplen;
       +char *argv0;
       +
       +void
       +usage(void)
       +{
       +        fprintf(stderr, "usage: %s [-hf] [-s socket]\n", argv0);
       +        exit(1);
       +}
       +
       +ssize_t
       +xread(int fd, void *buf, size_t nbytes)
       +{
       +        uint8_t *bp = buf;
       +        ssize_t total = 0;
       +
       +        while (nbytes > 0) {
       +                ssize_t n;
       +
       +                n = read(fd, &bp[total], nbytes);
       +                if (n < 0)
       +                        err(1, "read");
       +                else if (n == 0)
       +                        return total;
       +                total += n;
       +                nbytes -= n;
       +        }
       +        return total;
       +}
       +
       +ssize_t
       +xwrite(int fd, const void *buf, size_t nbytes)
       +{
       +        const uint8_t *bp = buf;
       +        ssize_t total = 0;
       +
       +        while (nbytes > 0) {
       +                ssize_t n;
       +
       +                n = write(fd, &bp[total], nbytes);
       +                if (n < 0)
       +                        err(1, "write");
       +                else if (n == 0)
       +                        return total;
       +                total += n;
       +                nbytes -= n;
       +        }
       +        return total;
       +}
       +
       +void
       +hash(uint8_t *buf, size_t size, uint8_t *md, size_t mdsize)
       +{
       +        crypto_generichash(md, mdsize, buf, size, NULL, 0);
       +}
       +
       +
       +static int
       +readpass(const char *prompt, uint8_t **target, uint32_t *len)
       +{
       +        char pass[BUFSIZ], *p;
       +
       +        p = readpassphrase(prompt, pass, sizeof(pass), RPP_ECHO_OFF);
       +        if (!p)
       +                err(1, "readpassphrase:");
       +
       +        if (p[0] == '\0')
       +                return -1;
       +
       +        *target = realloc(*target, strlen(p)); /* not null-terminated */
       +        if (!*target)
       +                err(1, "realloc:");
       +
       +        memcpy(*target, p, strlen(p));
       +        *len = strlen(p);
       +        return 0;
       +}
       +
       +void
       +deriv(char *pw, uint8_t *salt, uint8_t *key, size_t ks)
       +{
       +        if (crypto_pwhash(key, ks, pw, strlen(pw),
       +                        salt, crypto_pwhash_OPSLIMIT_INTERACTIVE,
       +                        crypto_pwhash_MEMLIMIT_INTERACTIVE,
       +                        crypto_pwhash_ALG_DEFAULT))
       +                err(1, "crypto_pwhash");
       +}
       +
       +int
       +servekey(char *path)
       +{
       +        int cfd, sfd;
       +        char hex[MDSIZ*2 +1];
       +        uint8_t md[MDSIZ];
       +        uint8_t salt[crypto_pwhash_SALTBYTES];
       +        uint8_t key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
       +        struct sockaddr_un addr;
       +
       +        readpass("Passphrase:", &passphrase, &pplen);
       +
       +        hash(passphrase, pplen, md, sizeof(md));
       +        sodium_memzero(passphrase, pplen);
       +        sodium_bin2hex(hex, sizeof(hex), md, sizeof(md));
       +
       +        sfd = socket(AF_UNIX, SOCK_STREAM, 0);
       +        if (sfd < 0)
       +                err(1, "socket: %s", path);
       +
       +        memset(&addr, 0, sizeof(addr));
       +        addr.sun_family = AF_UNIX;
       +        strcpy(addr.sun_path, path);
       +
       +        if (bind(sfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
       +                err(1, "bind: %s", path);
       +
       +        listen(sfd, 10);
       +
       +        while ((cfd = accept(sfd, NULL, NULL)) > 0) {
       +                xread(cfd, salt, sizeof(salt));
       +                deriv(hex, salt, key, sizeof(key));
       +                xwrite(cfd, key, sizeof(key));
       +                close(cfd);
       +        }
       +
       +        close(sfd);
       +
       +        return 0;
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        char *socket = SOCKET;
       +
       +        ARGBEGIN {
       +        case 's':
       +                socket = EARGF(usage());
       +                break;
       +        default:
       +                usage();
       +        } ARGEND
       +
       +        servekey(socket);
       +
       +        return 0;
       +}