Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unauthenticated REPORT requests with no body produce an HTTP 500 response #932

Open
jorgelzpz opened this issue Jan 16, 2017 · 6 comments
Open

Comments

@jorgelzpz
Copy link

Many HTTP clients, such as cURL, always sends the first request with Content-Length: 0 when digest authentication is used, even when a body is specified, likely to save some bandwidth until digest parameters are negotiated.

I don't know if the standard requires the whole body sent on the first request (haven't been able to find anything on this topic), but sabre/dav 3.2.0 answers with a 500 error on REPORT requests with no body. A 401 is expected, so most clients just stop after receiving a 5xx response.

Older releases (<3.2.0) did not show this behavior.

Other HTTP verbs don't have this issue, take a look at this PROPFIND request:

% curl --digest --user admin -X PROPFIND \
 -H "Content-Type: application/xml" --data @propfind.xml \
 http://localhost:8082/calendarserver.php/ -v
Enter host password for user 'admin':
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8082 (#0)
* Server auth using Digest with user 'admin'
> PROPFIND /calendarserver.php/ HTTP/1.1
> Host: localhost:8082
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/xml
> Content-Length: 0
>
< HTTP/1.1 401 Unauthorized
< Date: Wed, 07 Dec 2016 18:21:34 GMT
< Server: Apache/2.4.7 (Ubuntu)
< X-Powered-By: PHP/5.6.24-1+deb.sury.org~trusty+1
< X-Sabre-Version: 3.2.0
< WWW-Authenticate: Digest realm="SabreDAV",qop="auth",nonce="5848532ee79e4",opaque="df58bdff8cf60599c939187d0b5c54de"
< Content-Length: 403
< Content-Type: application/xml; charset=utf-8
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8082/calendarserver.php/'
* Found bundle for host localhost: 0x7f8251c0f210
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 8082 (#0)
* Server auth using Digest with user 'admin'
> PROPFIND /calendarserver.php/ HTTP/1.1
> Host: localhost:8082
> Authorization: Digest username="admin", realm="SabreDAV", nonce="5848532ee79e4", uri="/calendarserver.php/", cnonce="MDk3ODI0YjUwNTZkMGNiZDMwYTY4YzU3NDJiNDk3NGM=", nc=00000001, qop=auth, response="f40755e5078d0fd578a3d813ab205261", opaque="df58bdff8cf60599c939187d0b5c54de"
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/xml
> Content-Length: 347
>
* upload completely sent off: 347 out of 347 bytes
< HTTP/1.1 207 Multi-Status
< Date: Wed, 07 Dec 2016 18:21:34 GMT
< Server: Apache/2.4.7 (Ubuntu)
< X-Powered-By: PHP/5.6.24-1+deb.sury.org~trusty+1
< X-Sabre-Version: 3.2.0
< Vary: Brief,Prefer
< DAV: 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendarserver-subscribed, calendar-auto-schedule, calendar-availability, resource-sharing, calendarserver-sharing
< Content-Length: 1824
< Content-Type: application/xml; charset=utf-8
<
<?xml version="1.0"?>
[...]

However, a REPORT request gets a 500 response (note the Content-Length: 0):

% curl --digest --user admin -v -X REPORT \
  -H "Content-Type: application/xml" --data @report.xml \
  http://localhost:8082/calendarserver.php/calendars/admin/micalendario/ -v
Enter host password for user 'admin':
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8082 (#0)
* Server auth using Digest with user 'admin'
> REPORT /calendarserver.php/calendars/admin/micalendario/ HTTP/1.1
> Host: localhost:8082
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/xml
> Content-Length: 0
>
< HTTP/1.1 500 Internal Server Error
< Date: Wed, 07 Dec 2016 18:25:29 GMT
< Server: Apache/2.4.7 (Ubuntu)
< X-Powered-By: PHP/5.6.24-1+deb.sury.org~trusty+1
< X-Sabre-Version: 3.2.0
< Content-Length: 275
< Connection: close
< Content-Type: application/xml; charset=utf-8
<
<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:sabredav-version>3.2.0</s:sabredav-version>
  <s:exception>ErrorException</s:exception>
  <s:message>XMLReader::XML(): Empty string supplied as input</s:message>
</d:error>
* Closing connection 0
@staabm
Copy link
Member

staabm commented Jan 16, 2017

We recently changed handling regarding content-length in sabre-io/http@9cf0c48

Could you check this broke your app?

@evert
Copy link
Member

evert commented Jan 17, 2017

The reason this is happening is actually because of a change that happened a bit earlier. This change is documented here: http://sabre.io/dav/upgrade/3.1-to-3.2/

What the change here really entails is that we now try to do authentication as late as possible in the process. If you do a REPORT and you hit all calendar objects that have been made public, you will effectively never get asked for auth at all.

Only after we retrieve the iCalendar objects and find out that one of the objects is not publicly accessible and you didn't provide credentials, we force a login.

This basically allows us to build a number of features that weren't possible otherwise, such as public calendars and freebusy.

Since you're sending an invalid request, we reject it as early as possible, long before auth kicks in.

I understand curl's behavior, but I wonder if there's a way to work around it? Are you only doing this type of request for the first request to a server, or is it done for every single HTTP session?

Ideally your client should behave a bit like a browser, that is:

  • Do requests like you normally do, without auth
  • Until you hit a 401 with an authentication challenge
  • At that point send the appropriate headers

But if there is a different way you know of I can on my side see that I'm receiving a Curl 'auth preflight request', I would also be more than happy to implement a workaround for that. It would be helpful in that case to see a full HTTP request. I hope there's maybe a special header in there or something...

It might also be worth asking the curl authors what they think?

@jorgelzpz
Copy link
Author

@evert found this message from cURL author (Daniel Stenberg). He wrote it some years ago, so looks like cURL has been acting this way for a long time.

Found this problem while using Guzzle with the cURL handler. The workaround would be to use cURL's any authentication method instead of digest, but Guzzle doesn't seem to support it right now out of the box, so every REPORT request gets a 500 response.

I clearly see the benefits of sabre/dav processing authentication as late as possible, but unfortunately this breaks some cURL-based HTTP clients, at least if they know they have to use Digest authentication beforehand.

@evert
Copy link
Member

evert commented Jan 29, 2017

I don't really have a good answer than to just work around it at the moment though... the feature can be disabled in sabre/dav too, but I don't intend to remove it.

I think maybe the logical next step might be to open up a new bug report in curl and see what the author says about it.

@nunohorta
Copy link

What would be the solution if I need to use sabre 3.2 and REPORT requests?

@evert
Copy link
Member

evert commented Jan 9, 2018

This is a client bug, so ideally you fix the client.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants