# HG changeset patch # User Olaf Wintermann # Date 1553770467 -3600 # Node ID 060a8cda7f627425ca77f5bd0939d9f8c4648c45 # Parent e59a989d890d3e53e3a306fd458068d7e722a58c adds wrapper functions for setting/getting the content hash diff -r e59a989d890d -r 060a8cda7f62 dav/sync.c --- a/dav/sync.c Thu Mar 28 11:19:13 2019 +0100 +++ b/dav/sync.c Thu Mar 28 11:54:27 2019 +0100 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Olaf Wintermann. All rights reserved. + * Copyright 2019 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -517,7 +517,7 @@ } int ret = 0; - DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags,idav:finfo,idav:xattributes from / with depth = infinity"); + DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags,idav:finfo,idav:xattributes,idav:content-hash from / with depth = infinity"); if(!ls) { print_resource_error(sn, "/"); if(locked) { @@ -2055,7 +2055,7 @@ int ret = 0; if(err == 0) { char *etag = dav_get_string_property(remote, "D:getetag"); - char *hash = dav_get_string_property(remote, "idav:content-hash"); + char *hash = sync_get_content_hash(remote); if(hash || res->hash) { if(!nullstrcmp(hash, res->hash)) { ret = 1; @@ -2810,9 +2810,8 @@ // set content-hash char content_hash[DAV_SHA256_DIGEST_LENGTH]; dav_hash_final(sha, content_hash); - char *hash_hex = util_hexstr(content_hash, DAV_SHA256_DIGEST_LENGTH); - dav_set_string_property_ns(res, DAV_NS, "content-hash", hash_hex); - local->hash = hash_hex; + sync_set_content_hash(res, content_hash); + local->hash = util_hexstr(content_hash, DAV_SHA256_DIGEST_LENGTH); // get etags from uploaded resources // also delete everything, that is not part of the file @@ -4134,3 +4133,46 @@ } } +char* sync_get_content_hash(DavResource *res) { + uint32_t flags = res->session->flags; + if((flags & DAV_SESSION_ENCRYPT_CONTENT) == DAV_SESSION_ENCRYPT_CONTENT) { + char *enc_hash = dav_get_string_property_ns(res, DAV_NS, "crypto-hash"); + char *keyname = dav_get_string_property_ns(res, DAV_NS, "crypto-key"); + if(enc_hash && keyname) { + DavKey *key = dav_context_get_key(res->session->context, keyname); + if(!key) { + return NULL; + } + + size_t len = 0; + char *dec_hash = aes_decrypt(enc_hash, &len, key); + if(!dec_hash) { + return NULL; + } + + char *hex_hash = util_hexstr((unsigned char*)dec_hash, len); + free(dec_hash); + return hex_hash; + } + } else { + return dav_get_string_property_ns(res, DAV_NS, "content-hash"); + } + return NULL; +} + +void sync_set_content_hash(DavResource *res, const char *hashdata) { + uint32_t flags = res->session->flags; + if((flags & DAV_SESSION_ENCRYPT_CONTENT) == DAV_SESSION_ENCRYPT_CONTENT) { + if(res->session->key) { + char *enc_hash = aes_encrypt(hashdata, DAV_SHA256_DIGEST_LENGTH, res->session->key); + if(enc_hash) { + dav_set_string_property_ns(res, DAV_NS, "crypto-hash", enc_hash); + free(enc_hash); + } + } + } else { + char *hex_hash = util_hexstr((const unsigned char*)hashdata, DAV_SHA256_DIGEST_LENGTH); + dav_set_string_property_ns(res, DAV_NS, "content-hash", hex_hash); + free(hex_hash); + } +} diff -r e59a989d890d -r 060a8cda7f62 dav/sync.h --- a/dav/sync.h Thu Mar 28 11:19:13 2019 +0100 +++ b/dav/sync.h Thu Mar 28 11:54:27 2019 +0100 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Olaf Wintermann. All rights reserved. + * Copyright 2019 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -203,6 +203,20 @@ char* create_locktoken_file(const char *syncdirname, const char *locktoken); +/* + * if encryption is enabled, the crypto-hash is returned as hex string + * otherwise the content-hash is returned + */ +char* sync_get_content_hash(DavResource *res); + +/* + * if encryption is enabled, sets the crypto-hash property + * otherwise it sets the content-hash property + * + * hashdata must be raw sha256 data and 32 bytes long + */ +void sync_set_content_hash(DavResource *res, const char *hashdata); + #ifdef __cplusplus } #endif diff -r e59a989d890d -r 060a8cda7f62 libidav/resource.c --- a/libidav/resource.c Thu Mar 28 11:19:13 2019 +0100 +++ b/libidav/resource.c Thu Mar 28 11:54:27 2019 +0100 @@ -855,7 +855,7 @@ if(res_hash) { size_t len = 0; char *dec_hash = aes_decrypt(res_hash, &len, key); - char *hex_hash = util_hexstr((unsigned char*)dec_hash, 32); + char *hex_hash = util_hexstr((unsigned char*)dec_hash, len); if(strcmp(hash, hex_hash)) { verify_failed = 1; } diff -r e59a989d890d -r 060a8cda7f62 libidav/utils.c --- a/libidav/utils.c Thu Mar 28 11:19:13 2019 +0100 +++ b/libidav/utils.c Thu Mar 28 11:54:27 2019 +0100 @@ -824,7 +824,7 @@ } -char* util_hexstr(unsigned char *data, size_t len) { +char* util_hexstr(const unsigned char *data, size_t len) { size_t buflen = 2*len + 4; UcxBuffer *buf = ucx_buffer_new(malloc(buflen), buflen + 1, 0); for(int i=0;i