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 } |
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); |
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); |
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) { |