# HG changeset patch # User Olaf Wintermann # Date 1628419531 -7200 # Node ID e0358fa1a3b12bc7006d3ee48f290a74b9fc32b8 # Parent 83f832e345e07493765eeffd208646be3fd9bee4 implement secretstore unlock command diff -r 83f832e345e0 -r e0358fa1a3b1 dav/config.c --- a/dav/config.c Sun Aug 08 11:45:36 2021 +0200 +++ b/dav/config.c Sun Aug 08 12:45:31 2021 +0200 @@ -574,6 +574,10 @@ int load_secretstore(const xmlNode *node) { // currently only one secretstore is supported + if(!pstore) { + return 0; + } + node = node->children; int error = 0; while(node) { @@ -581,9 +585,9 @@ char *value = util_xml_get_text(node); if(value) { if(xstreq(node->name, "unlock-command")) { - secretstore_unlock_cmd = strdup(value); + pstore->unlock_cmd = strdup(value); } else if(xstreq(node->name, "lock-command")) { - secretstore_lock_cmd = strdup(value); + pstore->lock_cmd = strdup(value); } } } diff -r 83f832e345e0 -r e0358fa1a3b1 dav/main.c --- a/dav/main.c Sun Aug 08 11:45:36 2021 +0200 +++ b/dav/main.c Sun Aug 08 12:45:31 2021 +0200 @@ -466,10 +466,35 @@ return 1; } - char *ps_password = util_password_input("Master password: "); + char *ps_password = NULL; + if(secrets->unlock_cmd && strlen(secrets->unlock_cmd) > 0) { + UcxBuffer *cmd_out = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); + if(!util_exec_command(secrets->unlock_cmd, cmd_out)) { + // command successful, get first line from output without newline + // and use that as password for the secretstore + size_t len = 0; + for(size_t i=0;i<=cmd_out->size;i++) { + if(i == cmd_out->size || cmd_out->space[i] == '\n') { + len = i; + break; + } + } + if(len > 0) { + ps_password = malloc(len + 1); + memcpy(ps_password, cmd_out->space, len); + ps_password[len] = 0; + } + } + ucx_buffer_free(cmd_out); + } + if(!ps_password) { - return 1; + 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; diff -r 83f832e345e0 -r e0358fa1a3b1 dav/pwd.c --- a/dav/pwd.c Sun Aug 08 11:45:36 2021 +0200 +++ b/dav/pwd.c Sun Aug 08 12:45:31 2021 +0200 @@ -62,6 +62,8 @@ p->index = ucx_map_new(16); p->content = buf; p->key = NULL; + p->unlock_cmd = NULL; + p->lock_cmd = NULL; p->encoffset = PWDS_HEADER_SIZE; p->isdecrypted = 0; diff -r 83f832e345e0 -r e0358fa1a3b1 dav/pwd.h --- a/dav/pwd.h Sun Aug 08 11:45:36 2021 +0200 +++ b/dav/pwd.h Sun Aug 08 12:45:31 2021 +0200 @@ -115,6 +115,16 @@ DavKey *key; /* + * optional shell command, that is used for getting the master password + */ + char *unlock_cmd; + + /* + * optional shell command, that is exected when the secretstore is closed + */ + char *lock_cmd; + + /* * start offset of the encrypted buffer */ uint32_t encoffset; diff -r 83f832e345e0 -r e0358fa1a3b1 libidav/utils.c --- a/libidav/utils.c Sun Aug 08 11:45:36 2021 +0200 +++ b/libidav/utils.c Sun Aug 08 12:45:31 2021 +0200 @@ -44,6 +44,9 @@ #define IS_PATH_SEPARATOR(c) (c == '/' || c == '\\') #define PATH_SEPARATOR '\\' #else +#include +#include +#include #include #define getpasswordchar() getchar() #define IS_PATH_SEPARATOR(c) (c == '/') @@ -1114,6 +1117,55 @@ return str; } +int util_exec_command(char *command, UcxBuffer *outbuf) { +#ifdef _WIN32 + fprintf(stderr, "util_exec_command unsupported\n"); + return NULL; +#endif + + int pout[2]; + if(pipe(pout)) { + perror("pipe"); + return 1; + } + + int ret = 0; + + // close stdin and stderr, use pipe for stdout + posix_spawn_file_actions_t actions; + posix_spawn_file_actions_init(&actions); + posix_spawn_file_actions_addclose(&actions, 0); + posix_spawn_file_actions_adddup2(&actions, pout[1], 1); + posix_spawn_file_actions_addclose(&actions, 2); + + char *args[4]; + args[0] = "sh"; + args[1] = "-c"; + args[2] = command; + args[3] = NULL; + + pid_t pid; // child pid + ret = posix_spawn(&pid, "/bin/sh", &actions, NULL, args, NULL); + + close(pout[1]); + + if(!ret) { + ssize_t r; + char buf[1024]; + while((r = read(pout[0], buf, 1024)) > 0) { + ucx_buffer_write(buf, 1, r, outbuf); + } + } + + // wait for child process + ret = 1; + waitpid(pid, &ret, 0); + + posix_spawn_file_actions_destroy(&actions); + close(pout[0]); + + return ret; +} char* util_hexstr(const unsigned char *data, size_t len) { size_t buflen = 2*len + 4; diff -r 83f832e345e0 -r e0358fa1a3b1 libidav/utils.h --- a/libidav/utils.h Sun Aug 08 11:45:36 2021 +0200 +++ b/libidav/utils.h Sun Aug 08 12:45:31 2021 +0200 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -116,6 +117,8 @@ sstr_t util_readline(FILE *stream); char* util_password_input(char *prompt); +int util_exec_command(char *command, UcxBuffer *outbuf); + char* util_hexstr(const unsigned char *data, size_t len); void util_remove_trailing_pathseparator(char *path);