Mon, 14 Mar 2016 11:54:55 +0100
fixed hash verification and head requests
dav/error.c | file | annotate | diff | comparison | revisions | |
dav/main.c | file | annotate | diff | comparison | revisions | |
libidav/crypto.c | file | annotate | diff | comparison | revisions | |
libidav/crypto.h | file | annotate | diff | comparison | revisions | |
libidav/methods.c | file | annotate | diff | comparison | revisions | |
libidav/methods.h | file | annotate | diff | comparison | revisions | |
libidav/resource.c | file | annotate | diff | comparison | revisions | |
libidav/session.c | file | annotate | diff | comparison | revisions | |
libidav/webdav.h | file | annotate | diff | comparison | revisions |
--- a/dav/error.c Sun Mar 06 15:19:50 2016 +0100 +++ b/dav/error.c Mon Mar 14 11:54:55 2016 +0100 @@ -66,6 +66,12 @@ res_url); break; } + case DAV_LOCKED: { + fprintf( + stderr, + "Resource is locked.\n"); + break; + } case DAV_UNSUPPORTED_PROTOCOL: { fprintf(stderr, "Unsupported protocol.\n"); if(sn->errorstr) { @@ -96,6 +102,13 @@ } break; } + case DAV_CONTENT_VERIFICATION_ERROR: { + fprintf( + stderr, + "Content checksum verification failed for resource %s.\n", + res_url); + break; + } } free(res_url); }
--- a/dav/main.c Sun Mar 06 15:19:50 2016 +0100 +++ b/dav/main.c Mon Mar 14 11:54:55 2016 +0100 @@ -672,7 +672,10 @@ int ret = dav_get_content(res, fout, (dav_write_func)fwrite); fclose(fout); if(ret && strcmp(out, "-")) { - unlink(out); + print_resource_error(res->session, res->path); + //if(strcmp(out, "-")) { + // unlink(out); + //} } return 0;
--- a/libidav/crypto.c Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/crypto.c Mon Mar 14 11:54:55 2016 +0100 @@ -35,7 +35,7 @@ #include "crypto.h" AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func) { - AESDecrypter *dec = malloc(sizeof(AESDecrypter)); + AESDecrypter *dec = calloc(1, sizeof(AESDecrypter)); SHA256_Init(&dec->sha256); dec->stream = stream; dec->write = write_func; @@ -96,13 +96,17 @@ return (s*n) / s; } -void aes_decrypter_close(AESDecrypter *dec) { +void aes_decrypter_shutdown(AESDecrypter *dec) { void *out = malloc(128); int len = 0; EVP_DecryptFinal_ex(&dec->ctx, out, &len); dec->write(out, 1, len, dec->stream); + SHA256_Update(&dec->sha256, out, len); free(out); EVP_CIPHER_CTX_cleanup(&dec->ctx); +} + +void aes_decrypter_close(AESDecrypter *dec) { free(dec); } @@ -290,6 +294,6 @@ } -void dav_get_hash(SHA256_CTX *sha256, char *buf) { +void dav_get_hash(SHA256_CTX *sha256, unsigned char *buf) { SHA256_Final((unsigned char*)buf, sha256); }
--- a/libidav/crypto.h Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/crypto.h Mon Mar 14 11:54:55 2016 +0100 @@ -72,8 +72,8 @@ AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func); size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec); +void aes_decrypter_shutdown(AESDecrypter *dec); void aes_decrypter_close(AESDecrypter *dec); -void aes_decrypter_close2(EVP_CIPHER_CTX *ctx); AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func); size_t aes_read(void *buf, size_t s, size_t n, AESEncrypter *enc); @@ -82,7 +82,7 @@ char* aes_encrypt(char *in, size_t len, DavKey *key); char* aes_decrypt(char *in, size_t *len, DavKey *key); -void dav_get_hash(SHA256_CTX *sha256, char *buf); +void dav_get_hash(SHA256_CTX *sha256, unsigned char *buf); #ifdef __cplusplus }
--- a/libidav/methods.c Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/methods.c Mon Mar 14 11:54:55 2016 +0100 @@ -962,10 +962,13 @@ CURLcode do_head_request(CURL *handle) { curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "HEAD"); - curl_easy_setopt(handle, CURLOPT_PUT, 0L); curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); curl_easy_setopt(handle, CURLOPT_NOBODY, 1L); + // clear headers + struct curl_slist *headers = NULL; + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, dummy_write); curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL); @@ -1006,3 +1009,115 @@ return ret; } + +UcxBuffer* create_lock_request() { + UcxBuffer *buf = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); + sstr_t s; + + s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = S("<D:lockinfo xmlns:D=\"DAV:\">\n" + "<D:lockscope><D:exclusive/></D:lockscope>\n" + "<D:locktype><D:write/></D:locktype>\n" + "<D:owner><D:href>http://davutils.org/libidav/</D:href></D:owner>\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = S("</D:lockinfo>\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + return buf; +} + +int parse_lock_response(DavSession *sn, UcxBuffer *response, LockDiscovery *lock) { + lock->locktoken = NULL; + lock->timeout = NULL; + + xmlDoc *doc = xmlReadMemory(response->space, response->size, NULL, NULL, 0); + if(!doc) { + sn->error = DAV_ERROR; + return -1; + } + + char *timeout = NULL; + char *locktoken = NULL; + + int ret = -1; + xmlNode *xml_root = xmlDocGetRootElement(doc); + DavBool lockdiscovery = 0; + if(xml_root) { + xmlNode *node = xml_root->children; + while(node) { + if(node->type == XML_ELEMENT_NODE) { + if(xstreq(node->name, "lockdiscovery")) { + node = node->children; + lockdiscovery = 1; + continue; + } + + if(lockdiscovery) { + if(xstreq(node->name, "timeout")) { + timeout = util_xml_get_text(node); + } else if(xstreq(node->name, "locktoken")) { + xmlNode *n = node->children; + while(n) { + if(xstreq(n->name, "href")) { + locktoken = util_xml_get_text(n); + break; + } + n = n->next; + } + } + } + } + node = node->next; + } + } + + if(timeout && locktoken) { + lock->timeout = strdup(timeout); + lock->locktoken = strdup(locktoken); + ret = 0; + } + + xmlFreeDoc(doc); + return ret; +} + +CURLcode do_lock_request(CURL *handle, UcxBuffer *request, UcxBuffer *response) { + curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "LOCK"); + curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L); + request->pos = 0; + + // clear headers + struct curl_slist *headers = NULL; + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + + curl_easy_setopt(handle, CURLOPT_UPLOAD, 1); + curl_easy_setopt(handle, CURLOPT_READFUNCTION, ucx_buffer_read); + curl_easy_setopt(handle, CURLOPT_READDATA, request); + curl_easy_setopt(handle, CURLOPT_INFILESIZE, request->size); + + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ucx_buffer_write); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); + + CURLcode ret = curl_easy_perform(handle); + + return ret; +} + +CURLcode do_unlock_request(CURL *handle, char *locktoken) { + curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "UNLOCK"); + curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); + + // set lock-token header + sstr_t ltheader = ucx_sprintf("Lock-Token: <%s>", locktoken); + struct curl_slist *headers = curl_slist_append(NULL, ltheader.ptr); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + + CURLcode ret = curl_easy_perform(handle); + curl_slist_free_all(headers); + free(ltheader.ptr); + + return ret; +}
--- a/libidav/methods.h Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/methods.h Mon Mar 14 11:54:55 2016 +0100 @@ -40,6 +40,7 @@ typedef struct PropfindParser PropfindParser; typedef struct ResponseTag ResponseTag; +typedef struct LockDiscovery LockDiscovery; struct PropfindParser { xmlDoc *document; @@ -54,6 +55,11 @@ char *crypto_key; }; +struct LockDiscovery { + char *timeout; + char *locktoken; +}; + CURLcode do_propfind_request( CURL *handle, UcxBuffer *request, @@ -98,6 +104,11 @@ CURLcode do_copy_move_request(CURL *handle, char *dest, _Bool copy, _Bool override); +UcxBuffer* create_lock_request(); +int parse_lock_response(DavSession *sn, UcxBuffer *response, LockDiscovery *lock); +CURLcode do_lock_request(CURL *handle, UcxBuffer *request, UcxBuffer *response); +CURLcode do_unlock_request(CURL *handle, char *locktoken); + #ifdef __cplusplus } #endif
--- a/libidav/resource.c Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/resource.c Mon Mar 14 11:54:55 2016 +0100 @@ -584,9 +584,9 @@ 0); // get sha256 hash - char sha[SHA256_DIGEST_LENGTH]; + unsigned char sha[SHA256_DIGEST_LENGTH]; dav_get_hash(&enc->sha256, sha); - char *enc_hash = aes_encrypt(sha, SHA256_DIGEST_LENGTH, sn->key); + char *enc_hash = aes_encrypt((char*)sha, SHA256_DIGEST_LENGTH, sn->key); aes_encrypter_close(enc); if(buf) { @@ -682,10 +682,12 @@ char *hash = NULL; if(dec) { + aes_decrypter_shutdown(dec); // get final bytes + // get hash - char sha[SHA256_DIGEST_LENGTH]; + unsigned char sha[SHA256_DIGEST_LENGTH]; dav_get_hash(&dec->sha256, sha); - hash = util_hexstr((unsigned char*)sha, 32); + hash = util_hexstr(sha, 32); aes_decrypter_close(dec); } @@ -923,6 +925,54 @@ return dav_cp_mv_url(res, url, false, override); } +char* dav_lock(DavResource *res) { + DavSession *sn = res->session; + CURL *handle = sn->handle; + util_set_url(sn, dav_resource_get_href(res)); + + UcxBuffer *request = create_lock_request(); + UcxBuffer *response = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); + CURLcode ret = do_lock_request(handle, request, response); + + //printf("\nlock\n"); + //printf("%.*s\n\n", request->size, request->space); + //printf("%.*s\n\n", response->size, response->space); + + long status = 0; + curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); + if(ret == CURLE_OK && (status >= 200 && status < 300)) { + LockDiscovery lock; + if(parse_lock_response(sn, response, &lock)) { + sn->error = DAV_ERROR; + return NULL; + } + + free(lock.timeout); + return lock.locktoken; + } else { + dav_session_set_error(sn, ret, status); + return NULL; + } +} + +int dav_unlock(DavResource *res, char *locktoken) { + DavSession *sn = res->session; + CURL *handle = sn->handle; + util_set_url(sn, dav_resource_get_href(res)); + + CURLcode ret = do_unlock_request(handle, locktoken); + long status = 0; + curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); + if(ret == CURLE_OK && (status >= 200 && status < 300)) { + return 0; + } else { + dav_session_set_error(sn, ret, status); + return 1; + } + + return 0; +} + int resource_add_crypto_info(DavSession *sn, char *href, char *name, char *hash) { if(!DAV_IS_ENCRYPTED(sn)) {
--- a/libidav/session.c Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/session.c Mon Mar 14 11:54:55 2016 +0100 @@ -148,6 +148,7 @@ case 404: sn->error = DAV_NOT_FOUND; break; case 405: sn->error = DAV_METHOD_NOT_ALLOWED; break; case 409: sn->error = DAV_CONFLICT; break; + case 423: sn->error = DAV_LOCKED; break; } } else { switch(c) {
--- a/libidav/webdav.h Sun Mar 06 15:19:50 2016 +0100 +++ b/libidav/webdav.h Mon Mar 14 11:54:55 2016 +0100 @@ -64,6 +64,7 @@ DAV_FORBIDDEN, DAV_METHOD_NOT_ALLOWED, DAV_CONFLICT, + DAV_LOCKED, DAV_UNSUPPORTED_PROTOCOL, DAV_COULDNT_RESOLVE_PROXY, DAV_COULDNT_RESOLVE_HOST, @@ -231,6 +232,9 @@ int dav_copyto(DavResource *res, char *url, DavBool override); int dav_moveto(DavResource *res, char *url, DavBool override); +char* dav_lock(DavResource *res); +int dav_unlock(DavResource *res, char *locktoken); + char* dav_get_property(DavResource *res, char *name); char* dav_get_property_ns(DavResource *res, char *ns, char *name); void dav_set_property(DavResource *res, char *name, char *value);