add remove-user and list-users commands

Sat, 12 Oct 2019 11:17:11 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 12 Oct 2019 11:17:11 +0200
changeset 654
8f2b8f2a5cde
parent 653
f503c272bd70
child 655
4d33b672c33a

add remove-user and list-users commands

dav/main.c file | annotate | diff | comparison | revisions
dav/main.h file | annotate | diff | comparison | revisions
dav/pwd.c file | annotate | diff | comparison | revisions
dav/pwd.h file | annotate | diff | comparison | revisions
--- a/dav/main.c	Sat Oct 12 09:53:32 2019 +0200
+++ b/dav/main.c	Sat Oct 12 11:17:11 2019 +0200
@@ -176,6 +176,10 @@
             ret = cmd_repository_url(args);
         } else if(!strcasecmp(cmd, "add-user")) {
             ret = cmd_add_user(args);
+        } else if(!strcasecmp(cmd, "list-users")) {
+            ret = cmd_list_users(args);
+        } else if(!strcasecmp(cmd, "remove-user")) {
+            ret = cmd_remove_user(args);
         } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version")
                 || !strcasecmp(cmd, "--version")) {
             fprintf(stderr, "dav %s\n", DAV_VERSION);
@@ -296,7 +300,7 @@
     fprintf(stderr, "        versioncontrol list-versions checkout checkin uncheckout\n\n");
     fprintf(stderr, "Config commands:\n");
     fprintf(stderr, "        add-repository remove-repository list-repositories repository-url\n");
-    fprintf(stderr, "        add-user\n");
+    fprintf(stderr, "        add-user remove-user list-users\n");
     fprintf(stderr, "        check-config\n");
     fprintf(stderr, "\n");
     fprintf(stderr,
@@ -2625,55 +2629,202 @@
     return 0;
 }
 
-int cmd_add_user(CmdArgs *args) {
+
+typedef int(*sscmd_func)(CmdArgs *, PwdStore *, void *userdata);
+
+static int secretstore_after_decrypt(
+    CmdArgs *args,
+    PwdStore *secrets,
+    sscmd_func cb,
+    void *userdata);
+
+
+/*
+ * opens the secret store, executes a callback func before and after
+ * decryption
+ * Aborts if a callback returns 1
+ */
+static int secretstore_cmd(
+    CmdArgs *args,
+    DavBool create,
+    sscmd_func beforedecrypt,
+    sscmd_func afterdecrypt,
+    void *userdata)
+{
+    PwdStore *secrets = get_pwdstore();
+    if(!secrets) {
+        if(create) {
+            secrets = pwdstore_new();
+        } else {
+            return 1;
+        }
+    }
+    
+    int ret = 0;
+    if(beforedecrypt) {
+        ret = beforedecrypt(args, secrets, userdata);
+        if(ret) {
+            afterdecrypt = NULL; // exit
+        }
+    }
+    
+    if(afterdecrypt) {
+        ret = secretstore_after_decrypt(args, secrets, afterdecrypt, userdata);
+    }
+    
+    pwdstore_free(secrets);
+    
+    return ret;
+}
+
+static int secretstore_after_decrypt(
+    CmdArgs *args,
+    PwdStore *secrets,
+    sscmd_func cb,
+    void *userdata)
+{
     char *master_pw = util_password_input("Master password: ");
     if(!master_pw) {
+        fprintf(stderr, "Error: master password required.\nAbort.\n");
         return 1;
     }
     
-    PwdStore *secrets = get_pwdstore();
-    if(!secrets) {
-        secrets = pwdstore_new();
-    }
-    if(pwdstore_setpassword(secrets, master_pw)) {
+    int err = pwdstore_setpassword(secrets, master_pw);
+    free(master_pw);
+    if(err) {
         fprintf(stderr, "Error: Cannot generate key from password.\nAbort.\n");
         return 1;
     }
+    
     if(pwdstore_decrypt(secrets)) {
         fprintf(stderr, "Error: Cannot decrypt secrets store.\nAbort.\n");
+        return 1;
     }
     
-    
+    return cb(args, secrets, userdata);
+}
+
+static int cmd_ss_add_user(CmdArgs *Args, PwdStore *secrets, void *userdata) {
     char *id = assistant_getcfg("Credentials identifier");
-    if(id && pwdstore_get(secrets, id)) {
+    if(!id) {
+        fprintf(stderr, "Identifier required.\n");
+        return 1;
+    }
+    if(pwdstore_get(secrets, id)) {
         fprintf(stderr, "Credentials with this id already exist.\n");
         return 1;
     }
     
+    // get user name and password (required)
     char *user = assistant_getcfg("User");
     char *password = util_password_input("Password: ");
-    char *location = assistant_getoptcfg("Location");
-    UcxList *locations = location ? ucx_list_append(NULL, location) : NULL;
+    
+    // optionally, get one or more locations
+    char *location = NULL;
+    UcxList *locations = NULL;
+    while((location = assistant_getoptcfg("Location"))) {
+        locations = ucx_list_append(locations, location);
+    }
+    
     int ret = 1;
     if(user && password) {
         pwdstore_put_index(secrets, id, locations);
         pwdstore_put(secrets, id, user, password);
-        int ret = pwdstore_save(secrets);
+        ret = pwdstore_save(secrets);
         if(ret) {
             fprintf(stderr, "Error: saving srcrets store failed.\n");
         }
     }
     
-    pwdstore_free(secrets);
     if(id) free(id);
     if(user) free(user);
     if(password) free(password);
-    if(location) free(location);
-    if(locations) ucx_list_free(locations);
+    
+    ucx_list_free_content(locations, free);
+    ucx_list_free(locations);
     
     return ret;
 }
 
+int cmd_add_user(CmdArgs *args) { 
+    return secretstore_cmd(args, TRUE, NULL, cmd_ss_add_user, NULL);
+}
+
+/*
+ * called before the secret store is decrypted
+ */
+static int cmd_ss_list_users_bc(CmdArgs *Args, PwdStore *secrets, int *ret) {
+    if(secrets->index->count == 0) {
+        return 1; // abort, because the secret store is empty
+    }
+    // set ret to 1, because decrypt could fail and this should be an error
+    *ret = 1;
+    return 0;
+}
+
+/*
+ * called after the secret store is decrypted
+ */
+static int cmd_ss_list_users(CmdArgs *args, PwdStore *secrets, int *ret) {
+    *ret = 0;
+    
+    UcxList *list = secrets->locations;
+    for(int i=0;i<2;i++) {
+        UCX_FOREACH(elm, list) {
+            PwdIndexEntry *index = elm->data;
+            PwdEntry *e = ucx_map_cstr_get(secrets->ids, index->id);
+            if(e) {
+                printf("Id: %s\n", e->id);
+                printf("User: %s\n", e->user);
+                UCX_FOREACH(loc, index->locations) {
+                    char *location = loc->data;
+                    printf("Location: %s\n", location);
+                }
+                printf("\n");
+            } else {
+                // broken index
+                fprintf(stderr,
+                        "Warning: id '%s' not in secret store.\n",
+                        index->id);
+            }
+        }
+        list = secrets->noloc;
+    }
+    
+    
+    return 0;
+}
+
+int cmd_list_users(CmdArgs *args) {
+    int ret = 0;
+    secretstore_cmd(args, FALSE, (sscmd_func)cmd_ss_list_users_bc, (sscmd_func)cmd_ss_list_users, &ret);
+    return ret;
+}
+
+
+static int cmd_ss_remove_user(CmdArgs *args, PwdStore *secrets, void *ud) {
+    char *id = assistant_getcfg("Credentials identifier");
+    if(!id) {
+        fprintf(stderr, "Identifier required.\n");
+        return 1;
+    }
+    if(!pwdstore_get(secrets, id)) {
+        fprintf(stderr, "Credentials with this id doesn't exist.\n");
+        return 1;
+    }
+    
+    pwdstore_remove_entry(secrets, id);
+    
+    int ret = pwdstore_save(secrets);
+    if(ret) {
+        fprintf(stderr, "Error: saving srcrets store failed.\n");
+    }
+    return ret;
+}
+
+int cmd_remove_user(CmdArgs *args) {
+    return secretstore_cmd(args, FALSE, NULL, cmd_ss_remove_user, NULL);
+}
 
 int shell_completion(CmdArgs *args, int index) {
     if(args->argc < 2 || args->argc < 3) {
--- a/dav/main.h	Sat Oct 12 09:53:32 2019 +0200
+++ b/dav/main.h	Sat Oct 12 11:17:11 2019 +0200
@@ -131,6 +131,8 @@
 int cmd_repository_url(CmdArgs *args);
 
 int cmd_add_user(CmdArgs *args);
+int cmd_list_users(CmdArgs *args);
+int cmd_remove_user(CmdArgs *args);
 
 int shell_completion(CmdArgs *args, int index);
 
--- a/dav/pwd.c	Sat Oct 12 09:53:32 2019 +0200
+++ b/dav/pwd.c	Sat Oct 12 11:17:11 2019 +0200
@@ -191,6 +191,58 @@
     return ret;
 }
 
+static int remove_list_entries(PwdStore *s, const char *id) {
+    int ret = 0;
+    
+    UcxList *loc_entry = NULL;
+    UcxList *noloc_entry = NULL;
+    UCX_FOREACH(elm, s->locations) {
+        PwdIndexEntry *ie = elm->data;
+        if(!strcmp(ie->id, id)) {
+            loc_entry = elm;
+            ret = 1;
+            break;
+        }
+    }
+    UCX_FOREACH(elm, s->noloc) {
+        PwdIndexEntry *ie = elm->data;
+        if(!strcmp(ie->id, id)) {
+            noloc_entry = elm;
+            ret = 1;
+            break;
+        }
+    }
+    
+    if(loc_entry) {
+        s->locations = ucx_list_remove(s->locations, loc_entry);
+    }
+    if(noloc_entry) {
+        s->noloc = ucx_list_remove(s->noloc, noloc_entry);
+    }
+    
+    return ret;
+}
+
+void pwdstore_remove_entry(PwdStore *s, const char *id) {
+    while(remove_list_entries(s, id)) {}
+    
+    PwdIndexEntry *i = ucx_map_cstr_remove(s->index, id);
+    PwdEntry *e = ucx_map_cstr_remove(s->ids, id);
+    
+    if(i) {
+        ucx_list_free_content(i->locations, free);
+        ucx_list_free(i->locations);
+        free(i->id);
+        free(i);
+    }
+    if(e) {
+        free(e->id);
+        free(e->user);
+        free(e->password);
+        free(e);
+    }
+}
+
 int pwdstore_getindex(PwdStore *s) {
     uint32_t netindexlen;
     
--- a/dav/pwd.h	Sat Oct 12 09:53:32 2019 +0200
+++ b/dav/pwd.h	Sat Oct 12 11:17:11 2019 +0200
@@ -171,6 +171,8 @@
 void pwdstore_put(PwdStore *p, const char *id, const char *username, const char *password);
 void pwdstore_put_index(PwdStore *p, char *id, UcxList *locations);
 
+void pwdstore_remove_entry(PwdStore *s, const char *id);
+
 int pwdstore_store(PwdStore *p, const char *file);
 
 /* private */

mercurial