pass

A stripped down version of the standard unix password manager "pass"
git clone git://nocebo.space/pass
Log | Files | Refs | LICENSE

commit 00eff5e9eea8509f70207dca159ab338c12fa362
parent 93e35606b8dc6768262d7dcd04243b5eef5d4680
Author: Naveen Narayanan zerous <zerous@nocebo.space>
Date:   Sun, 17 Dec 2017 22:27:19 +0300

insert implemented.

Diffstat:
Makefile | 30++++++++++++++++++++++++++++++
config.mk | 10++++++++++
pass.c | 246+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
3 files changed, 250 insertions(+), 36 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,30 @@ +VERSION = 0.1 + +include config.mk + +OBJ = pass.o +BIN = pass + +all: ${BIN} + +${BIN}: ${OBJ} + ${CC} ${LDFLAGS} -o $@ ${OBJ} ${LIBS} + +pass.o: + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f ${BIN} ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/${BIN} + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + cp -f ${BIN}.1 ${DESTDIR}${MANPREFIX}/man1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/${BIN}.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/${BIN} \ + ${DESTDIR}${MANPREFIX}/man1/${BIN}.1 + +clean: + rm -f ${OBJ} pass pass.core pass.o + +.PHONY: all clean install uninstall diff --git a/config.mk b/config.mk @@ -0,0 +1,10 @@ +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/man + +CFLAGS ?=-Os +CFLAGS +=-pedantic -Wall -Wextra -g +CFLAGS +=-I/usr/include -I/usr/local/include +CFLAGS +=-DVERSION=\"${VERSION}\" +LDFLAGS +=-L/usr/local/lib + +LIBS +=-lgpgme -lassuan -lgpg-error diff --git a/pass.c b/pass.c @@ -1,8 +1,12 @@ +#include <err.h> +#include <errno.h> #include <fcntl.h> -#include <limits.h> +#include <gpgme.h> #include <getopt.h> +#include <limits.h> +#include <locale.h> +#include <pwd.h> #include <stdio.h> -#include <err.h> #include <string.h> #include <stdlib.h> #include <sys/stat.h> @@ -10,7 +14,37 @@ #include "pass.h" -extern char* optarg; +void +initgpgme(void) +{ + const char *reqlibver = "1.6.0"; + const char *reqgpgver = "2.1.0"; + + setlocale(LC_ALL, "en_US.UTF-8"); + gpgme_set_locale(NULL, LC_ALL, "en_US.UTF-8"); + gpgme_set_global_flag("require-gnupg", reqgpgver); + gpgme_check_version(reqlibver); + +} + +void +find (char *item) +{ + (void)item; +} + +void +delete (char *item) +{ + (void)item; +} + +void +list(void) +{ + return; +} + void usage(void) @@ -18,8 +52,148 @@ usage(void) return; } +void +printpass(char *item) +{ + (void)item; +} + +void +getuserid(char *u) +{ + char file[PATH_MAX]; + const char* home; + FILE *fp; + int i; + + if (!(home = getenv("HOME"))) + errx(1, "$HOME not set, cannot determine password-store location"); + snprintf(file, sizeof(file), "%s/.password-store/.gpg-id", home); + + fp = fopen(file, "r"); + while ((i = fgetc(fp)) != EOF) + *u++ = i; + *u = '\0'; +} + +void +insert(char *item) +{ + char t[256]; + char *tp, *i, *gfile; + const char *home; + char file[PATH_MAX]; + FILE *fp, *fin, *fout; + int r; + char uid[128]; + mode_t mode = S_IRWXU; + gpgme_data_t in, out; + gpgme_error_t gpgerr; + gpgme_ctx_t ctx; + gpgme_key_t key; + gpgme_key_t keys[2]; + gpgme_protocol_t proto; + + initgpgme(); + proto = GPGME_PROTOCOL_OpenPGP; + memcpy(t, item, strlen(item)+1); + if (!(home = getenv("HOME"))) + errx(1, "$HOME not set, cannot determine password-store location"); + snprintf(file, sizeof(file), "%s/.password-store", home); + + tp = t; + if ((i = strrchr(tp, '/'))) { + *i = '\0'; + gfile = i + 1; + } else + gfile = item; + +#ifdef DEBUG + printf("gfile: %s\n", gfile); +#endif + + while ((i = strchr(tp, '/'))) { + *i = '\0'; + snprintf(file, sizeof(file), "%s/%s", file, tp); + printf("mkdir %s\n", file); + if ((r = mkdir(file, mode)) == -1) { + if (errno == EEXIST) + ; + else + err(1, "mkdir"); + } + tp = i + 1; + } + snprintf(file, sizeof(file), "%s/%s", file, gfile); + + /* TO-DO: + * * Have to check if the file exists + * * if it does + * ask if user wants to overwrite the file + * * re-confirm password before writing to file + */ + + printf("file: %s\n", file); + if (!(fp = fopen(file, "w+b"))) + err(1, "fopen"); + printf("Enter password for %s: ", item); + while ((r = getchar()) != '\n' && r != EOF) { + if (fputc(r, fp) == EOF) + err(1, "fputc"); + } + + fclose(fp); + + getuserid(uid); + + if (gpgme_err_code(gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) + errx(1, "gpme_new"); + + gpgerr = gpgme_set_protocol(ctx, proto); + if (gpgme_err_code(gpgerr) == GPG_ERR_INV_VALUE) + errx(1, "gpgme_set_protocol"); + + if (gpgme_op_keylist_start(ctx, uid, 0) != GPG_ERR_INV_VALUE) + while (!(gpgerr = gpgme_op_keylist_next(ctx, &key))) { + if (key->can_encrypt) { + break; + } + } + keys[0] = key; + keys[1] = NULL; + + /* set ascii armor */ + gpgme_set_armor(ctx, 1); + + fin = fopen(file, "r"); + snprintf(file, sizeof(file), "%s.gpg", file); + fout = fopen(file, "w"); + + gpgerr = gpgme_data_new_from_stream(&in, fin); + if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) + errx(1, "gpgme_data_new_from_file %s", gpgme_strerror(gpgerr)); + + gpgerr = gpgme_data_new_from_stream(&out, fout); + gpgme_data_set_encoding(out, GPGME_DATA_ENCODING_ARMOR); + if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) + errx(1, "gpgme_data_new: %s", gpgme_strerror(gpgerr)); + + gpgerr = gpgme_op_encrypt(ctx, keys, + GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) + errx(1, "gpgme_op_encrypt: %s", gpgme_strerror(gpgerr)); + + gpgme_key_release(key); + gpgme_data_release(in); + gpgme_data_release(out); + gpgme_release(ctx); + fclose(fin); + fclose(fout); +} + + int -isInit(void) /* check if .password-store exists */ +isinit(void) /* check if .password-store exists */ { int fp; const char *home; @@ -31,27 +205,27 @@ isInit(void) /* check if .password-store exists */ snprintf(file, sizeof(file), "%s/.password-store", home); -#ifdef dbg +#ifdef DEBUG printf("filename: %s\n", file); #endif - if ((fp = open(file, O_RDONLY)) != -1) - if (!fstat(fp, &sb)) - if (S_ISDIR(sb.st_mode)) { - close(fp); - return 1; - } + if ((fp = open(file, O_RDONLY)) != -1 && + (!fstat(fp, &sb)) && + (S_ISDIR(sb.st_mode))) { + close(fp); + return 1; + } return 0; } void -initPass(char *pgpid) +initpass(char *pgpid) { char file[PATH_MAX]; const char* home; FILE *gpg; mode_t mode = S_IRWXU; - if (!isInit()) + if (!isinit()) { if (!(home = getenv("HOME"))) errx(1, "$HOME not set, cannot determine password-store location"); @@ -62,7 +236,7 @@ initPass(char *pgpid) err(1, "mkdir"); snprintf(file, sizeof(file), "%s/.password-store/.gpg-id", home); -#ifdef dbg +#ifdef DEBUG printf("file: %s", file); #endif if (!(gpg = fopen(file, "a"))) @@ -71,37 +245,37 @@ initPass(char *pgpid) if (fputs(pgpid, gpg) == EOF) err(1, "fputs"); - printf("Password store initialized\n"); + printf("Password store initialized for %s\n", pgpid); fclose(gpg); } else { - errx(1, "Password store initialized"); + errx(1, "Password store initialized for %s\n", pgpid); } } int main(int argc, char** argv) { - int init, c; - const char *str; - struct option longopts[] = { - {"init", required_argument, &init, 1} - }; - - c = 0; - init = 0; - str = ""; - while ((c = getopt_long(argc, argv, str, longopts, NULL)) != 1) - switch (c) { - case 0: - if (init) { - initPass(optarg); - } - break; - default: - usage(); - exit(1); - } + if (argc > 1) + { + argv++; + + if (!strcmp("init", *argv)) + initpass(*(argv + 1)); + else if (!strcmp("insert", *argv)) + insert(*(argv + 1)); + else if (!strcmp("ls", *argv)) + list(); + else if (!strcmp("rm", *argv)) + delete(*(argv + 1)); + else if (!strcmp("find", *argv)) + find(*(argv + 1)); + else + printpass(*(argv + 1)); + + } else { + list(); + } return 0; }