dav/main.c

changeset 473
6740adb5fccd
parent 472
08d2d1263429
child 474
017a4f09e6fa
equal deleted inserted replaced
472:08d2d1263429 473:6740adb5fccd
402 DavLock *lock = dav_create_lock(sn, locktoken, NULL); 402 DavLock *lock = dav_create_lock(sn, locktoken, NULL);
403 dav_add_collection_lock(sn, "/", lock); 403 dav_add_collection_lock(sn, "/", lock);
404 } 404 }
405 } 405 }
406 406
407 static int decrypt_secrets(CmdArgs *a, PwdStore *secrets) {
408 if(cmd_getoption(a, "noinput")) {
409 return 1;
410 }
411
412 char *ps_password = util_password_input("Master password: ");
413 if(!ps_password) {
414 return 1;
415 }
416 if(pwdstore_setpassword(secrets, ps_password)) {
417 fprintf(stderr, "Error: cannot create key from password\n");
418 return 1;
419 }
420 if(pwdstore_decrypt(secrets)) {
421 fprintf(stderr, "Error: cannot decrypt secrets store\n");
422 return 1;
423 }
424 return 0;
425 }
407 426
408 static int get_stored_credentials(CmdArgs *a, char *credid, char **user, char **password) { 427 static int get_stored_credentials(CmdArgs *a, char *credid, char **user, char **password) {
409 if(!credid) { 428 if(!credid) {
410 return 0; 429 return 0;
411 } 430 }
416 return 0; 435 return 0;
417 } 436 }
418 437
419 if(pwdstore_has_id(secrets, credid)) { 438 if(pwdstore_has_id(secrets, credid)) {
420 if(!secrets->isdecrypted) { 439 if(!secrets->isdecrypted) {
421 if(cmd_getoption(a, "noinput")) { 440 if(decrypt_secrets(a, secrets)) {
422 return 0;
423 }
424 char *ps_password = util_password_input("Master password: ");
425 if(!ps_password) {
426 return 0;
427 }
428 if(pwdstore_setpassword(secrets, ps_password)) {
429 fprintf(stderr, "Error: cannot create key from password\n");
430 return 0;
431 }
432 if(pwdstore_decrypt(secrets)) {
433 fprintf(stderr, "Error: cannot decrypt secrets store\n");
434 return 0; 441 return 0;
435 } 442 }
436 } 443 }
437 444
438 PwdEntry *s_cred = pwdstore_get(secrets, credid); 445 PwdEntry *s_cred = pwdstore_get(secrets, credid);
446 } 453 }
447 454
448 return 0; 455 return 0;
449 } 456 }
450 457
451 static int get_location_credentials(CmdArgs *a, Repository *repo, char **user, char **password) { 458 static int cmp_url_cred_entry(PwdEntry *e1, PwdEntry *e2, void *n) {
452 return 0; 459 return strcmp(e2->location, e1->location);
453 } 460 }
454 461
455 static DavSession* connect_to_repo(Repository *repo, CmdArgs *a) { 462 static int get_location_credentials(CmdArgs *a, Repository *repo, char *path, char **user, char **password) {
463 PwdStore *secrets = get_pwdstore();
464 if(!secrets) {
465 return 0;
466 }
467
468 /*
469 * The list secrets->location contains urls or repo names as
470 * location strings. We need a list, that contains only urls
471 */
472 UcxList *locations = NULL;
473 UCX_FOREACH(elm, secrets->locations) {
474 PwdEntry *e = elm->data;
475 char *path;
476 Repository *r = url2repo(e->location, &path);
477 PwdEntry *urlentry = calloc(1, sizeof(PwdEntry));
478 urlentry->id = strdup(e->id);
479 urlentry->location = util_concat_path(r->url, path);
480 locations = ucx_list_append(locations, urlentry);
481 }
482 // the list must be sorted
483 locations = ucx_list_sort(locations, (cmp_func)cmp_url_cred_entry, NULL);
484
485 // create full request url string and remove protocol prefix
486 sstr_t req_url_proto = sstr(util_concat_path(repo->url, path));
487 sstr_t req_url = req_url_proto;
488 if(sstrprefix(req_url, S("http://"))) {
489 req_url = sstrsubs(req_url, 7);
490 } else if(sstrprefix(req_url, S("https://"))) {
491 req_url = sstrsubs(req_url, 8);
492 }
493
494 // iterate over sorted locations and check if a location is a prefix
495 // of the requested url
496 char *id = NULL;
497 int ret = 0;
498 UCX_FOREACH(elm, locations) {
499 PwdEntry *cred = elm->data;
500 sstr_t cred_url = sstr(cred->location);
501
502 // remove protocol prefix
503 if(sstrprefix(cred_url, S("http://"))) {
504 cred_url = sstrsubs(cred_url, 7);
505 } else if(sstrprefix(cred_url, S("https://"))) {
506 cred_url = sstrsubs(cred_url, 8);
507 }
508
509 if(sstrprefix(req_url, cred_url)) {
510 id = cred->id;
511 break;
512 }
513 }
514
515 // if an id is found and we can access the decrypted secret store
516 // we can set the user/password
517 if(id && (secrets->isdecrypted || !decrypt_secrets(a, secrets))) {
518 PwdEntry *cred = pwdstore_get(secrets, id);
519 *user = cred->user;
520 *password = cred->password;
521 ret = 1;
522 }
523
524 free(req_url_proto.ptr);
525 ucx_list_free_content(locations, (ucx_destructor)pwdstore_free_entry);
526
527 return ret;
528 }
529
530 static DavSession* connect_to_repo(Repository *repo, char *path, CmdArgs *a) {
456 char *user = repo->user; 531 char *user = repo->user;
457 char *password = repo->password; 532 char *password = repo->password;
458 533
459 if(!user && !password) { 534 if(!user && !password) {
460 if(!get_stored_credentials(a, repo->stored_user, &user, &password)) { 535 if(!get_stored_credentials(a, repo->stored_user, &user, &password)) {
461 get_location_credentials(a, repo, &user, &password); 536 get_location_credentials(a, repo, path, &user, &password);
462 } 537 }
463 } 538 }
464 539
465 DavSession *sn = dav_session_new_auth(ctx, repo->url, user, password); 540 DavSession *sn = dav_session_new_auth(ctx, repo->url, user, password);
466 sn->flags = get_repository_flags(repo); 541 sn->flags = get_repository_flags(repo);
520 } 595 }
521 596
522 char *url = a->argv[0]; 597 char *url = a->argv[0];
523 char *path = NULL; 598 char *path = NULL;
524 Repository *repo = url2repo(url, &path); 599 Repository *repo = url2repo(url, &path);
525 DavSession *sn = connect_to_repo(repo, a); 600 DavSession *sn = connect_to_repo(repo, path, a);
526 601
527 if(set_session_config(sn, a)) { 602 if(set_session_config(sn, a)) {
528 return -1; 603 return -1;
529 } 604 }
530 605
787 } 862 }
788 863
789 char *url = a->argv[0]; 864 char *url = a->argv[0];
790 char *path = NULL; 865 char *path = NULL;
791 Repository *repo = url2repo(url, &path); 866 Repository *repo = url2repo(url, &path);
792 DavSession *sn = connect_to_repo(repo, a); 867 DavSession *sn = connect_to_repo(repo, path, a);
793 868
794 if(set_session_config(sn, a)) { 869 if(set_session_config(sn, a)) {
795 return -1; 870 return -1;
796 } 871 }
797 872
1056 1131
1057 char *url = a->argv[0]; 1132 char *url = a->argv[0];
1058 char *file = a->argv[1]; 1133 char *file = a->argv[1];
1059 char *path = NULL; 1134 char *path = NULL;
1060 Repository *repo = url2repo(url, &path); 1135 Repository *repo = url2repo(url, &path);
1061 DavSession *sn = connect_to_repo(repo, a); 1136 DavSession *sn = connect_to_repo(repo, path, a);
1062 1137
1063 if(set_session_config(sn, a)) { 1138 if(set_session_config(sn, a)) {
1064 return -1; 1139 return -1;
1065 } 1140 }
1066 set_session_lock(sn, a); 1141 set_session_lock(sn, a);
1321 } 1396 }
1322 1397
1323 char *url = a->argv[0]; 1398 char *url = a->argv[0];
1324 char *path = NULL; 1399 char *path = NULL;
1325 Repository *repo = url2repo(url, &path); 1400 Repository *repo = url2repo(url, &path);
1326 DavSession *sn = connect_to_repo(repo, a); 1401 DavSession *sn = connect_to_repo(repo, path, a);
1327 1402
1328 if(set_session_config(sn, a)) { 1403 if(set_session_config(sn, a)) {
1329 return -1; 1404 return -1;
1330 } 1405 }
1331 set_session_lock(sn, a); 1406 set_session_lock(sn, a);
1355 } 1430 }
1356 1431
1357 char *url = a->argv[0]; 1432 char *url = a->argv[0];
1358 char *path = NULL; 1433 char *path = NULL;
1359 Repository *repo = url2repo(url, &path); 1434 Repository *repo = url2repo(url, &path);
1360 DavSession *sn = connect_to_repo(repo, a); 1435 DavSession *sn = connect_to_repo(repo, path, a);
1361 1436
1362 if(set_session_config(sn, a)) { 1437 if(set_session_config(sn, a)) {
1363 return -1; 1438 return -1;
1364 } 1439 }
1365 set_session_lock(sn, a); 1440 set_session_lock(sn, a);
1406 1481
1407 char *srcurl = a->argv[0]; 1482 char *srcurl = a->argv[0];
1408 char *srcpath = NULL; 1483 char *srcpath = NULL;
1409 Repository *srcrepo = url2repo(srcurl, &srcpath); 1484 Repository *srcrepo = url2repo(srcurl, &srcpath);
1410 1485
1411 DavSession *srcsn = connect_to_repo(srcrepo, a); 1486 DavSession *srcsn = connect_to_repo(srcrepo, srcpath, a);
1412 if(set_session_config(srcsn, a)) { 1487 if(set_session_config(srcsn, a)) {
1413 return -1; 1488 return -1;
1414 } 1489 }
1415 set_session_lock(srcsn, a); 1490 set_session_lock(srcsn, a);
1416 1491
1431 } 1506 }
1432 } else { 1507 } else {
1433 char *srchost = util_url_base(srcrepo->url); 1508 char *srchost = util_url_base(srcrepo->url);
1434 char *desthost = util_url_base(destrepo->url); 1509 char *desthost = util_url_base(destrepo->url);
1435 if(!strcmp(srchost, desthost)) { 1510 if(!strcmp(srchost, desthost)) {
1436 DavSession *destsn = connect_to_repo(destrepo, a); 1511 DavSession *destsn = connect_to_repo(destrepo, destpath, a);
1437 if(set_session_config(destsn, a)) { 1512 if(set_session_config(destsn, a)) {
1438 return -1; 1513 return -1;
1439 } 1514 }
1440 DavResource *dest = dav_resource_new(destsn, destpath); 1515 DavResource *dest = dav_resource_new(destsn, destpath);
1441 char *desthref = dav_resource_get_href(dest); 1516 char *desthref = dav_resource_get_href(dest);
1487 size_t len = strftime(str, 32, "%a, %d %b %Y %H:%M:%S GMT\n", date); 1562 size_t len = strftime(str, 32, "%a, %d %b %Y %H:%M:%S GMT\n", date);
1488 fwrite(str, 1, len, stdout); 1563 fwrite(str, 1, len, stdout);
1489 } else if (a->argc == 1) { 1564 } else if (a->argc == 1) {
1490 char *url = a->argv[0]; 1565 char *url = a->argv[0];
1491 char *path = NULL; 1566 char *path = NULL;
1492 DavSession *sn = connect_to_repo(url2repo(url, &path), a); 1567 Repository *repo = url2repo(url, &path);
1568 DavSession *sn = connect_to_repo(repo, path, a);
1493 1569
1494 DavResource *res = dav_resource_new(sn, path); 1570 DavResource *res = dav_resource_new(sn, path);
1495 char *date = NULL; 1571 char *date = NULL;
1496 curl_easy_setopt(sn->handle, CURLOPT_HEADERFUNCTION, get_date_header_cb); 1572 curl_easy_setopt(sn->handle, CURLOPT_HEADERFUNCTION, get_date_header_cb);
1497 curl_easy_setopt(sn->handle, CURLOPT_WRITEHEADER, &date); 1573 curl_easy_setopt(sn->handle, CURLOPT_WRITEHEADER, &date);
1518 } 1594 }
1519 1595
1520 char *url = a->argv[0]; 1596 char *url = a->argv[0];
1521 char *path = NULL; 1597 char *path = NULL;
1522 Repository *repo = url2repo(url, &path); 1598 Repository *repo = url2repo(url, &path);
1523 DavSession *sn = connect_to_repo(repo, a); 1599 DavSession *sn = connect_to_repo(repo, path, a);
1524 1600
1525 if(set_session_config(sn, a)) { 1601 if(set_session_config(sn, a)) {
1526 return -1; 1602 return -1;
1527 } 1603 }
1528 1604
1580 } 1656 }
1581 1657
1582 char *url = a->argv[0]; 1658 char *url = a->argv[0];
1583 char *path = NULL; 1659 char *path = NULL;
1584 Repository *repo = url2repo(url, &path); 1660 Repository *repo = url2repo(url, &path);
1585 DavSession *sn = connect_to_repo(repo, a); 1661 DavSession *sn = connect_to_repo(repo, path, a);
1586 1662
1587 if(set_session_config(sn, a)) { 1663 if(set_session_config(sn, a)) {
1588 return -1; 1664 return -1;
1589 } 1665 }
1590 set_session_lock(sn, a); 1666 set_session_lock(sn, a);
1643 } 1719 }
1644 1720
1645 char *url = a->argv[0]; 1721 char *url = a->argv[0];
1646 char *path = NULL; 1722 char *path = NULL;
1647 Repository *repo = url2repo(url, &path); 1723 Repository *repo = url2repo(url, &path);
1648 DavSession *sn = connect_to_repo(repo, a); 1724 DavSession *sn = connect_to_repo(repo, path, a);
1649 1725
1650 if(set_session_config(sn, a)) { 1726 if(set_session_config(sn, a)) {
1651 return -1; 1727 return -1;
1652 } 1728 }
1653 1729
1684 } 1760 }
1685 1761
1686 char *url = a->argv[0]; 1762 char *url = a->argv[0];
1687 char *path = NULL; 1763 char *path = NULL;
1688 Repository *repo = url2repo(url, &path); 1764 Repository *repo = url2repo(url, &path);
1689 DavSession *sn = connect_to_repo(repo, a); 1765 DavSession *sn = connect_to_repo(repo, path, a);
1690 ucx_mempool_reg_destr(sn->mp, path, free); 1766 ucx_mempool_reg_destr(sn->mp, path, free);
1691 1767
1692 if(set_session_config(sn, a)) { 1768 if(set_session_config(sn, a)) {
1693 return -1; 1769 return -1;
1694 } 1770 }
1749 return -1; 1825 return -1;
1750 } 1826 }
1751 1827
1752 char *url = a->argv[0]; 1828 char *url = a->argv[0];
1753 char *path = NULL; 1829 char *path = NULL;
1754 DavSession *sn = connect_to_repo(url2repo(url, &path), a); 1830 Repository *repo = url2repo(url, &path);
1831 DavSession *sn = connect_to_repo(repo, path, a);
1755 ucx_mempool_reg_destr(sn->mp, path, free); 1832 ucx_mempool_reg_destr(sn->mp, path, free);
1756 if(set_session_config(sn, a)) { 1833 if(set_session_config(sn, a)) {
1757 return -1; 1834 return -1;
1758 } 1835 }
1759 1836
1809 } 1886 }
1810 1887
1811 char *url = a->argv[0]; 1888 char *url = a->argv[0];
1812 char *path = NULL; 1889 char *path = NULL;
1813 Repository *repo = url2repo(url, &path); 1890 Repository *repo = url2repo(url, &path);
1814 DavSession *sn = connect_to_repo(repo, a); 1891 DavSession *sn = connect_to_repo(repo, path, a);
1815 1892
1816 if(set_session_config(sn, a)) { 1893 if(set_session_config(sn, a)) {
1817 return -1; 1894 return -1;
1818 } 1895 }
1819 1896
2090 return -1; 2167 return -1;
2091 } 2168 }
2092 } 2169 }
2093 2170
2094 int cmd_add_user(CmdArgs *args) { 2171 int cmd_add_user(CmdArgs *args) {
2172 char *master_pw = util_password_input("Master password: ");
2173 if(!master_pw) {
2174 return 1;
2175 }
2176
2177 PwdStore *secrets = get_pwdstore();
2178 if(!secrets) {
2179 secrets = pwdstore_new();
2180 }
2181 if(pwdstore_setpassword(secrets, master_pw)) {
2182 fprintf(stderr, "Error: Cannot generate key from password.\nAbort.\n");
2183 return 1;
2184 }
2185 if(pwdstore_decrypt(secrets)) {
2186 fprintf(stderr, "Error: Cannot decrypt secrets store.\nAbort.\n");
2187 }
2188
2189
2095 char *id = assistant_getcfg("Credentials identifier"); 2190 char *id = assistant_getcfg("Credentials identifier");
2191 if(id && pwdstore_get(secrets, id)) {
2192 fprintf(stderr, "Credentials with this id already exist");
2193 return 1;
2194 }
2096 2195
2097 char *user = assistant_getcfg("User"); 2196 char *user = assistant_getcfg("User");
2098 char *password = util_password_input("Password: "); 2197 char *password = util_password_input("Password: ");
2198 char *location = assistant_getoptcfg("Location");
2199 int ret = 1;
2099 if(user && password) { 2200 if(user && password) {
2100 PwdStore *pstore = get_pwdstore(); 2201 pwdstore_put(secrets, id, location, user, password);
2101 if(!pstore) { 2202 int ret = pwdstore_save(secrets);
2102 pstore = pwdstore_new();
2103 }
2104 pwdstore_put(pstore, id, NULL, user, password);
2105 char *master_pw = util_password_input("Master password: ");
2106 if(!master_pw) {
2107 return 1;
2108 }
2109 if(pwdstore_setpassword(pstore, master_pw)) {
2110 fprintf(stderr, "Error: Cannot generate key from password.\nAbort.\n");
2111 return 1;
2112 }
2113 int ret = pwdstore_save(pstore);
2114 if(ret) { 2203 if(ret) {
2115 fprintf(stderr, "Error: saving password store failed.\n"); 2204 fprintf(stderr, "Error: saving srcrets store failed.\n");
2116 } 2205 }
2117 return ret; 2206 }
2118 } 2207
2119 return 1; 2208 pwdstore_free(secrets);
2209 if(id) free(id);
2210 if(user) free(user);
2211 if(password) free(password);
2212 if(location) free(location);
2213
2214 return ret;
2120 } 2215 }
2121 2216
2122 2217
2123 int shell_completion(CmdArgs *args, int index) { 2218 int shell_completion(CmdArgs *args, int index) {
2124 if(args->argc < 2 || args->argc < 3) { 2219 if(args->argc < 2 || args->argc < 3) {
2213 a.options = ucx_map_new(4); 2308 a.options = ucx_map_new(4);
2214 ucx_map_cstr_put(a.options, "noinput", ""); 2309 ucx_map_cstr_put(a.options, "noinput", "");
2215 2310
2216 char *path = NULL; 2311 char *path = NULL;
2217 Repository *repo = url2repo(u, &path); 2312 Repository *repo = url2repo(u, &path);
2218 DavSession *sn = connect_to_repo(repo, &a); 2313 DavSession *sn = connect_to_repo(repo, path, &a);
2219 ucx_map_free(a.options); 2314 ucx_map_free(a.options);
2220 if(!sn) { 2315 if(!sn) {
2221 return 0; 2316 return 0;
2222 } 2317 }
2223 2318

mercurial