libidav/resource.c

changeset 150
37fb12574acd
parent 146
e48048334602
child 151
a316613205dc
--- 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;
     }
 }

mercurial