safe

Password protected secret keeper
git clone git://git.z3bra.org/safe.git
Log | Files | Refs | README | LICENSE

commit 9d91b27b8b86983fb7383399a4eab63decae40db
parent 6d148607abca29a784e2558bcc73639a81b20ae7
Author: z3bra <contactatz3bradotorg>
Date:   Fri, 24 May 2019 18:18:21 +0200

Move agent functionnality in safe.c

Diffstat:
makefile | 33++++++++++++---------------------
mkfile | 27+++++++++++----------------
safe-agent.c | 167-------------------------------------------------------------------------------
safe.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 96 insertions(+), 207 deletions(-)

diff --git a/makefile b/makefile @@ -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 diff --git a/mkfile b/mkfile @@ -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 diff --git a/safe-agent.c b/safe-agent.c @@ -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; -} diff --git a/safe.c b/safe.c @@ -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; @@ -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; @@ -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; @@ -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)