From 705ed7afd5c707419e02fca1b97f2a6516453506 Mon Sep 17 00:00:00 2001 From: sinanmohd Date: Sat, 30 Dec 2023 11:14:24 +0530 Subject: pass/cat: init --- gpg.c | 34 ++++++++++++++++++++++++++++++++++ gpg.h | 3 +++ pass.c | 11 ++++++++++- pass_util.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- pass_util.h | 4 ++++ util.h | 4 ++-- 6 files changed, 98 insertions(+), 11 deletions(-) diff --git a/gpg.c b/gpg.c index ab7d8dd..5206a48 100644 --- a/gpg.c +++ b/gpg.c @@ -1,9 +1,11 @@ #include +#include #include #include #include "gpg.h" +#include "util.h" #define fail_if_err(err) \ if (err) { \ @@ -59,6 +61,38 @@ int gpg_key_validate(const char *fpr) fail_if_err(err); gpg_cleanup(); + return 0; +} + +int gpg_decrypt(const char *fpr, const char *path, char *pass_out, size_t n) +{ + int r; + gpgme_data_t in, out; + gpgme_error_t err; + + r = gpg_init(); + if (r) + return r; + + err = gpgme_get_key(ctx, fpr, &key, 1); + fail_if_err(err); + + err = gpgme_data_new_from_file(&in, path, 1); + fail_if_err(err); + err = gpgme_data_new(&out); + fail_if_err(err); + err = gpgme_op_decrypt(ctx, in, out); + fail_if_err(err); + + r = gpgme_data_seek(out, 0, SEEK_SET); + if (r) + fail_if_err (gpgme_err_code_from_errno(errno)); + r = gpgme_data_read(out, pass_out, n); + gpg_cleanup(); + if (r < 0) + fail_if_err(gpgme_err_code_from_errno(errno)); + // if (r) // TODO: upstream: did not return 0 despite eob + // err_die(r, "did not reach end of object"); return 0; } diff --git a/gpg.h b/gpg.h index 36904df..36c2b87 100644 --- a/gpg.h +++ b/gpg.h @@ -1 +1,4 @@ +#include + int gpg_key_validate(const char *fpr); +int gpg_decrypt(const char *fpr, const char *path, char *pass_out, size_t n); diff --git a/pass.c b/pass.c index 41e8a76..f7ce19e 100644 --- a/pass.c +++ b/pass.c @@ -31,6 +31,7 @@ void print_usage(void) int main(int argc, char *argv[]) { int r = 0; + const char *s = NULL; if (!--argc) { print_usage(); @@ -43,9 +44,17 @@ int main(int argc, char *argv[]) print_usage(); } else if (!strcmp("init", *argv)) { if (!argv[1]) - err_die("invalid usage, try pass help"); + err_die(1, "invalid usage, try pass help"); r = pass_init(argv[1]); + } else if (!strcmp("cat", *argv)) { + if (!argv[1]) + err_die(1, "invalid usage, try pass help"); + + s = pass_cat(argv[1]); + r = !(s == NULL); + if (s) + fputs(s, stdout); } return r; diff --git a/pass_util.c b/pass_util.c index bcc4aaa..47e72f2 100644 --- a/pass_util.c +++ b/pass_util.c @@ -11,7 +11,8 @@ #define DEF_PASS_DIR "pass" -char pass_dir[PATH_MAX]; +static char pass_dir[PATH_MAX] = {0}; +static char pass_out[PASS_MAX] = {0}; int set_pass_dir(void); @@ -49,30 +50,66 @@ int pass_init(const char *fpr) r = set_pass_dir(); if (r) - err_die("PASSWORD_STORE_DIR not set"); + err_die(1, "PASSWORD_STORE_DIR not set"); r = gpg_key_validate(fpr); if (r) - err_die("key not usable, try gpg --full-generate-key"); + err_die(1, "key not usable, try gpg --full-generate-key"); r = r_mkdir(pass_dir, S_IRWXU); if (r) - err_die("%s %s", pass_dir, strerror(errno)); + err_die(1, "%s %s", pass_dir, strerror(errno)); r = snprintf(gpg_id_path, sizeof(gpg_id_path), "%s/%s", pass_dir, ".gpg-id"); if (r > (int) sizeof(gpg_id_path)) - err_die("path exceeded PATH_MAX"); + err_die(1, "path exceeded PATH_MAX"); gpg_id = fopen(gpg_id_path, "w"); if (!gpg_id) - err_die("%s %s", gpg_id_path, strerror(errno)); + err_die(1, "%s %s", gpg_id_path, strerror(errno)); r = fwrite(fpr, strlen(fpr), 1,gpg_id); + fclose(gpg_id); if (!r) - err_die("write failed"); + err_die(1, "write failed"); + + return 0; +} + +const char *pass_cat(const char *path) +{ + int r; + char *rc; + char gpg_id_path[PATH_MAX], fpr[FPR_MAX], pass_path[PATH_MAX]; + FILE *gpg_id; + + r = set_pass_dir(); + if (r) + err_die(NULL, "PASSWORD_STORE_DIR not set"); + + r = snprintf(gpg_id_path, sizeof(gpg_id_path), "%s/%s", pass_dir, ".gpg-id"); + if (r > (int) sizeof(gpg_id_path)) + err_die(NULL, "path exceeded PATH_MAX"); + + gpg_id = fopen(gpg_id_path, "r"); + if (!gpg_id) + err_die(NULL, "%s %s", gpg_id_path, strerror(errno)); + + rc = fgets(fpr, sizeof(fpr), gpg_id); + if (!rc) + err_die(NULL, "failed to read %s", gpg_id_path); fclose(gpg_id); - return 0; + r = gpg_key_validate(fpr); + if (r) + err_die(NULL, "key not usable, try gpg --list-keys"); + + r = snprintf(pass_path, sizeof(pass_path), "%s/%s.gpg", pass_dir, path); + if (r > (int) sizeof(gpg_id_path)) + err_die(NULL, "path exceeded PATH_MAX"); + + r = gpg_decrypt(fpr, pass_path, pass_out, sizeof(pass_out)); + return r ? NULL : pass_out; } diff --git a/pass_util.h b/pass_util.h index a2cacdc..3ad4eed 100644 --- a/pass_util.h +++ b/pass_util.h @@ -1 +1,5 @@ +#define PASS_MAX 4096 +#define FPR_MAX 128 + int pass_init(const char *fpr); +const char *pass_cat(const char *path); diff --git a/util.h b/util.h index be1c5ec..9353849 100644 --- a/util.h +++ b/util.h @@ -3,11 +3,11 @@ #include #include -#define err_die(...) {\ +#define err_die(r, ...) {\ fprintf(stderr, "err: %s:%d: ", __FILE__, __LINE__); \ fprintf(stderr, __VA_ARGS__); \ fputc('\n', stderr); \ - return 1; \ + return r; \ } int r_mkdir(const char *path, mode_t mode); -- cgit v1.2.3