1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798(*
* Copyright (C) Citrix Systems Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)letinfofmt=Logging.info"perms"fmtexceptionPermission_denied(* permission of connections *)openXs_protocol.ACLtypeelt=domid*permlisttypet={main:elt;target:eltoption}letsuperuser:t={main=(0,[READ;WRITE]);target=None}letof_domaindomid:t={main=(domid,[READ;WRITE]);target=None}letset_target(connection:t)domid={connectionwithtarget=Some(domid,[READ;WRITE])}letget_owners(connection:t)=match(connection.main,connection.target)with|c1,Somec2->[fstc1;fstc2]|c1,None->[fstc1]letis_owner(connection:t)id=matchconnection.targetwith|Sometarget->fstconnection.main=id||fsttarget=id|None->fstconnection.main=idletis_dom0(connection:t)=is_ownerconnection0letrestrict(connection:t)domid=match(connection.target,connection.main)with|None,(0,perms)->info"restricting connection from domid %d to domid %d"0domid;{connectionwithmain=(domid,perms)}|_->raisePermission_deniedtypepermission=|READ|WRITE|CHANGE_ACL|DEBUG|INTRODUCE|ISINTRODUCED|RESUME|RELEASE|SET_TARGET|RESTRICT|CONFIGURElethas(t:t)_p=ifnot(is_dom0t)thenraisePermission_denied(* check if owner of the current connection and of the current node are the same *)letcheck_owner(connection:t)(node:Xs_protocol.ACL.t)=ifnot(is_dom0connection)thenis_ownerconnectionnode.Xs_protocol.ACL.ownerelsetrue(* check if the current connection has the requested perm on the current node *)letcheck(connection:t)request(node:Xs_protocol.ACL.t)=letcheck_acldomainid=letperm=ifList.mem_assocdomainidnode.Xs_protocol.ACL.aclthenList.assocdomainidnode.Xs_protocol.ACL.aclelsenode.Xs_protocol.ACL.otherinmatch(perm,request)with|Xs_protocol.ACL.NONE,_->info"Permission denied: Domain %d has no permission"domainid;false|Xs_protocol.ACL.RDWR,_->true|Xs_protocol.ACL.READ,READ->true|Xs_protocol.ACL.WRITE,WRITE->true|Xs_protocol.ACL.READ,_->info"Permission denied: Domain %d has read only access"domainid;false|Xs_protocol.ACL.WRITE,_->info"Permission denied: Domain %d has write only access"domainid;falseiniftrue&&(not(is_dom0connection))&&(not(check_ownerconnectionnode))&¬(List.existscheck_acl(get_ownersconnection))thenraisePermission_denied