diff -r 509e9e1cbdcc -r 37fb12574acd libidav/resource.c --- a/libidav/resource.c Sat Oct 03 20:10:54 2015 +0200 +++ b/libidav/resource.c Sun Oct 04 15:57:40 2015 +0200 @@ -84,7 +84,7 @@ // set name, path and href sstr_t n = sstr(name); res->name = sstrdup_a(sn->mp->allocator, n).ptr; - if(n.ptr[n.length-1] == '/') { + if(n.length > 0 && n.ptr[n.length-1] == '/') { res->name[n.length-1] = '\0'; } @@ -570,12 +570,18 @@ (dav_read_func)ucx_buffer_read); } - // create an empty resource + // put resource ret = do_put_request( sn->handle, enc, (dav_read_func)aes_read, 0); + + // get sha256 hash + char sha[SHA256_DIGEST_LENGTH]; + dav_get_hash(&enc->sha256, sha); + char *enc_hash = aes_encrypt(sha, SHA256_DIGEST_LENGTH, sn->key); + aes_encrypter_close(enc); if(buf) { ucx_buffer_free(buf); @@ -583,9 +589,12 @@ // add crypto properties // TODO: store the properties later - if(resource_add_crypto_info(sn, res->href, res->name)) { + if(resource_add_crypto_info(sn, res->href, res->name, enc_hash)) { + free(enc_hash); return 1; } + resource_add_property(res, DAV_NS, "crypto-hash", enc_hash); + free(enc_hash); } else { ret = do_put_request( sn->handle, @@ -663,13 +672,41 @@ CURLcode ret = curl_easy_perform(handle); + char *hash = NULL; if(dec) { + // get hash + char sha[SHA256_DIGEST_LENGTH]; + dav_get_hash(&dec->sha256, sha); + hash = util_hexstr(sha, 32); + aes_decrypter_close(dec); } int status = 0; curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); if(ret == CURLE_OK && (status >= 200 && status < 300)) { + int verify_failed = 0; + if(DAV_DECRYPT_CONTENT(sn)) { + // try to verify the content + char *res_hash = dav_get_property_ns(res, DAV_NS, "crypto-hash"); + + if(res_hash) { + size_t len = 0; + char *dec_hash = aes_decrypt(res_hash, &len, sn->key); + char *hex_hash = util_hexstr(dec_hash, 32); + if(strcmp(hash, hex_hash)) { + verify_failed = 1; + } + free(dec_hash); + free(hex_hash); + } + } + + if(verify_failed) { + res->session->error = DAV_CONTENT_VERIFICATION_ERROR; + return 1; + } + res->session->error = DAV_OK; return 0; } else { @@ -733,7 +770,7 @@ if(name[len - 1] == '/') { name[len - 1] = '\0'; } - if(resource_add_crypto_info(sn, h, name)) { + if(resource_add_crypto_info(sn, h, name, NULL)) { // TODO: error } break; @@ -775,7 +812,7 @@ if(code == CURLE_OK && (s >= 200 && s < 300)) { sn->error = DAV_OK; // if the session has encrypted file names, add crypto infos - resource_add_crypto_info(sn, res->href, res->name); // TODO: check return type + resource_add_crypto_info(sn, res->href, res->name, NULL); // TODO: check return type // do a minimal propfind request UcxBuffer *rqbuf = create_propfind_request(sn, NULL); @@ -822,24 +859,27 @@ } -int resource_add_crypto_info(DavSession *sn, char *href, char *name) { +int resource_add_crypto_info(DavSession *sn, char *href, char *name, char *hash) { if(!DAV_IS_ENCRYPTED(sn)) { return 0; } - UcxBuffer *request = create_crypto_proppatch_request(sn, sn->key, name); + UcxBuffer *request = create_crypto_proppatch_request(sn, sn->key, name, hash); UcxBuffer *response = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); util_set_url(sn, href); CURLcode ret = do_proppatch_request(sn->handle, request, response); + ucx_buffer_free(request); int status = 0; curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &status); if(ret == CURLE_OK && status == 207) { // TODO: parse response - sn->error = DAV_OK; + sn->error = DAV_OK; + ucx_buffer_free(response); return 0; } else { dav_session_set_error(sn, ret, status); + ucx_buffer_free(response); return 1; } }