Thu, 14 Nov 2024 23:22:35 +0100
add support for secret store credentials when connecting to repositories, resolves #496
--- a/application/config.c Thu Nov 14 22:28:36 2024 +0100 +++ b/application/config.c Thu Nov 14 23:22:35 2024 +0100 @@ -300,7 +300,7 @@ free(c); } -int get_stored_credentials(char *credid, char **user, char **password) { +int get_stored_credentials(const char *credid, char **user, char **password) { if(!credid) { return 0; } @@ -332,10 +332,10 @@ } -int get_location_credentials(DavCfgRepository *repo, const char *path, char **user, char **password) { +const char* get_location_credentials(DavCfgRepository *repo, const char *path) { PwdStore *secrets = get_pwdstore(); if(!secrets) { - return 0; + return NULL; } /* @@ -371,8 +371,7 @@ // iterate over sorted locations and check if a location is a prefix // of the requested url - char *id = NULL; - int ret = 0; + const char *id = NULL; i = cxListIterator(locations); cx_foreach(CredLocation*, cred, i) { cxstring cred_url = cx_str(cred->location); @@ -390,19 +389,8 @@ } } - // if an id is found and we can access the decrypted secret store - // we can set the user/password - if(id && (secrets->isdecrypted || !pwdstore_decrypt_secrets(secrets))) { - PwdEntry *cred = pwdstore_get(secrets, id); - if(cred) { - *user = cred->user; - *password = cred->password; - ret = 1; - } - } - free(req_url_proto.ptr); cxListDestroy(locations); - return ret; + return id; }
--- a/application/config.h Thu Nov 14 22:28:36 2024 +0100 +++ b/application/config.h Thu Nov 14 23:22:35 2024 +0100 @@ -66,8 +66,8 @@ int pwdstore_save(PwdStore *pwdstore); -int get_stored_credentials(char *credid, char **user, char **password); -int get_location_credentials(DavCfgRepository *repo, const char *path, char **user, char **password); +int get_stored_credentials(const char *credid, char **user, char **password); +const char* get_location_credentials(DavCfgRepository *repo, const char *path); #ifdef __cplusplus
--- a/application/davcontroller.c Thu Nov 14 22:28:36 2024 +0100 +++ b/application/davcontroller.c Thu Nov 14 23:22:35 2024 +0100 @@ -78,13 +78,101 @@ // ------------------------------ davbrowser_connect2repo ------------------------------ -void davbrowser_connect2repo(UiObject *ui, DavBrowser *browser, DavCfgRepository *repo, const char *path) { - DavSession *sn = dav_session_new(application_dav_context(), repo->url.value.ptr); +typedef struct DavConnect2Repo { + UiObject *ui; + DavBrowser *browser; + + DavCfgRepository *repo; + char *path; + + UiString *password; +} DavConnect2Repo; + +static void dialog_secretstore_decrypt(UiEvent *event, void *data) { + DavConnect2Repo *c2r = event->window; + + if(event->intval == 4) { + char *pw = ui_get(c2r->password); + + PwdStore *secrets = get_pwdstore(); + pwdstore_setpassword(secrets, pw); + if(pwdstore_decrypt(secrets)) { + ui_dialog(c2r->ui, .title = "Error", .content = "Cannot decrypt Secret Store", .closebutton_label = "OK"); + } else { + davbrowser_connect2repo(c2r->ui, c2r->browser, c2r->repo, c2r->path); + } + } + free(c2r->path); + if(!c2r->repo->node) { + dav_repository_free(get_config(), c2r->repo); + } + + ui_close(event->obj); +} + +int davbrowser_connect2repo(UiObject *ui, DavBrowser *browser, DavCfgRepository *repo, const char *path) { + char *user = NULL; + char *password = NULL; + char *password_free = NULL; if (repo->user.value.ptr && repo->password.value.ptr) { + user = repo->user.value.ptr; cxmutstr decodedpw = dav_repository_get_decodedpassword(repo); - dav_session_set_auth(sn, repo->user.value.ptr, decodedpw.ptr); - free(decodedpw.ptr); + password = decodedpw.ptr; + password_free = decodedpw.ptr; + } else { + PwdStore *secrets = get_pwdstore(); + const char *credentials = NULL; + if(repo->stored_user.value.ptr) { + if(pwdstore_has_id(secrets, repo->stored_user.value.ptr)) { + credentials = repo->stored_user.value.ptr; + } + } else { + credentials = get_location_credentials(repo, path); + } + + if(credentials) { + if(!secrets->isdecrypted) { + UiObject *obj = ui_dialog_window(ui, + .title = "Authentication", + .lbutton1 = "Cancel", + .rbutton4 = "Connect", + .default_button = 4, + .show_closebutton = UI_OFF, + .onclick = dialog_secretstore_decrypt); + + DavConnect2Repo *c2r = ui_malloc(obj->ctx, sizeof(DavConnect2Repo)); + c2r->ui = ui; + c2r->browser = browser; + c2r->repo = repo; + c2r->path = path ? strdup(path) : NULL; + c2r->password = ui_string_new(obj->ctx, NULL); + obj->window = c2r; + + ui_grid(obj, .margin = 20, .columnspacing = 12, .rowspacing = 16) { + ui_llabel(obj, .label = "Decrypt Secret Store", .colspan = 2); + ui_newline(obj); + + ui_llabel(obj, .label = "Password"); + ui_passwordfield(obj, .value = c2r->password, .hexpand = TRUE); + } + + ui_show(obj); + + return 1; + } + + if(!get_stored_credentials(credentials, &user, &password)) { + fprintf(stderr, "Error: failed to get user/password for credentials %s\n", credentials); + } + } } + + DavSession *sn = dav_session_new(application_dav_context(), repo->url.value.ptr); + if (user && password) { + dav_session_set_auth(sn, user, password); + } + free(password_free); + browser->sn = sn; if (repo->name.value.length > 0) { browser->repo_base = cx_strdup(cx_strn(repo->name.value.ptr, repo->name.value.length)).ptr; @@ -105,6 +193,8 @@ dav_session_set_authcallback(sn, jobthr_davbrowser_auth, auth); davbrowser_query_path(ui, browser, path); + + return 0; } // ------------------------------ davbrowser_auth ------------------------------ @@ -232,11 +322,13 @@ char *path = NULL; DavCfgRepository *repo = dav_config_url2repo(get_config(), url, &path); - davbrowser_connect2repo(ui, browser, repo, path); + + int ret = davbrowser_connect2repo(ui, browser, repo, path); + free(path); + if(ret) { + return; + } - if (path) { - free(path); - } if (!repo->node) { dav_repository_free(get_config(), repo); }
--- a/application/davcontroller.h Thu Nov 14 22:28:36 2024 +0100 +++ b/application/davcontroller.h Thu Nov 14 23:22:35 2024 +0100 @@ -50,7 +50,7 @@ void davbrowser_set_collection(UiObject *ui, DavBrowser *browser, DavResource *collection); -void davbrowser_connect2repo(UiObject *ui, DavBrowser *browser, DavCfgRepository *repo, const char *path); +int davbrowser_connect2repo(UiObject *ui, DavBrowser *browser, DavCfgRepository *repo, const char *path); void davbrowser_query_path(UiObject *ui, DavBrowser *browser, const char *path);
--- a/libidav/pwdstore.h Thu Nov 14 22:28:36 2024 +0100 +++ b/libidav/pwdstore.h Thu Nov 14 23:22:35 2024 +0100 @@ -181,7 +181,6 @@ void pwdstore_free(PwdStore* p); int pwdstore_has_id(PwdStore *s, const char *id); -int pwdstore_has_location(PwdStore *s, const char *location); PwdEntry* pwdstore_get(PwdStore *p, const char *id);