dav/main.c

changeset 473
6740adb5fccd
parent 472
08d2d1263429
child 474
017a4f09e6fa
--- a/dav/main.c	Thu Sep 20 13:07:38 2018 +0200
+++ b/dav/main.c	Thu Sep 20 17:14:55 2018 +0200
@@ -404,6 +404,25 @@
     }
 }
 
+static int decrypt_secrets(CmdArgs *a, PwdStore *secrets) {
+    if(cmd_getoption(a, "noinput")) {
+        return 1;
+    }
+    
+    char *ps_password = util_password_input("Master password: ");
+    if(!ps_password) {
+        return 1;
+    }
+    if(pwdstore_setpassword(secrets, ps_password)) {
+        fprintf(stderr, "Error: cannot create key from password\n");
+        return 1;
+    }
+    if(pwdstore_decrypt(secrets)) {
+        fprintf(stderr, "Error: cannot decrypt secrets store\n");
+        return 1;
+    }
+    return 0;
+}
 
 static int get_stored_credentials(CmdArgs *a, char *credid, char **user, char **password) {
     if(!credid) {
@@ -418,19 +437,7 @@
     
     if(pwdstore_has_id(secrets, credid)) {
         if(!secrets->isdecrypted) {
-            if(cmd_getoption(a, "noinput")) {
-                return 0;
-            }
-            char *ps_password = util_password_input("Master password: ");
-            if(!ps_password) {
-                return 0;
-            }
-            if(pwdstore_setpassword(secrets, ps_password)) {
-                fprintf(stderr, "Error: cannot create key from password\n");
-                return 0;
-            }
-            if(pwdstore_decrypt(secrets)) {
-                fprintf(stderr, "Error: cannot decrypt secrets store\n");
+            if(decrypt_secrets(a, secrets)) {
                 return 0;
             }
         }
@@ -448,17 +455,85 @@
     return 0;
 }
 
-static int get_location_credentials(CmdArgs *a, Repository *repo, char **user, char **password) {
-    return 0;
+static int cmp_url_cred_entry(PwdEntry *e1, PwdEntry *e2, void *n) {
+    return strcmp(e2->location, e1->location);
 }
 
-static DavSession* connect_to_repo(Repository *repo, CmdArgs *a) {
+static int get_location_credentials(CmdArgs *a, Repository *repo, char *path, char **user, char **password) {
+    PwdStore *secrets = get_pwdstore();
+    if(!secrets) {
+        return 0;
+    }
+    
+    /*
+     * The list secrets->location contains urls or repo names as
+     * location strings. We need a list, that contains only urls
+     */
+    UcxList *locations = NULL;
+    UCX_FOREACH(elm, secrets->locations) {
+        PwdEntry *e = elm->data;
+        char *path;
+        Repository *r = url2repo(e->location, &path);
+        PwdEntry *urlentry = calloc(1, sizeof(PwdEntry));
+        urlentry->id = strdup(e->id);
+        urlentry->location = util_concat_path(r->url, path);
+        locations = ucx_list_append(locations, urlentry);
+    }
+    // the list must be sorted
+    locations = ucx_list_sort(locations, (cmp_func)cmp_url_cred_entry, NULL);
+    
+    // create full request url string and remove protocol prefix
+    sstr_t req_url_proto = sstr(util_concat_path(repo->url, path));
+    sstr_t req_url = req_url_proto;
+    if(sstrprefix(req_url, S("http://"))) {
+        req_url = sstrsubs(req_url, 7);
+    } else if(sstrprefix(req_url, S("https://"))) {
+        req_url = sstrsubs(req_url, 8);
+    }
+    
+    // iterate over sorted locations and check if a location is a prefix
+    // of the requested url
+    char *id = NULL;
+    int ret = 0;
+    UCX_FOREACH(elm, locations) {
+        PwdEntry *cred = elm->data;
+        sstr_t cred_url = sstr(cred->location);
+        
+        // remove protocol prefix
+        if(sstrprefix(cred_url, S("http://"))) {
+            cred_url = sstrsubs(cred_url, 7);
+        } else if(sstrprefix(cred_url, S("https://"))) {
+            cred_url = sstrsubs(cred_url, 8);
+        }
+        
+        if(sstrprefix(req_url, cred_url)) {
+            id = cred->id;
+            break;
+        }
+    }
+    
+    // if an id is found and we can access the decrypted secret store
+    // we can set the user/password
+    if(id && (secrets->isdecrypted || !decrypt_secrets(a, secrets))) {
+        PwdEntry *cred = pwdstore_get(secrets, id);
+        *user = cred->user;
+        *password = cred->password;
+        ret = 1;
+    }
+    
+    free(req_url_proto.ptr);
+    ucx_list_free_content(locations, (ucx_destructor)pwdstore_free_entry);
+    
+    return ret;
+}
+
+static DavSession* connect_to_repo(Repository *repo, char *path, CmdArgs *a) {
     char *user = repo->user;
     char *password = repo->password;
     
     if(!user && !password) {
         if(!get_stored_credentials(a, repo->stored_user, &user, &password)) {
-            get_location_credentials(a, repo, &user, &password);
+            get_location_credentials(a, repo, path, &user, &password);
         }
     }
     
@@ -522,7 +597,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -789,7 +864,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1058,7 +1133,7 @@
     char *file = a->argv[1];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1323,7 +1398,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1357,7 +1432,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1408,7 +1483,7 @@
     char *srcpath = NULL;
     Repository *srcrepo = url2repo(srcurl, &srcpath);
     
-    DavSession *srcsn = connect_to_repo(srcrepo, a);
+    DavSession *srcsn = connect_to_repo(srcrepo, srcpath, a);
     if(set_session_config(srcsn, a)) {
         return -1;
     }
@@ -1433,7 +1508,7 @@
         char *srchost = util_url_base(srcrepo->url);
         char *desthost = util_url_base(destrepo->url);     
         if(!strcmp(srchost, desthost)) {
-            DavSession *destsn = connect_to_repo(destrepo, a);
+            DavSession *destsn = connect_to_repo(destrepo, destpath, a);
             if(set_session_config(destsn, a)) {
                 return -1;
             }
@@ -1489,7 +1564,8 @@
     } else if (a->argc == 1) {
         char *url = a->argv[0];
         char *path = NULL;
-        DavSession *sn = connect_to_repo(url2repo(url, &path), a);
+        Repository *repo = url2repo(url, &path);
+        DavSession *sn = connect_to_repo(repo, path, a);
 
         DavResource *res = dav_resource_new(sn, path);
         char *date = NULL;
@@ -1520,7 +1596,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1582,7 +1658,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1645,7 +1721,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -1686,7 +1762,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     ucx_mempool_reg_destr(sn->mp, path, free);
     
     if(set_session_config(sn, a)) {
@@ -1751,7 +1827,8 @@
     
     char *url = a->argv[0];
     char *path = NULL;
-    DavSession *sn = connect_to_repo(url2repo(url, &path), a);
+    Repository *repo = url2repo(url, &path);
+    DavSession *sn = connect_to_repo(repo, path, a);
     ucx_mempool_reg_destr(sn->mp, path, free);
     if(set_session_config(sn, a)) {
         return -1;
@@ -1811,7 +1888,7 @@
     char *url = a->argv[0];
     char *path = NULL;
     Repository *repo = url2repo(url, &path);
-    DavSession *sn = connect_to_repo(repo, a);
+    DavSession *sn = connect_to_repo(repo, path, a);
     
     if(set_session_config(sn, a)) {
         return -1;
@@ -2092,31 +2169,49 @@
 }
 
 int cmd_add_user(CmdArgs *args) {
+    char *master_pw = util_password_input("Master password: ");
+    if(!master_pw) {
+        return 1;
+    }
+    
+    PwdStore *secrets = get_pwdstore();
+    if(!secrets) {
+        secrets = pwdstore_new();
+    }
+    if(pwdstore_setpassword(secrets, master_pw)) {
+        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");
+    }
+    
+    
     char *id = assistant_getcfg("Credentials identifier");
+    if(id && pwdstore_get(secrets, id)) {
+        fprintf(stderr, "Credentials with this id already exist");
+        return 1;
+    }
     
     char *user = assistant_getcfg("User");
     char *password = util_password_input("Password: ");
+    char *location = assistant_getoptcfg("Location");
+    int ret = 1;
     if(user && password) {
-        PwdStore *pstore = get_pwdstore();
-        if(!pstore) {
-            pstore = pwdstore_new();
-        }
-        pwdstore_put(pstore, id, NULL, user, password);
-        char *master_pw = util_password_input("Master password: ");
-        if(!master_pw) {
-            return 1;
+        pwdstore_put(secrets, id, location, user, password);
+        int ret = pwdstore_save(secrets);
+        if(ret) {
+            fprintf(stderr, "Error: saving srcrets store failed.\n");
         }
-        if(pwdstore_setpassword(pstore, master_pw)) {
-            fprintf(stderr, "Error: Cannot generate key from password.\nAbort.\n");
-            return 1;
-        }
-        int ret = pwdstore_save(pstore);
-        if(ret) {
-            fprintf(stderr, "Error: saving password store failed.\n");
-        }
-        return ret;
     }
-    return 1;
+    
+    pwdstore_free(secrets);
+    if(id) free(id);
+    if(user) free(user);
+    if(password) free(password);
+    if(location) free(location);
+    
+    return ret;
 }
 
 
@@ -2215,7 +2310,7 @@
         
         char *path = NULL;
         Repository *repo = url2repo(u, &path);
-        DavSession *sn = connect_to_repo(repo, &a);
+        DavSession *sn = connect_to_repo(repo, path, &a);
         ucx_map_free(a.options);
         if(!sn) {
             return 0;

mercurial