# HG changeset patch # User Olaf Wintermann # Date 1570871831 -7200 # Node ID 8f2b8f2a5cdef0150b0f35197aae22d9286d0550 # Parent f503c272bd70ca5c55310f68504bf3f28620d07a add remove-user and list-users commands diff -r f503c272bd70 -r 8f2b8f2a5cde dav/main.c --- 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) { diff -r f503c272bd70 -r 8f2b8f2a5cde dav/main.h --- 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); diff -r f503c272bd70 -r 8f2b8f2a5cde dav/pwd.c --- 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; diff -r f503c272bd70 -r 8f2b8f2a5cde dav/pwd.h --- 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 */