Sat, 03 Oct 2015 18:11:07 +0200
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; }