mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-08-28 18:16:05 +00:00
Basic support for the ACL method. Working, but needs work.
This commit is contained in:
parent
645d7b71bb
commit
d718e818dc
@ -88,9 +88,132 @@ $resource = new DAVResource( $request->path );
|
||||
would allow unauthenticated access to resources.
|
||||
*/
|
||||
|
||||
$ace = $xmltree->GetPath("/DAV::acl/DAV::ace/*");
|
||||
function precondition_failed($precondition, $explanation = '') {
|
||||
global $request;
|
||||
$xmldoc = sprintf('<?xml version="1.0" encoding="utf-8" ?>
|
||||
<error xmlns="DAV:">
|
||||
<%s/>%s
|
||||
</error>', $precondition, $explanation );
|
||||
|
||||
foreach( $ace AS $k => $v ) {
|
||||
$request->DoResponse( 403, $xmldoc, 'text/xml; charset="utf-8"' );
|
||||
exit(0); // Unecessary, but might clarify things
|
||||
}
|
||||
|
||||
function malformed_request( $text = 'Bad request' ) {
|
||||
global $request;
|
||||
$request->DoResponse( 400, $text );
|
||||
exit(0); // Unecessary, but might clarify things
|
||||
}
|
||||
|
||||
|
||||
$position = 0;
|
||||
$xmltree = BuildXMLTree( $request->xml_tags, $position);
|
||||
$aces = $xmltree->GetPath("/DAV::acl/*");
|
||||
|
||||
$grantor = new DAVResource($request->path);
|
||||
if ( ! $grantor->Exists() ) $request->DoResponse( 404 );
|
||||
$by_principal = null;
|
||||
$by_collection = null;
|
||||
if ( $grantor->IsPrincipal() ) $by_principal = $grantor->GetProperty('principal_id');
|
||||
else if ( $grantor->IsCollection() ) $by_collection = $grantor->GetProperty('collection_id');
|
||||
else precondition_failed('not-supported-privilege','ACLs may only be applied to Principals or Collections');
|
||||
|
||||
$qry = new AwlQuery('BEGIN');
|
||||
$qry->Exec('ACL',__FILE__,__LINE__);
|
||||
|
||||
foreach( $aces AS $k => $ace ) {
|
||||
$elements = $ace->GetContent();
|
||||
$principal = $elements[0];
|
||||
$grant = $elements[1];
|
||||
if ( $principal->GetTag() != 'DAV::principal' ) malformed_request('ACL request must contain a principal, not '.$principal->GetTag());
|
||||
$grant_tag = $grant->GetTag();
|
||||
if ( $grant_tag == 'DAV::deny' ) precondition_failed('grant-only');
|
||||
if ( $grant_tag == 'DAV::invert' ) precondition_failed('no-invert');
|
||||
if ( $grant->GetTag() != 'DAV::grant' ) malformed_request('ACL request must contain a principal for each ACE');
|
||||
|
||||
$privilege_names = array();
|
||||
$xml_privs = $grant->GetPath("/DAV::grant/DAV::privilege/*");
|
||||
foreach( $xml_privs AS $k => $priv ) {
|
||||
$privilege_names[] = $priv->GetTag();
|
||||
}
|
||||
$privileges = privilege_to_bits($privilege_names);
|
||||
|
||||
$principal_content = $principal->GetContent();
|
||||
if ( count($principal_content) != 1 ) malformed_request('ACL request must contain exactly one principal per ACE');
|
||||
$principal_content = $principal_content[0];
|
||||
switch( $principal_content->GetTag() ) {
|
||||
case 'DAV::property':
|
||||
$principal_property = $principal_content->GetContent();
|
||||
if ( $principal_property[0]->GetTag() != 'DAV::owner' ) precondition_failed( 'recognized-principal' );
|
||||
if ( privilege_to_bits('all') != $privileges ) {
|
||||
precondition_failed( 'no-protected-ace-conflict', 'Owner must always have all permissions' );
|
||||
}
|
||||
continue; // and then we ignore it, since it's protected
|
||||
break;
|
||||
|
||||
case 'DAV::unauthenticated':
|
||||
precondition_failed( 'allowed-principal', 'May not set privileges for unauthenticated users' );
|
||||
break;
|
||||
|
||||
case 'DAV::href':
|
||||
$principal_type = 'href';
|
||||
$principal = new DAVResource( DeconstructURL($principal_content->GetContent()) );
|
||||
if ( ! $principal->Exists() || !$principal->IsPrincipal() )
|
||||
precondition_failed('recognized-principal', 'Principal "' + $principal_content->GetContent() + '" not found.');
|
||||
$sqlparms = array( ':to_principal' => $principal->GetProperty('principal_id') );
|
||||
$where = 'WHERE to_principal=:to_principal AND ';
|
||||
if ( isset($by_principal) ) {
|
||||
$sqlparms[':by_principal'] = $by_principal;
|
||||
$where .= 'by_principal = :by_principal';
|
||||
}
|
||||
else {
|
||||
$sqlparms[':by_collection'] = $by_collection;
|
||||
$where .= 'by_collection = :by_collection';
|
||||
}
|
||||
$qry = new AwlQuery('SELECT privileges FROM grants '.$where, $sqlparms);
|
||||
if ( $qry->Exec('ACL',__FILE__,__LINE__) && $qry->rows() == 1 && $current = $qry->Fetch() ) {
|
||||
$sql = 'UPDATE grants SET privileges=:privileges::INT::BIT(24) '.$where;
|
||||
}
|
||||
else {
|
||||
$sqlparms[':by_principal'] = $by_principal;
|
||||
$sqlparms[':by_collection'] = $by_collection;
|
||||
$sql = 'INSERT INTO grants (by_principal, by_collection, to_principal, privileges) VALUES(:by_principal, :by_collection, :to_principal, :privileges::INT::BIT(24))';
|
||||
}
|
||||
$sqlparms[':privileges'] = $privileges;
|
||||
$qry = new AwlQuery($sql, $sqlparms);
|
||||
$qry->Exec('ACL',__FILE__,__LINE__);
|
||||
break;
|
||||
|
||||
case 'DAV::authenticated':
|
||||
$principal_type = 'authenticated';
|
||||
if ( bindec($grantor->GetProperty('default_privileges')) == $privileges ) continue; // There is no change, so skip it
|
||||
$sqlparms = array( ':privileges' => $privileges );
|
||||
if ( isset($by_collection) ) {
|
||||
$sql = 'UPDATE collection SET default_privileges=:privileges::INT::BIT(24) WHERE collection_id=:by_collection';
|
||||
$sqlparms[':by_collection'] = $by_collection;
|
||||
}
|
||||
else {
|
||||
$sql = 'UPDATE principal SET default_privileges=:privileges::INT::BIT(24) WHERE principal_id=:by_principal';
|
||||
$sqlparms[':by_principal'] = $by_principal;
|
||||
}
|
||||
$qry = new AwlQuery($sql, $sqlparms);
|
||||
$qry->Exec('ACL',__FILE__,__LINE__);
|
||||
break;
|
||||
|
||||
case 'DAV::all':
|
||||
// $principal_type = 'all';
|
||||
precondition_failed( 'allowed-principal', 'May not set privileges for unauthenticated users' );
|
||||
break;
|
||||
|
||||
default:
|
||||
precondition_failed( 'recognized-principal' );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$qry = new AwlQuery('COMMIT');
|
||||
$qry->Exec('ACL',__FILE__,__LINE__);
|
||||
|
||||
|
||||
$request->DoResponse( 200 );
|
||||
|
||||
25
testing/tests/regression-suite/945-ACL.result
Normal file
25
testing/tests/regression-suite/945-ACL.result
Normal file
@ -0,0 +1,25 @@
|
||||
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
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
|
||||
by_collection: >NULL<
|
||||
by_principal: >3<
|
||||
displayname: >User 4<
|
||||
privileges: >000000001111111011111111<
|
||||
to_principal: >6<
|
||||
|
||||
by_collection: >NULL<
|
||||
by_principal: >3<
|
||||
displayname: >Assistant 1<
|
||||
privileges: >000000000001001011000111<
|
||||
to_principal: >10<
|
||||
|
||||
by_collection: >NULL<
|
||||
by_principal: >3<
|
||||
displayname: >Team for Client1<
|
||||
privileges: >000000000001001000000001<
|
||||
to_principal: >14<
|
||||
|
||||
56
testing/tests/regression-suite/945-ACL.test
Normal file
56
testing/tests/regression-suite/945-ACL.test
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# ACL setting default privileges on a collection to nothing, and
|
||||
# specific privileges to include read-acl.
|
||||
#
|
||||
TYPE=ACL
|
||||
URL=http://regression.host/caldav.php/user1/
|
||||
HEADER=User-Agent: RFC3744 Spec Tests
|
||||
HEADER=Content-Type: text/xml; charset="UTF-8"
|
||||
HEAD
|
||||
|
||||
|
||||
BEGINDATA
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<acl xmlns="DAV:" xmlns:CalDAV="urn:ietf:params:xml:ns:caldav">
|
||||
<ace>
|
||||
<principal>
|
||||
<property><owner/></property>
|
||||
</principal>
|
||||
<grant>
|
||||
<privilege><all/></privilege>
|
||||
</grant>
|
||||
</ace>
|
||||
<ace>
|
||||
<principal>
|
||||
<href>/caldav.php/user4/</href>
|
||||
</principal>
|
||||
<grant>
|
||||
<privilege><read/></privilege>
|
||||
<privilege><read-acl/></privilege>
|
||||
<privilege><read-current-user-privilege-set/></privilege>
|
||||
<privilege><CalDAV:read-free-busy/></privilege>
|
||||
<privilege><CalDAV:schedule-deliver/></privilege>
|
||||
<privilege><CalDAV:schedule-send/></privilege>
|
||||
<privilege><write/></privilege>
|
||||
<privilege><bind/></privilege>
|
||||
<privilege><unbind/></privilege>
|
||||
<privilege><unlock/></privilege>
|
||||
</grant>
|
||||
</ace>
|
||||
<ace>
|
||||
<principal><authenticated/></principal>
|
||||
<grant>
|
||||
<privilege/>
|
||||
</grant>
|
||||
</ace>
|
||||
</acl>
|
||||
ENDDATA
|
||||
|
||||
QUERY
|
||||
SELECT by_principal, by_collection, privileges, p_to.displayname, to_principal
|
||||
FROM grants JOIN dav_principal p_to ON (to_principal=principal_id)
|
||||
LEFT JOIN collection ON (by_collection=collection.collection_id)
|
||||
LEFT JOIN dav_principal p_by ON (by_principal=p_by.principal_id)
|
||||
WHERE p_by.username = 'user1'
|
||||
ENDQUERY
|
||||
|
||||
13
testing/tests/regression-suite/946-ACL.result
Normal file
13
testing/tests/regression-suite/946-ACL.result
Normal file
@ -0,0 +1,13 @@
|
||||
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
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
|
||||
by_collection: >10<
|
||||
by_principal: >NULL<
|
||||
displayname: >User 4<
|
||||
privileges: >000000000000001000110001<
|
||||
to_principal: >6<
|
||||
|
||||
41
testing/tests/regression-suite/946-ACL.test
Normal file
41
testing/tests/regression-suite/946-ACL.test
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# ACL setting default privileges on a collection to nothing, and
|
||||
# specific privileges to include read-acl.
|
||||
#
|
||||
TYPE=ACL
|
||||
URL=http://regression.host/caldav.php/user1/home/
|
||||
HEADER=User-Agent: RFC3744 Spec Tests
|
||||
HEADER=Content-Type: text/xml; charset="UTF-8"
|
||||
HEAD
|
||||
|
||||
|
||||
BEGINDATA
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<acl xmlns="DAV:" xmlns:CalDAV="urn:ietf:params:xml:ns:caldav">
|
||||
<ace>
|
||||
<principal>
|
||||
<href>/caldav.php/user4/</href>
|
||||
</principal>
|
||||
<grant>
|
||||
<privilege><read/></privilege>
|
||||
<privilege><read-acl/></privilege>
|
||||
<privilege><read-current-user-privilege-set/></privilege>
|
||||
<privilege><CalDAV:read-free-busy/></privilege>
|
||||
</grant>
|
||||
</ace>
|
||||
<ace>
|
||||
<principal><authenticated/></principal>
|
||||
<grant>
|
||||
<privilege/>
|
||||
</grant>
|
||||
</ace>
|
||||
</acl>
|
||||
ENDDATA
|
||||
|
||||
QUERY
|
||||
SELECT by_principal, by_collection, privileges, p_to.displayname, to_principal
|
||||
FROM grants JOIN dav_principal p_to ON (to_principal=principal_id)
|
||||
LEFT JOIN collection ON (by_collection=collection.collection_id)
|
||||
WHERE collection.dav_name = '/user1/home/'
|
||||
ENDQUERY
|
||||
|
||||
25
testing/tests/regression-suite/947-ACL.result
Normal file
25
testing/tests/regression-suite/947-ACL.result
Normal file
@ -0,0 +1,25 @@
|
||||
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
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
|
||||
by_collection: >NULL<
|
||||
by_principal: >3<
|
||||
displayname: >User 4<
|
||||
privileges: >000000000001001000100001<
|
||||
to_principal: >6<
|
||||
|
||||
by_collection: >NULL<
|
||||
by_principal: >3<
|
||||
displayname: >Assistant 1<
|
||||
privileges: >000000000001001011000111<
|
||||
to_principal: >10<
|
||||
|
||||
by_collection: >NULL<
|
||||
by_principal: >3<
|
||||
displayname: >Team for Client1<
|
||||
privileges: >000000000001001000000001<
|
||||
to_principal: >14<
|
||||
|
||||
42
testing/tests/regression-suite/947-ACL.test
Normal file
42
testing/tests/regression-suite/947-ACL.test
Normal file
@ -0,0 +1,42 @@
|
||||
#
|
||||
# ACL setting default privileges on a collection to nothing, and
|
||||
# specific privileges to include read-acl.
|
||||
#
|
||||
TYPE=ACL
|
||||
URL=http://regression.host/caldav.php/user1/
|
||||
HEADER=User-Agent: RFC3744 Spec Tests
|
||||
HEADER=Content-Type: text/xml; charset="UTF-8"
|
||||
HEAD
|
||||
|
||||
|
||||
BEGINDATA
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<acl xmlns="DAV:" xmlns:CalDAV="urn:ietf:params:xml:ns:caldav">
|
||||
<ace>
|
||||
<principal>
|
||||
<href>/caldav.php/user4/</href>
|
||||
</principal>
|
||||
<grant>
|
||||
<privilege><read/></privilege>
|
||||
<privilege><read-current-user-privilege-set/></privilege>
|
||||
<privilege><CalDAV:read-free-busy/></privilege>
|
||||
<privilege><CalDAV:schedule-query-freebusy/></privilege>
|
||||
</grant>
|
||||
</ace>
|
||||
<ace>
|
||||
<principal><authenticated/></principal>
|
||||
<grant>
|
||||
<privilege/>
|
||||
</grant>
|
||||
</ace>
|
||||
</acl>
|
||||
ENDDATA
|
||||
|
||||
QUERY
|
||||
SELECT by_principal, by_collection, privileges, p_to.displayname, to_principal
|
||||
FROM grants JOIN dav_principal p_to ON (to_principal=principal_id)
|
||||
LEFT JOIN collection ON (by_collection=collection.collection_id)
|
||||
LEFT JOIN dav_principal p_by ON (by_principal=p_by.principal_id)
|
||||
WHERE p_by.dav_name = '/user1/'
|
||||
ENDQUERY
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user