implement secretstore unlock command

Sun, 08 Aug 2021 12:45:31 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 08 Aug 2021 12:45:31 +0200
changeset 731
e0358fa1a3b1
parent 730
83f832e345e0
child 732
b0eb645cd26e

implement secretstore unlock command

dav/config.c file | annotate | diff | comparison | revisions
dav/main.c file | annotate | diff | comparison | revisions
dav/pwd.c file | annotate | diff | comparison | revisions
dav/pwd.h file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
libidav/utils.h file | annotate | diff | comparison | revisions
--- 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);
                 }
             }
         }
--- 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;
--- 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;
     
--- 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;
--- 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 <unistd.h>
+#include <spawn.h>
+#include <sys/wait.h>
 #include <termios.h>
 #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;
--- 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 <sys/types.h>
 #include <libxml/tree.h>
 #include <ucx/string.h>
+#include <ucx/buffer.h>
 #include <sys/stat.h>
 #include <inttypes.h>
 
@@ -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);

mercurial