application/config.c

changeset 7
905ac52c910f
parent 6
09ac07345656
equal deleted inserted replaced
6:09ac07345656 7:905ac52c910f
324 char* pwfile = util_concat_path(ENV_HOME, ".dav/secrets.crypt"); 324 char* pwfile = util_concat_path(ENV_HOME, ".dav/secrets.crypt");
325 int ret = pwdstore_store(pwdstore, pwfile); 325 int ret = pwdstore_store(pwdstore, pwfile);
326 free(pwfile); 326 free(pwfile);
327 return ret; 327 return ret;
328 } 328 }
329
330
331
332 static int decrypt_secrets(PwdStore *secrets) {
333 char *ps_password = NULL;
334 if(secrets->unlock_cmd && strlen(secrets->unlock_cmd) > 0) {
335 CxBuffer *cmd_out = cxBufferCreate(NULL, 128, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
336 if(!util_exec_command(secrets->unlock_cmd, cmd_out)) {
337 // command successful, get first line from output without newline
338 // and use that as password for the secretstore
339 size_t len = 0;
340 for(size_t i=0;i<=cmd_out->size;i++) {
341 if(i == cmd_out->size || cmd_out->space[i] == '\n') {
342 len = i;
343 break;
344 }
345 }
346 if(len > 0) {
347 ps_password = malloc(len + 1);
348 memcpy(ps_password, cmd_out->space, len);
349 ps_password[len] = 0;
350 }
351 }
352 cxBufferFree(cmd_out);
353 }
354
355 return 1;
356 // TODO
357 /*
358 if(!ps_password) {
359 ps_password = util_password_input("Master password: ");
360 if(!ps_password) {
361 return 1;
362 }
363 }
364
365 if(pwdstore_setpassword(secrets, ps_password)) {
366 fprintf(stderr, "Error: cannot create key from password\n");
367 return 1;
368 }
369 if(pwdstore_decrypt(secrets)) {
370 fprintf(stderr, "Error: cannot decrypt secrets store\n");
371 return 1;
372 }
373 return 0;
374 */
375 }
376
377
378 typedef struct CredLocation {
379 char *id;
380 char *location;
381 } CredLocation;
382
383 static int cmp_url_cred_entry(CredLocation *e1, CredLocation *e2, void *n) {
384 return strcmp(e2->location, e1->location);
385 }
386
387 static void free_cred_location(CredLocation *c) {
388 // c->id is not a copy, therefore we don't have to free it
389 free(c->location);
390 free(c);
391 }
392
393 static int get_stored_credentials(char *credid, char **user, char **password) {
394 return 0;
395 // TODO
396 /*
397 if(!credid) {
398 return 0;
399 }
400 PwdStore *secrets = get_pwdstore();
401 if(!secrets) {
402 fprintf(stderr, "Error: no secrets store available\n");
403 return 0;
404 }
405
406 if(pwdstore_has_id(secrets, credid)) {
407 if(!secrets->isdecrypted) {
408 if(decrypt_secrets(a, secrets)) {
409 return 0;
410 }
411 }
412
413 PwdEntry *s_cred = pwdstore_get(secrets, credid);
414 if(s_cred) {
415 *user = s_cred->user;
416 *password = s_cred->password;
417 return 1;
418 }
419 } else {
420 fprintf(stderr, "Error: credentials id '%s' not found\n", credid);
421 }
422
423 return 0;
424 */
425 }
426
427
428 static int get_location_credentials(DavCfgRepository *repo, const char *path, char **user, char **password) {
429 PwdStore *secrets = get_pwdstore();
430 if(!secrets) {
431 return 0;
432 }
433
434 /*
435 * The list secrets->location contains urls or repo names as
436 * location strings. We need a list, that contains only urls
437 */
438 CxList *locations = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)cmp_url_cred_entry, CX_STORE_POINTERS);
439 locations->simple_destructor = (cx_destructor_func)free_cred_location;
440 CxIterator i = cxListIterator(secrets->locations);
441 cx_foreach(PwdIndexEntry*, e, i) {
442 CxIterator entry_iter = cxListIterator(e->locations);
443 cx_foreach(char *, loc, entry_iter) {
444 cxmutstr rpath;
445 DavCfgRepository *r = dav_config_url2repo_s(davconfig, cx_str(loc), &rpath);
446 CredLocation *urlentry = calloc(1, sizeof(CredLocation));
447 urlentry->id = e->id;
448 urlentry->location = util_concat_path_s(cx_strcast(r->url.value), cx_strcast(rpath)).ptr;
449 cxListAdd(locations, urlentry);
450 free(rpath.ptr);
451 }
452 }
453 // the list must be sorted
454 cxListSort(locations);
455
456 // create full request url string and remove protocol prefix
457 cxmutstr req_url_proto = util_concat_path_s(cx_strcast(repo->url.value), cx_str(path));
458 cxstring req_url = cx_strcast(req_url_proto);
459 if(cx_strprefix(req_url, CX_STR("http://"))) {
460 req_url = cx_strsubs(req_url, 7);
461 } else if(cx_strprefix(req_url, CX_STR("https://"))) {
462 req_url = cx_strsubs(req_url, 8);
463 }
464
465 // iterate over sorted locations and check if a location is a prefix
466 // of the requested url
467 char *id = NULL;
468 int ret = 0;
469 i = cxListIterator(locations);
470 cx_foreach(CredLocation*, cred, i) {
471 cxstring cred_url = cx_str(cred->location);
472
473 // remove protocol prefix
474 if(cx_strprefix(cred_url, CX_STR("http://"))) {
475 cred_url = cx_strsubs(cred_url, 7);
476 } else if(cx_strprefix(cred_url, CX_STR("https://"))) {
477 cred_url = cx_strsubs(cred_url, 8);
478 }
479
480 if(cx_strprefix(req_url, cred_url)) {
481 id = cred->id;
482 break;
483 }
484 }
485
486 // if an id is found and we can access the decrypted secret store
487 // we can set the user/password
488 if(id && (secrets->isdecrypted || !decrypt_secrets(secrets))) {
489 PwdEntry *cred = pwdstore_get(secrets, id);
490 if(cred) {
491 *user = cred->user;
492 *password = cred->password;
493 ret = 1;
494 }
495 }
496
497 free(req_url_proto.ptr);
498 cxListDestroy(locations);
499
500 return ret;
501 }
502
503
504 DavSession* connect_to_repo(DavContext *ctx, DavCfgRepository *repo, const char *path, dav_auth_func authfunc) {
505 cxmutstr decodedpw = dav_repository_get_decodedpassword(repo);
506
507 char *user = repo->user.value.ptr;
508 char *password = decodedpw.ptr;
509
510 if(!user && !password) {
511 if(!get_stored_credentials(repo->stored_user.value.ptr, &user, &password)) {
512 get_location_credentials(repo, path, &user, &password);
513 }
514 }
515
516 DavSession *sn = dav_session_new_auth(ctx, repo->url.value.ptr, user, password);
517 if(password) {
518 free(password);
519 }
520
521 sn->flags = dav_repository_get_flags(repo);
522 sn->key = dav_context_get_key(ctx, repo->default_key.value.ptr);
523 curl_easy_setopt(sn->handle, CURLOPT_HTTPAUTH, repo->authmethods);
524 curl_easy_setopt(sn->handle, CURLOPT_SSLVERSION, repo->ssl_version);
525 if(repo->cert.value.ptr) {
526 curl_easy_setopt(sn->handle, CURLOPT_CAINFO, repo->cert.value.ptr);
527 }
528 if(!repo->verification.value) {
529 curl_easy_setopt(sn->handle, CURLOPT_SSL_VERIFYPEER, 0);
530 curl_easy_setopt(sn->handle, CURLOPT_SSL_VERIFYHOST, 0);
531 }
532
533 return sn;
534 }

mercurial