Fr:RFC Compliance/WebDAV Tickets

Ticket-Based Access Control in DAViCal
From 0.9.9 DAViCal will include an implementation of some elements of.

DAViCal will generally be following the line taken by Cosmo's implementation of this spec, which is lightly documented here

Deviations from Spec
In order to promote interoperability, DAViCal aligns with Cosmo as much as possible. The spec differences are as follows:


 * Visit limits are not supported. Regardless of what is requested, DAViCal always returns a value of infinity. Cosmo (& Xythos, apparently) behave the same way. In DAViCal the parameter is optional, which may not be the case in Cosmo & Xythos.


 * The custom XML namespace http://www.xythos.com/namespaces/StorageServer is used for XML elements defined by the spec (ticketdiscovery, ticketinfo, id and timeout). While DAViCal will accept requests with ticketdiscovery, ticketinfo, id and timeout in either the 'DAV:' or 'http://www.xythos.com/namespaces/StorageServer' namespaces, the 'http://www.xythos.com/namespaces/StorageServer' namespace will be used on all responses.


 * If different ticket ids are included in the request headers and URL, the id in the URL is used (the one from the Ticket header is ignored, even if the ticket identified by the URL is not found by the server).


 * If a DELTICKET request is received for a resource on which the requesting user does not have appropriate access privileges, DAViCal returns a 403 (Forbidden) response. Example: User A owns resource X and creates ticket 123 on it. User B does not have privileges on resource X but attempts to delete the ticket.


 * In order to issue a MKTICKET or DELTICKET, DAViCal requires the requesting user to have DAV::bind / DAV::unbind privilege on the target collection, or on the containing collection (for resources). In the case of a DELTICKET, they can also delete the ticket if they own it, regardless of their privileges to the underlying resource. Cosmo only allows the owner or root to perform these actions.


 * The draft does not specify what might control access to the tickets. DAViCal will return all tickets for a PROPFIND of the ticketdiscovery property if the accessing user has the DAV::read-acl privilege to the resource.  Otherwise only tickets actually owned by the accessing user, or which are specified in the request header, will be listed.

Client Support
In theory no client-side support is needed, if DAViCal had elements in the administrative UI that would provide an interface to the tickets. At this point that interface is not done, but we expect to add it in due course.

For now the only client that is believed to possibly provide an interface to issuing tickets is Chandler, although possibly Chandler does not attempt this through the MKTICKET interface, which would be truly sad.

The work for adding Ticket support to DAViCal was undertaken under contract from dotCal who use tickets as a component of their mechanisms for providing access to otherwise private calendars, and who are in the process of migrating their backend server from Cosmo to a DAViCal with expected completion by the end of March 2010.

Successful MKTICKET on collection
Request: MKTICKET /caldav.php/user1/home/ HTTP/1.1 Host: regression.host Content-length: xxx Content-Type: text/xml; charset="utf-8" Authorization: Basic dGVzdHVzZXI6dGVzdHVzZXI=    Second-3600 1 

Response: HTTP/1.1 200 OK Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy Ticket: Oiai12eS ETag: "5e7528c8e464f8cd4b7b7671e194659d" Content-Length: 537 Content-Type: text/xml; charset="utf-8"     Oiai12eS /caldav.php/user1/ <read-current-user-privilege-set/> <C:read-free-busy/> <C:schedule-query-freebusy/> <T:timeout>Second-3600</T:timeout> <T:visits>infinity</T:visits> </T:ticketinfo> </T:ticketdiscovery>

Successful MKTICKET on resource
Request: MKTICKET /caldav.php/user1/home/4aaf8f37-f232-4c8e-a72e-e171d4c4fe54.ics HTTP/1.1 Host: regression.host Content-length: xxx Content-Type: text/xml; charset="utf-8" Authorization: Basic dGVzdHVzZXI6dGVzdHVzZXI= <?xml version="1.0" encoding="utf-8" ?>  <D:write/></D:privilege> Second-86400</D:timeout> </D:ticketinfo>

Response: HTTP/1.1 200 OK Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy Ticket: c4X8Qnox ETag: "3795b8fb42a81c589077f6a63e86a1ce" Content-Length: 622 Content-Type: text/xml; charset="utf-8" <?xml version="1.0" encoding="utf-8" ?> <prop xmlns="DAV:" xmlns:T="http://www.xythos.com/namespaces/StorageServer" xmlns:C="urn:ietf:params:xml:ns:caldav"> <T:ticketdiscovery> <T:ticketinfo> c4X8Qnox</T:id> /caldav.php/user1/ <read-current-user-privilege-set/> <C:read-free-busy/> <write-properties/> <write-content/> <C:schedule-query-freebusy/> <T:timeout>Second-86400</T:timeout> <T:visits>infinity</T:visits> </T:ticketinfo> </T:ticketdiscovery>

Failed MKTICKET - insufficient privileges
Response: HTTP/1.1 403 Forbidden Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy Content-Length: xxx Content-Type: text/xml; charset="utf-8" <?xml version="1.0" encoding="utf-8" ?> <error xmlns="DAV:"> <need-privileges> /caldav.php/user4/home/ </need-privileges>

Successful PROPFIND for ticketdiscovery
Request: PROPFIND /caldav.php/user1/home/ HTTP/1.1 Host: regression.host Content-length: xxx Content-Type: text/xml; charset="utf-8" Authorization: Basic dGVzdHVzZXI6dGVzdHVzZXI= <?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:" xmlns:T="http://www.xythos.com/namespaces/StorageServer"> <current-user-privilege-set/> <T:ticketdiscovery/> Response: <?xml version="1.0" encoding="utf-8" ?> <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:TKT="http://www.xythos.com/namespaces/StorageServer"> /caldav.php/user1/home/ <current-user-privilege-set> <read-acl/> <read-current-user-privilege-set/> <write-acl/> <C:read-free-busy/> <write-properties/> <write-content/> <C:schedule-deliver/> <C:schedule-deliver-invite/> <C:schedule-deliver-reply/> <C:schedule-query-freebusy/> <C:schedule-send/> <C:schedule-send-invite/> <C:schedule-send-reply/> <C:schedule-send-freebusy/> </current-user-privilege-set> <TKT:ticketdiscovery> <TKT:ticketinfo> <TKT:id>Oiai12eS</TKT:id> <TKT:owner> /caldav.php/user1/ </TKT:owner> <TKT:timeout>Seconds-3573</TKT:timeout> <TKT:visits>infinity</TKT:visits> <read-current-user-privilege-set/> <C:read-free-busy/> <C:schedule-query-freebusy/> </TKT:ticketinfo> </TKT:ticketdiscovery> HTTP/1.1 200 OK

Successful DELTICKET
Request: DELTICKET /caldav.php/user1/home/4aaf8f37-f232-4c8e-a72e-e171d4c4fe54.ics HTTP/1.1 Host: regression.host Authorization: Basic dGVzdHVzZXI6dGVzdHVzZXI= Response: HTTP/1.1 204 No Content Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy Content-Length: 0 Content-Type: text/plain; charset="utf-8"

Manually Adding Tickets
If you don't have a client that supports tickets, but don't mind manually manipulating the database, you can create your own tickets via the psql command line interface until DAViCal has support for doing this in the Web GUI.

# Read / FreeBusy insert into access_ticket ( ticket_id, dav_owner_id, privileges, target_collection_id ) values (   'abcdefg',    5,    '000000000001001000100001',    25  );

where


 * "abcdefg" is your hard-to-guess random string of characters
 * 5 is the principal_id of the user who owns the collection
 * 25 is the collection_id of the collection you're granting access to
 * the privileges string is a bit(24) string that represents the permissions you want to grant.

(See some example values in the privileges column of your own "grants" table, or see the function function privilege_to_bits in inc/always.php.in)

Someone can then access your collection with the ticket, using the URL structure described in Public collections.