PATCH request for TUS upload with wrong checksum gives incorrect response
Describe the bug
According to the TUS checksum extension description in https://tus.io/protocols/resumable-upload.html#checksum when a PATCH request is send with an Upload-Checksum header depending on the result the server may respond with one of the following status code:
1.400 Bad Request if the checksum algorithm is not supported by the server
2. 460 Checksum Mismatch if the checksums mismatch
3. 204 No Content if the checksums match and the processing of the data succeeded
But when we send PATCH request with wrong checksum then instead of 460 Checksum Mismatch we get 204 No Content
Steps to reproduce
Steps to reproduce the behavior:
- Create a base64 encoding of a file name
echo -n "textFile.txt" | base64(example dGV4dEZpbGUudHh0)
- As user Einstein send a
POSTrequest to create resource which will give a resource location url.
curl -k -X POST -u einstein:relativity https://localhost:9200/remote.php/dav/files/Einstein/ -H 'Tus-Resumable: 1.0.0' -H 'Upload-Length: 5' -H 'Upload-Metadata: filename dGV4dEZpbGUudHh0' -v
- User Einstein send
PATCHrequest to upload data to the location url along with a wrong checkum For example: correct sha1sum for '12345' is8cb2237d0679ca88db6464eac60da96345513964but we are sending wrong value i.e.01b307acba4f54f55aafc33bb06bbbf6ca803e9a:
curl -k -X PATCH <your TUS resource Location> -u einstein:relativity -H 'Content-Type: application/offset+octet-stream' -H 'Tus-Resumable: 1.0.0' -H 'Upload-Offset: 0' -H'Upload-Checksum:sha1 01b307acba4f54f55aafc33bb06bbbf6ca803e9a' -d '12345' -v
Expected behavior
HTTP/1.1 460 Checksum Mismatch
Tus-Resumable: 1.0.0
Upload-Offset: 5
Actual behavior
HTTP/1.1 204 No content
Tus-Resumable: 1.0.0
Upload-Offset: 5
While doing PROPFIND it can be seen that the file textFile.txt has been created and it gives the correct checksum and ignores the incorrect checksum send during PATCH request.
curl -X PROPFIND -u einstein:relativity https://localhost:9200/remote.php/webdav -k | xmllint --format -
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1676 100 1676 0 0 27032 0 --:--:-- --:--:-- --:--:-- 27032
<?xml version="1.0" encoding="utf-8"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">
<d:response>
<d:href>/remote.php/webdav/</d:href>
<d:propstat>
<d:prop>
<oc:id>MTI4NGQyMzgtYWE5Mi00MmNlLWJkYzQtMGIwMDAwMDA5MTU3OjA2OTRjZjY4LWYxOGUtNDY1ZC1hMzlkLTEzNWFkM2RkMjg3ZA==</oc:id>
<oc:fileid>MTI4NGQyMzgtYWE5Mi00MmNlLWJkYzQtMGIwMDAwMDA5MTU3OjA2OTRjZjY4LWYxOGUtNDY1ZC1hMzlkLTEzNWFkM2RkMjg3ZA==</oc:fileid>
<d:getetag>"7bdfa13e5b7a5a4cdd27fb7550617b10"</d:getetag>
<oc:permissions>DNVCKR</oc:permissions>
<d:resourcetype>
<d:collection/>
</d:resourcetype>
<oc:size>5</oc:size>
<d:getlastmodified>Thu, 04 Mar 2021 06:38:01 GMT</d:getlastmodified>
<oc:favorite>0</oc:favorite>
</d:prop>
<d:status>HTTP/1.1 200 OK</d:status>
</d:propstat>
</d:response>
<d:response>
<d:href>/remote.php/webdav/textFile.txt</d:href>
<d:propstat>
<d:prop>
<oc:id>MTI4NGQyMzgtYWE5Mi00MmNlLWJkYzQtMGIwMDAwMDA5MTU3Ojg2NzI2NzA5LTNlOTQtNDcxZS04YTAyLTAzOTdlMzdjYzdhYw==</oc:id>
<oc:fileid>MTI4NGQyMzgtYWE5Mi00MmNlLWJkYzQtMGIwMDAwMDA5MTU3Ojg2NzI2NzA5LTNlOTQtNDcxZS04YTAyLTAzOTdlMzdjYzdhYw==</oc:fileid>
<d:getetag>"a5cf632982d978b971264c7edddb2738"</d:getetag>
<oc:permissions>DNVWR</oc:permissions>
<d:resourcetype/>
<d:getcontentlength>5</d:getcontentlength>
<d:getcontenttype>text/plain; charset=utf-8</d:getcontenttype>
<d:getlastmodified>Thu, 04 Mar 2021 06:38:01 GMT</d:getlastmodified>
<oc:checksums>
<oc:checksum>SHA1:8cb2237d0679ca88db6464eac60da96345513964 MD5:827ccb0eea8a706c4c34a16891f84e7b ADLER32:02f80100</oc:checksum>
</oc:checksums>
<oc:favorite>0</oc:favorite>
</d:prop>
<d:status>HTTP/1.1 200 OK</d:status>
</d:propstat>
</d:response>
</d:multistatus>
tested on ocis 6.0.0 still relevant
@micbar @butonic @aduffeck There are few points for discussion:
- Why do we stick to the v1 of tus/tusd packge if v2 was already realised a long time back?
- It looks like the
checksum extensionsto tusd have been available since V2, How to enable checksum? https://github.com/cs3org/reva/blob/f4b705be700c9c374d5ab84cc9d5dfa58aa2be46/pkg/storage/utils/decomposedfs/upload/upload.go#L68
Yes, we need to switch to v2 version if we want this fixed. See accurate description of the problem here: https://github.com/cs3org/reva/blob/edge/pkg/storage/utils/decomposedfs/upload/upload.go#L68-L71 (tusd v1 simply doesn't support it...)
How do we continue here? Do we update to version 2? What is the downside?
v2 has landed on master. I'll try making progress here next week :+1:
Tried to add support for chunk based checksum checking here https://github.com/cs3org/reva/pull/4807 but we hit several walls.
A) Mixed checksum format during test. The format in which the checksum headers are sent differs within test. Tests not specifying a checksum use the tus-php package which base64 encodes the checksum. Test that specify a checksum do not base64 encode. The tus spec states that the header should be base64 encoded.
B) Breaking bug in tus-php package The tus-php contains a breaking bug. It always sends the checksum for the complete file instead of the checksum for one chunk. https://github.com/ankitpokhrel/tus-php/issues/422 This means the tests are sending wrong requests when making multiple requests.
We could get pass A by adjusting all tests. But B is breaking as we cannot control it. We have two options: fix it upstream (if possible) or switch to different tus package for php tests.
There does not seem to be another up to date php tus client library: https://tus.io/implementations