tMove agent functionnality in safe.c - 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 9d91b27b8b86983fb7383399a4eab63decae40db
 (DIR) parent 6d148607abca29a784e2558bcc73639a81b20ae7
 (HTM) Author: z3bra <contactatz3bradotorg>
       Date:   Fri, 24 May 2019 18:18:21 +0200
       
       Move agent functionnality in safe.c
       
       Diffstat:
         M makefile                            |      33 +++++++++++--------------------
         M mkfile                              |      27 +++++++++++----------------
         D safe-agent.c                        |     167 -------------------------------
         M safe.c                              |      76 +++++++++++++++++++++++++++++--
       
       4 files changed, 96 insertions(+), 207 deletions(-)
       ---
 (DIR) diff --git a/makefile b/makefile
       t@@ -4,33 +4,24 @@ LD = $(CC)
        PREFIX = /usr/local
        MANPREFIX = ${PREFIX}/man
        
       -CPPFLAGS = -D_XOPEN_SOURCE -I/usr/local/include
       +CPPFLAGS = -I/usr/local/include
        CFLAGS = -Wall -Wextra -pedantic
        LDFLAGS = -L/usr/local/lib
        LDLIBS = -lsodium
        
       -all: safe safe-agent
       -
       -safe-agent: safe-agent.o readpassphrase.o
       -        $(LD) -o $@ safe-agent.o readpassphrase.o $(LDFLAGS) $(LDLIBS)
       -
       -safe: safe.o
       -        $(LD) -o $@ safe.o $(LDFLAGS) $(LDLIBS)
       +safe: safe.o readpassphrase.o
        
        clean:
       -        rm -f *.o safe safe-agent
       +        rm -f *.o safe
        
       -install: safe safe-agent
       -        mkdir -p ${DESTDIR}${PREFIX}/bin
       -        cp safe ${DESTDIR}${PREFIX}/bin/safe
       -        cp safe-agent ${DESTDIR}${PREFIX}/bin/safe-agent
       -        chmod 755 ${DESTDIR}${PREFIX}/bin/safe
       -        chmod 755 ${DESTDIR}${PREFIX}/bin/safe-agent
       -        mkdir -p ${DESTDIR}${MANPREFIX}/man1
       -        cp safe.1 ${DESTDIR}${MANPREFIX}/man1/safe.1
       -        chmod 644 ${DESTDIR}${MANPREFIX}/man1/safe.1
       +install: safe
       +        mkdir -p ${DESTDIR}${PREFIX}/bin
       +        cp safe ${DESTDIR}${PREFIX}/bin/safe
       +        chmod 755 ${DESTDIR}${PREFIX}/bin/safe
       +        mkdir -p ${DESTDIR}${MANPREFIX}/man1
       +        cp safe.1 ${DESTDIR}${MANPREFIX}/man1/safe.1
       +        chmod 644 ${DESTDIR}${MANPREFIX}/man1/safe.1
        
        uninstall::
       -        rm ${DESTDIR}${PREFIX}/bin/safe
       -        rm ${DESTDIR}${PREFIX}/bin/safe-agent
       -        rm ${DESTDIR}${MANPREFIX}/man1/safe.1
       +        rm ${DESTDIR}${PREFIX}/bin/safe
       +        rm ${DESTDIR}${MANPREFIX}/man1/safe.1
 (DIR) diff --git a/mkfile b/mkfile
       t@@ -4,33 +4,28 @@ LD = ${CC}
        PREFIX = /usr/local
        MANPREFIX = ${PREFIX}/man
        
       -CPPFLAGS = -D_XOPEN_SOURCE
       +CPPFLAGS = -I/usr/local/include
        CFLAGS = -g -Wall -Wextra -pedantic
       -LDFLAGS =
       +LDFLAGS = -L/usr/local/lib
        LDLIBS = -lsodium
        
       -all:V: safe safe-agent
       -
       -safe-agent: safe-agent.o readpassphrase.o
       -        $LD -o $target $prereq $LDFLAGS $LDLIBS
       -
       -safe: safe.o
       +safe: safe.o readpassphrase.o
                $LD -o $target $prereq $LDFLAGS $LDLIBS
        
        %.o: %.c
                $CC $CPPFLAGS $CFLAGS -c $stem.c
        
        clean:V:
       -        rm -f *.o safe safe-agent
       +        rm -f *.o safe
        
       -install:V: ${BIN}
       +install:V: safe
                mkdir -p ${DESTDIR}${PREFIX}/bin
       -        cp ${BIN} ${DESTDIR}${PREFIX}/bin/${BIN}
       -        chmod 755 ${DESTDIR}${PREFIX}/bin/${BIN}
       +        cp safe ${DESTDIR}${PREFIX}/bin/safe
       +        chmod 755 ${DESTDIR}${PREFIX}/bin/safe
                mkdir -p ${DESTDIR}${MANPREFIX}/man1
       -        cp ${BIN}.1 ${DESTDIR}${MANPREFIX}/man1/${BIN}.1
       -        chmod 644 ${DESTDIR}${MANPREFIX}/man1/${BIN}.1
       +        cp safe.1 ${DESTDIR}${MANPREFIX}/man1/safe.1
       +        chmod 644 ${DESTDIR}${MANPREFIX}/man1/safe.1
        
        uninstall:V:
       -        rm ${DESTDIR}${PREFIX}/bin/${BIN}
       -        rm ${DESTDIR}${MANPREFIX}/man1/${BIN}.1
       +        rm ${DESTDIR}${PREFIX}/bin/safe
       +        rm ${DESTDIR}${MANPREFIX}/man1/safe.1
 (DIR) diff --git a/safe-agent.c b/safe-agent.c
       t@@ -1,167 +0,0 @@
       -#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;
       -}
 (DIR) diff --git a/safe.c b/safe.c
       t@@ -18,6 +18,8 @@
        #include "readpassphrase.h"
        
        #define MDSIZ crypto_generichash_BYTES
       +#define SOCKDIR "/tmp/safe-XXXXXX"
       +#define SOCKET  "agent"
        #define SAFE ".secrets"
        
        uint8_t *passphrase;
       t@@ -192,6 +194,63 @@ deriv(char *pw, uint8_t *salt, uint8_t *key, size_t ks)
        }
        
        int
       +creatsock(char *sockpath)
       +{
       +        int sfd;
       +        char path[PATH_MAX] = SOCKDIR;
       +        struct sockaddr_un addr;
       +
       +        if (sockpath) {
       +                strncpy(path, sockpath, sizeof(path));
       +        } else {
       +                if (!mkdtemp(path))
       +                        err(1, "mkdtemp: %s", path);
       +
       +                strncat(path, "/", 1);
       +                strncat(path, SOCKET, sizeof(path));
       +        }
       +
       +        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);
       +
       +        if (listen(sfd, 10) < 0)
       +                err(1, "listen: %s", path);
       +
       +        return sfd;
       +}
       +
       +int
       +agent(char *path)
       +{
       +        int cfd, sfd;
       +        uint8_t salt[crypto_pwhash_SALTBYTES];
       +        uint8_t key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
       +
       +        readpass("password:", &passphrase, &pplen);
       +
       +        sfd = creatsock(path);
       +
       +        while ((cfd = accept(sfd, NULL, NULL)) > 0) {
       +                xread(cfd, salt, sizeof(salt));
       +                deriv((char *)passphrase, salt, key, sizeof(key));
       +                xwrite(cfd, key, sizeof(key));
       +                close(cfd);
       +        }
       +
       +        close(sfd);
       +
       +        return 0;
       +}
       +
       +int
        getkey(char *path, uint8_t *key, uint8_t *salt)
        {
                int sfd;
       t@@ -269,13 +328,19 @@ show_secret(int fd, char *name)
        int
        main(int argc, char *argv[])
        {
       -        int aflag = 0, lflag = 0;
       -        char *secret = NULL, *safe = SAFE;
       +        int aflag = 0, dflag = 0;
       +        char *secret = NULL, *sockp = NULL, *safe = SAFE;
        
                ARGBEGIN {
                case 'a':
                        aflag = 1;
                        break;
       +        case 'd':
       +                dflag = 1;
       +                break;
       +        case 'f':
       +                sockp = EARGF(usage());
       +                break;
                case 's':
                        safe = EARGF(usage());
                        break;
       t@@ -283,9 +348,14 @@ main(int argc, char *argv[])
                        usage();
                } ARGEND
        
       -        if (argc != 1 && !lflag)
       +        if (argc != 1 && !dflag)
                        usage();
        
       +        if (dflag) {
       +                agent(sockp);
       +                return 0;
       +        }
       +
                if (safe) {
                        mkdir(safe, 0700);
                        if (chdir(safe) < 0)