aboutsummaryrefslogtreecommitdiff
path: root/src/libnpass/libnpass.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnpass/libnpass.c')
-rw-r--r--src/libnpass/libnpass.c170
1 files changed, 168 insertions, 2 deletions
diff --git a/src/libnpass/libnpass.c b/src/libnpass/libnpass.c
index aa1a285..37fc40c 100644
--- a/src/libnpass/libnpass.c
+++ b/src/libnpass/libnpass.c
@@ -7,6 +7,7 @@
#include <libgen.h>
#include <termios.h>
#include <stdio.h>
+#include <dirent.h>
#include "libnpass/libnpass.h"
#include "libnpass/gpg.h"
@@ -14,8 +15,8 @@
#include "util.h"
-#define DEF_PASS_DIR "pass"
-#define FPR_MAX 256
+#define DEF_PASS_DIR "pass"
+#define FPR_MAX NAME_MAX
static char pass_dir[PATH_MAX] = {0};
const char *pass_gen_set[] = {
@@ -32,6 +33,7 @@ const char *pass_gen_set[] = {
};
int set_pass_dir(void);
+int is_storeobj(struct dirent *dir);
int set_pass_dir(void) {
const char *env;
@@ -59,6 +61,170 @@ int set_pass_dir(void) {
return 1;
}
+int pass_store_cmp(const void *vp1, const void *vp2) {
+ struct store *sp1, *sp2;
+
+ sp1 = (struct store *) vp1;
+ sp2 = (struct store *) vp2;
+ return strcmp(sp1->name, sp2->name);
+}
+
+int is_storeobj(struct dirent *dir) {
+ int r;
+ char *s;
+
+ switch (dir->d_type) {
+ case DT_DIR:
+ r = strcmp(dir->d_name, ".");
+ if (r)
+ r = strcmp(dir->d_name, "..");
+
+ return r;
+ break;
+ case DT_REG:
+ s = strrchr(dir->d_name, '.');
+ if (!s)
+ return 0;
+
+ r = strcmp(s, ".gpg");
+ return (r == 0);
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+pass_store_t pass_store_type(const char *spath) {
+ int r;
+ struct stat sbuf;
+ char abs_path[PATH_MAX];
+
+ r = set_pass_dir();
+ if (r)
+ err_ret(PASS_STORE_INV, "PASSWORD_STORE_DIR not set");
+
+ r = snprintf(abs_path, sizeof(abs_path) - 1, "%s/%s",
+ pass_dir, spath);
+ if (r >= (int) sizeof(abs_path))
+ err_ret(PASS_STORE_INV, "path exceeded PATH_MAX");
+ r = stat(abs_path, &sbuf);
+ if (!r && (sbuf.st_mode & S_IFMT) == S_IFDIR)
+ return PASS_STORE_DIR;
+
+ r = snprintf(abs_path, sizeof(abs_path) - 1, "%s/%s.gpg",
+ pass_dir, spath);
+ if (r >= (int) sizeof(abs_path))
+ err_ret(PASS_STORE_INV, "path exceeded PATH_MAX");
+ r = stat(abs_path, &sbuf);
+ if (r)
+ err_ret(PASS_STORE_INV, "%s", strerror(errno));
+
+ if ((sbuf.st_mode & S_IFMT) == S_IFREG) {
+ return PASS_STORE_ENC;
+ } else {
+ err_ret(PASS_STORE_INV, "%s is not a regular file", abs_path);
+ }
+}
+
+DIR *openstore(const char *spath) {
+ int r;
+ DIR *d;
+ const char *path;
+ char abs_path[PATH_MAX];
+
+ r = set_pass_dir();
+ if (r)
+ err_ret(NULL, "PASSWORD_STORE_DIR not set");
+
+ if (spath) {
+ r = snprintf(abs_path, sizeof(abs_path) - 1, "%s/%s",
+ pass_dir, spath);
+ if (r >= (int) sizeof(abs_path))
+ err_ret(NULL, "path exceeded PATH_MAX");
+
+ path = abs_path;
+ } else {
+ path = pass_dir;
+ }
+
+ d = opendir(path);
+ if (!d)
+ err_ret(NULL, "%s", strerror(errno));
+
+ return d;
+}
+
+int readstore(DIR *dirp, struct store *s) {
+ struct dirent *dir;
+
+ errno = 0;
+
+ while ((dir = readdir(dirp))) {
+ if (is_storeobj(dir))
+ break;
+ }
+
+ if (!dir) {
+ if (errno != 0)
+ err_ret(1, "%s", strerror(errno));
+
+ return EOF;
+ }
+
+ strncpy(s->name , dir->d_name, sizeof(s->name));
+ switch (dir->d_type) {
+ case DT_DIR:
+ s->type = PASS_STORE_DIR;
+ break;
+ case DT_REG:
+ /* this is safe since is_storeobj()
+ * rejects files without .gpg suffix */
+ *(strrchr(s->name, '.')) = '\0';
+ s->type = PASS_STORE_ENC;
+ break;
+ default:
+ s->type = PASS_STORE_INV;
+ break;
+ }
+
+ return 0;
+}
+
+int readstore_all(const char *path, struct store **stor) {
+ int r;
+ void *p;
+ size_t i;
+ DIR *dirp;
+ size_t len = PATH_MAX;
+
+ *stor = malloc(sizeof(struct store) * len);
+ if (!*stor)
+ err_ret(-1, "%s", strerror(errno));
+
+ dirp = openstore(path);
+ if (!dirp) {
+ free(*stor);
+ return -1;
+ };
+
+ for (i = 0; !(r = readstore(dirp, *stor + i)); i++) {
+ if (i < len - 1)
+ continue;
+
+ len *= 2;
+ p = realloc(*stor, sizeof(**stor) * len);
+ if (!p) {
+ free(*stor);
+ err_ret(-1, "%s", strerror(errno));
+ } else {
+ *stor = p;
+ }
+ }
+
+ return i;
+}
+
int pass_init(const char *fpr)
{
int r;