added password based keys and fixed crash when keys are missing

Sat, 03 Oct 2015 18:11:07 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 03 Oct 2015 18:11:07 +0200
changeset 147
458a8dc68048
parent 146
e48048334602
child 148
f21ee22170bf

added password based keys and fixed crash when keys are missing

dav/config.c file | annotate | diff | comparison | revisions
dav/main.c file | annotate | diff | comparison | revisions
dav/main.h file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
libidav/methods.c file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
libidav/utils.h file | annotate | diff | comparison | revisions
libidav/webdav.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/dav/config.c	Sat Oct 03 16:44:50 2015 +0200
+++ b/dav/config.c	Sat Oct 03 18:11:07 2015 +0200
@@ -321,6 +321,8 @@
                     key->type = KEY_AES128;
                 } else if(!strcmp(value, "aes256")) {
                     key->type = KEY_AES256;
+                } else if(!strcmp(value, "password")) {
+                    key->type = KEY_PASSWORD;
                 }
             }
                 
@@ -331,20 +333,41 @@
     if(key->name) {
         if(key->type == KEY_AES128) {
             if(key->length < 16) {
+                fprintf(
+                        stderr,
+                        "Error: Key %s is too small (%d < 16)\n",
+                        key->name,
+                        key->length);
                 return;
             }
             key->length = 16;
         }
         if(key->type == KEY_AES256) {
             if(key->length < 32) {
+                fprintf(
+                        stderr,
+                        "Error: Key %s is too small (%d < 32)\n",
+                        key->name,
+                        key->length);
                 return;
             }
             key->length = 32;
         }
+        if(key->type == KEY_PASSWORD) {
+            key->length = 0;
+            if(key->data) {
+                // make sure the pw-key is not loaded from a file
+                free(key->data);
+                key->data = NULL;
+            }
+        }
         ucx_map_cstr_put(keys, key->name, key);
         dav_context_add_key(context, key);
     } else {
-        // TODO: free
+        if(key->data) {
+            free(key->data);
+            free(key);
+        }
     }
 }
 
--- a/dav/main.c	Sat Oct 03 16:44:50 2015 +0200
+++ b/dav/main.c	Sat Oct 03 18:11:07 2015 +0200
@@ -68,6 +68,7 @@
     xmlGenericErrorFunc fnc = xmlerrorfnc;
     initGenericErrorDefaultFunc(&fnc);
     ctx = dav_context_new();
+    ctx->key_input = util_key_input;
     load_config(ctx);
     printxmlerror = 0;
 #ifdef DO_THE_TEST
@@ -175,49 +176,6 @@
     fprintf(stderr, "\n");
 }
 
-char* password_input(char *prompt) {
-    fprintf(stderr, "%s", prompt);
-    fflush(stderr);
-    
-    // hide terminal input
-#ifdef _WIN32
-    // TODO
-#else
-    struct termios oflags, nflags;
-    tcgetattr(fileno(stdin), &oflags);
-    nflags = oflags;
-    nflags.c_lflag &= ~ECHO;
-    nflags.c_lflag |= ECHONL;
-    if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
-        perror("tcsetattr");
-    }
-#endif
-    
-    // read password input
-    UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND);
-    int c = 0;
-    while((c = getchar()) != EOF) {
-        if(c == '\n') {
-            break;
-        }
-        ucx_buffer_putc(buf, c);
-    }
-    ucx_buffer_putc(buf, 0);
-    
-    // restore terminal settings
-#ifdef _WIN32
-    // TODO
-#else
-    if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
-        perror("tcsetattr");
-    }
-#endif
-    
-    char *str = buf->space;
-    free(buf); // only free the UcxBuffer struct
-    return str;
-}
-
 int request_auth(Repository *repo, DavSession *sn) {
     static int login = 0;
     if(login) {
@@ -234,7 +192,7 @@
         user = fgets(ubuf, 256, stdin);
     }
     
-    char *password = password_input("password: ");
+    char *password = util_password_input("password: ");
     
     size_t ulen = strlen(user);
     if(user[ulen-1] == '\n') {
--- a/dav/main.h	Sat Oct 03 16:44:50 2015 +0200
+++ b/dav/main.h	Sat Oct 03 18:11:07 2015 +0200
@@ -38,6 +38,8 @@
 #endif
 
 void print_usage(char *cmd);
+char* password_input(char *prompt);
+int request_auth(Repository *repo, DavSession *sn);
 
 int cmd_list(CmdArgs *args);
 void ls_print_list_elm(DavResource *res, CmdArgs *args);
--- a/dav/sync.c	Sat Oct 03 16:44:50 2015 +0200
+++ b/dav/sync.c	Sat Oct 03 18:11:07 2015 +0200
@@ -72,6 +72,7 @@
     xmlGenericErrorFunc fnc = xmlerrorfnc;
     initGenericErrorDefaultFunc(&fnc);
     ctx = dav_context_new();
+    ctx->key_input = util_key_input;
     load_config(ctx);
     
     // copy proxy config
--- a/libidav/methods.c	Sat Oct 03 16:44:50 2015 +0200
+++ b/libidav/methods.c	Sat Oct 03 18:11:07 2015 +0200
@@ -415,13 +415,14 @@
 DavResource* response2resource(DavSession *sn, ResponseTag *response, char *parent_path) {
     // create resource
     char *name = NULL;
-    if(DAV_DECRYPT_NAME(sn) && response->crypto_name) {
+    DavKey *key = NULL;
+    if(DAV_DECRYPT_NAME(sn) && response->crypto_name && (key = dav_context_get_key(sn->context, response->crypto_key))) {
         if(!response->crypto_key) {
             // TODO: error
             fprintf(stderr, "encrypted resource without key\n");
             return NULL;
         }
-        name = util_decrypt_str(sn, response->crypto_name, response->crypto_key);
+        name = util_decrypt_str_k(sn, response->crypto_name, key);
         if(!name) {
             // TODO: error
             fprintf(stderr, "decrypted name is null\n");
--- a/libidav/utils.c	Sat Oct 03 16:44:50 2015 +0200
+++ b/libidav/utils.c	Sat Oct 03 18:11:07 2015 +0200
@@ -36,6 +36,7 @@
 #include <ucx/utils.h>
 #include <libxml/tree.h>
 #include <curl/curl.h>
+#include <termios.h>
 
 #include <openssl/sha.h>
 #include <openssl/hmac.h>
@@ -304,7 +305,11 @@
         return NULL;
     }
     
-    char *enc_str = aes_encrypt(str, k);
+    return util_encrypt_str_k(sn, str, k);
+}
+
+char* util_encrypt_str_k(DavSession *sn, char *str, DavKey *key) {
+    char *enc_str = aes_encrypt(str, key);
     char *ret_str = dav_session_strdup(sn, enc_str);
     free(enc_str);
     return ret_str;
@@ -317,7 +322,11 @@
         return NULL;
     }
     
-    char *dec_str = aes_decrypt(str, k);
+    return util_decrypt_str_k(sn, str, k);
+}
+
+char* util_decrypt_str_k(DavSession *sn, char *str, DavKey *key) {
+    char *dec_str = aes_decrypt(str, key);
     char *ret_str = dav_session_strdup(sn, dec_str);
     free(dec_str);
     return ret_str;
@@ -399,3 +408,64 @@
     ucx_buffer_free(buf);
     return str;
 }
+
+char* util_password_input(char *prompt) {
+    fprintf(stderr, "%s", prompt);
+    fflush(stderr);
+    
+    // hide terminal input
+#ifdef _WIN32
+    // TODO
+#else
+    struct termios oflags, nflags;
+    tcgetattr(fileno(stdin), &oflags);
+    nflags = oflags;
+    nflags.c_lflag &= ~ECHO;
+    nflags.c_lflag |= ECHONL;
+    if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
+        perror("tcsetattr");
+    }
+#endif
+    
+    // read password input
+    UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND);
+    int c = 0;
+    while((c = getchar()) != EOF) {
+        if(c == '\n') {
+            break;
+        }
+        ucx_buffer_putc(buf, c);
+    }
+    ucx_buffer_putc(buf, 0);
+    
+    // restore terminal settings
+#ifdef _WIN32
+    // TODO
+#else
+    if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
+        perror("tcsetattr");
+    }
+#endif
+    
+    char *str = buf->space;
+    free(buf); // only free the UcxBuffer struct
+    return str;
+}
+
+void util_generate_key(DavKey *key, char *password) {
+    key->data = malloc(SHA256_DIGEST_LENGTH);
+    key->length = SHA256_DIGEST_LENGTH;
+    key->type =  DAV_KEY_AES256;
+    
+    SHA256_CTX sha256;
+    SHA256_Init(&sha256);
+    SHA256_Update(&sha256, password, strlen(password));
+    SHA256_Final(key->data, &sha256);
+}
+
+char* util_key_input(DavContext *ctx, DavKey *key) {
+    sstr_t prompt = ucx_sprintf("Enter password for key (%s): ", key->name);
+    char *password = util_password_input(prompt.ptr);
+    free(prompt.ptr);
+    return password;
+}
--- a/libidav/utils.h	Sat Oct 03 16:44:50 2015 +0200
+++ b/libidav/utils.h	Sat Oct 03 18:11:07 2015 +0200
@@ -77,13 +77,19 @@
 char* util_base64encode(char *in, size_t len);
 
 char* util_encrypt_str(DavSession *sn, char *str, char *key);
+char* util_encrypt_str_k(DavSession *sn, char *str, DavKey *key);
 char* util_decrypt_str(DavSession *sn, char *str, char *key);
+char* util_decrypt_str_k(DavSession *sn, char *str, DavKey *key);
 
 char* util_random_str();
 
 sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub);
 
 sstr_t util_readline(FILE *stream);
+char* util_password_input(char *prompt);
+
+void util_generate_key(DavKey *key, char *password);
+char* util_key_input(DavContext *ctx, DavKey *key);
 
 #ifdef	__cplusplus
 }
--- a/libidav/webdav.c	Sat Oct 03 16:44:50 2015 +0200
+++ b/libidav/webdav.c	Sat Oct 03 18:11:07 2015 +0200
@@ -185,7 +185,21 @@
 
 DavKey* dav_context_get_key(DavContext *context, char *name) {
     if(name) {
-        return ucx_map_cstr_get(context->keys, name);
+        DavKey *key = ucx_map_cstr_get(context->keys, name);
+        if(key && key->type == DAV_KEY_PASSWORD && !key->data) {
+            char *pw = NULL;
+            if(context->key_input && (pw = context->key_input(context, key))) {
+                // generate key
+                util_generate_key(key, pw);
+            } else {
+                // cannot generate key from password
+                key = NULL;
+            }
+            if(pw) {
+                free(pw);
+            }
+        }
+        return key;
     } else {
         return NULL;
     }
--- a/libidav/webdav.h	Sat Oct 03 16:44:50 2015 +0200
+++ b/libidav/webdav.h	Sat Oct 03 18:11:07 2015 +0200
@@ -124,6 +124,7 @@
     UcxList *sessions;
     DavProxy *http_proxy;
     DavProxy *https_proxy;
+    char* (*key_input)(DavContext *ctx, DavKey *key);
 };
 
 struct DavProxy {

mercurial