add support for secret store credentials when connecting to repositories, resolves #496

Thu, 14 Nov 2024 23:22:35 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 14 Nov 2024 23:22:35 +0100
changeset 85
44ebbb4c8a13
parent 84
57a359c52617
child 86
8e7c57c23133

add support for secret store credentials when connecting to repositories, resolves #496

application/config.c file | annotate | diff | comparison | revisions
application/config.h file | annotate | diff | comparison | revisions
application/davcontroller.c file | annotate | diff | comparison | revisions
application/davcontroller.h file | annotate | diff | comparison | revisions
libidav/pwdstore.h file | annotate | diff | comparison | revisions
--- 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);
 

mercurial