def defaultAccessControlList(self):
        aces = (
            # DAV:read access for authenticated users.
            davxml.ACE(
                davxml.Principal(davxml.Authenticated()),
                davxml.Grant(davxml.Privilege(davxml.Read())),
            ),
            # Inheritable DAV:all access for the resource's associated principal.
            davxml.ACE(
                davxml.Principal(davxml.HRef(self.parent.principalURL())),
                davxml.Grant(davxml.Privilege(davxml.WriteProperties())),
                davxml.Protected(),
            ),
        )

        # Add admins
        aces += tuple((
            davxml.ACE(
                davxml.Principal(davxml.HRef(principal)),
                davxml.Grant(davxml.Privilege(davxml.All())),
                davxml.Protected(),
            )
            for principal in config.AdminPrincipals
        ))

        return succeed(davxml.ACL(*aces))
Пример #2
0
    def test_Privilege_isAggregateOf(self):
        """
        Privilege.isAggregateOf()
        """
        for a, b in (
            (davxml.All(), davxml.Write()),
            (davxml.All(), davxml.ReadACL()),
            (davxml.Write(), davxml.WriteProperties()),
            (davxml.Write(), davxml.WriteContent()),
            (davxml.Write(), davxml.Bind()),
            (davxml.Write(), davxml.Unbind()),
        ):
            pa = davxml.Privilege(a)
            pb = davxml.Privilege(b)

            self.failUnless(pa.isAggregateOf(pb, davPrivilegeSet),
                            "%s contains %s" % (a.sname(), b.sname()))
            self.failIf(pb.isAggregateOf(pa, davPrivilegeSet),
                        "%s does not contain %s" % (b.sname(), a.sname()))

        for a, b in (
            (davxml.Unlock(), davxml.Write()),
            (davxml.Unlock(), davxml.WriteACL()),
            (davxml.ReadCurrentUserPrivilegeSet(), davxml.WriteProperties()),
        ):
            pa = davxml.Privilege(a)
            pb = davxml.Privilege(b)

            self.failIf(pb.isAggregateOf(pa, davPrivilegeSet),
                        "%s does not contain %s" % (b.sname(), a.sname()))
Пример #3
0
def _schedulePrivilegeSet(deliver):
    edited = False

    top_supported_privileges = []

    for supported_privilege in davPrivilegeSet.childrenOfType(davxml.SupportedPrivilege):
        all_privilege = supported_privilege.childOfType(davxml.Privilege)
        if isinstance(all_privilege.children[0], davxml.All):
            all_description = supported_privilege.childOfType(davxml.Description)
            all_supported_privileges = list(supported_privilege.childrenOfType(davxml.SupportedPrivilege))
            all_supported_privileges.append(
                davxml.SupportedPrivilege(
                    davxml.Privilege(caldavxml.ScheduleDeliver() if deliver else caldavxml.ScheduleSend()),
                    davxml.Description("schedule privileges for current principal", **{"xml:lang": "en"}),
                ),
            )
            if config.Scheduling.CalDAV.OldDraftCompatibility:
                all_supported_privileges.append(
                    davxml.SupportedPrivilege(
                        davxml.Privilege(caldavxml.Schedule()),
                        davxml.Description("old-style schedule privileges for current principal", **{"xml:lang": "en"}),
                    ),
                )
            top_supported_privileges.append(
                davxml.SupportedPrivilege(all_privilege, all_description, *all_supported_privileges)
            )
            edited = True
        else:
            top_supported_privileges.append(supported_privilege)

    assert edited, "Structure of davPrivilegeSet changed in a way that I don't know how to extend for schedulePrivilegeSet"

    return davxml.SupportedPrivilegeSet(*top_supported_privileges)
Пример #4
0
    def defaultAccessControlList(self):
        privs = (
            davxml.Privilege(davxml.Read()),
            davxml.Privilege(caldavxml.ScheduleDeliver()),
        )
        if config.Scheduling.CalDAV.OldDraftCompatibility:
            privs += (davxml.Privilege(caldavxml.Schedule()),)

        aces = (
            # DAV:Read, CalDAV:schedule-deliver for all principals (does not include anonymous)
            davxml.ACE(
                davxml.Principal(davxml.Authenticated()),
                davxml.Grant(*privs),
                davxml.Protected(),
            ),
        )
        if config.FreeBusyURL.AnonymousAccess:
            aces += (
                # DAV:Read, for unauthenticated principals
                davxml.ACE(
                    davxml.Principal(davxml.Unauthenticated()),
                    davxml.Grant(
                        davxml.Privilege(davxml.Read()),
                    ),
                    davxml.Protected(),
                ),
            )
        return succeed(davxml.ACL(*aces))
Пример #5
0
    def defaultAccessControlList(self):

        privs = (davxml.Privilege(caldavxml.ScheduleDeliver()), )
        if config.Scheduling.CalDAV.OldDraftCompatibility:
            privs += (davxml.Privilege(caldavxml.Schedule()), )

        return succeed(
            davxml.ACL(
                # CalDAV:schedule-deliver for any authenticated user
                davxml.ACE(
                    davxml.Principal(davxml.Authenticated()),
                    davxml.Grant(*privs),
                ), ))
Пример #6
0
    def defaultAccessControlList(self):
        privs = (
            davxml.Privilege(davxml.Read()),
            davxml.Privilege(caldavxml.ScheduleDeliver()),
        )

        return succeed(
            davxml.ACL(
                # DAV:Read, CalDAV:schedule-deliver for all principals (includes anonymous)
                davxml.ACE(
                    davxml.Principal(davxml.All()),
                    davxml.Grant(*privs),
                    davxml.Protected(),
                ), ))
Пример #7
0
 def defaultAccessControlList(self):
     return succeed(
         davxml.ACL(
             # DAV:Read for authenticated principals
             davxml.ACE(
                 davxml.Principal(davxml.Authenticated()),
                 davxml.Grant(davxml.Privilege(davxml.Read()), ),
                 davxml.Protected(),
             ),
             # DAV:Write for authenticated principals
             davxml.ACE(
                 davxml.Principal(davxml.Authenticated()),
                 davxml.Grant(davxml.Privilege(davxml.Write()), ),
                 davxml.Protected(),
             ),
         ))
Пример #8
0
    def accessControlList(self, request, *args, **kwargs):
        """
        Override this to give write proxies DAV:write-acl privilege so they can add attachments too.
        """

        acl = (yield super(DropBoxHomeResource,
                           self).accessControlList(request, *args, **kwargs))

        if config.EnableProxyPrincipals:
            owner = (yield self.ownerPrincipal(request))

            newaces = tuple(acl.children)
            newaces += (
                # DAV:write-acl access for this principal's calendar-proxy-write users.
                davxml.ACE(
                    davxml.Principal(
                        davxml.HRef(
                            joinURL(owner.principalURL(),
                                    "calendar-proxy-write/"))),
                    davxml.Grant(davxml.Privilege(davxml.WriteACL()), ),
                    davxml.Protected(),
                    TwistedACLInheritable(),
                ), )

            returnValue(davxml.ACL(*newaces))

        else:
            returnValue(acl)
Пример #9
0
class SimpleResource(
        CalDAVResource, ):

    allReadACL = davxml.ACL(
        # Read access for all users.
        davxml.ACE(
            davxml.Principal(davxml.All()),
            davxml.Grant(davxml.Privilege(davxml.Read())),
            davxml.Protected(),
        ), )
    authReadACL = davxml.ACL(
        # Read access for authenticated users.
        davxml.ACE(
            davxml.Principal(davxml.Authenticated()),
            davxml.Grant(davxml.Privilege(davxml.Read())),
            davxml.Protected(),
        ), )

    def __init__(self,
                 principalCollections,
                 isdir=False,
                 defaultACL=authReadACL):
        """
        Make sure it is a collection.
        """
        CalDAVResource.__init__(self,
                                principalCollections=principalCollections)
        self._isDir = isdir
        self.defaultACL = defaultACL

    def isCollection(self):
        return self._isDir

    def deadProperties(self):
        if not hasattr(self, "_dead_properties"):
            self._dead_properties = NonePropertyStore(self)
        return self._dead_properties

    def etag(self):
        return succeed(None)

    def accessControlList(self,
                          request,
                          inheritance=True,
                          expanding=False,
                          inherited_aces=None):
        return succeed(self.defaultACL)
Пример #10
0
class TestResource(DAVResource):
    """A simple test resource used for creating trees of
    DAV Resources
    """
    _cachedPropertyStores = {}

    acl = davxml.ACL(
        davxml.ACE(
            davxml.Principal(davxml.All()),
            davxml.Grant(davxml.Privilege(davxml.All())),
            davxml.Protected(),
        ))

    def __init__(self, uri=None, children=None, principalCollections=()):
        """
        @param uri: A string respresenting the URI of the given resource
        @param children: a dictionary of names to Resources
        """
        DAVResource.__init__(self, principalCollections=principalCollections)
        self.children = children
        self.uri = uri

    def deadProperties(self):
        """
        Retrieve deadProperties from a special place in memory
        """
        if not hasattr(self, "_dead_properties"):
            dp = TestResource._cachedPropertyStores.get(self.uri)
            if dp is None:
                TestResource._cachedPropertyStores[
                    self.uri] = InMemoryPropertyStore(self)
                dp = TestResource._cachedPropertyStores[self.uri]
            self._dead_properties = dp
        return self._dead_properties

    def isCollection(self):
        return self.children is not None

    def listChildren(self):
        return self.children.keys()

    def supportedPrivileges(self, request):
        return succeed(davPrivilegeSet)

    def locateChild(self, request, segments):
        child = segments[0]
        if child == "":
            return self, segments[1:]
        elif child in self.children:
            return self.children[child], segments[1:]
        else:
            raise HTTPError(404)

    def setAccessControlList(self, acl):
        self.acl = acl

    def accessControlList(self, request, **kwargs):
        return succeed(self.acl)
Пример #11
0
 def defaultAccessControlList(self):
     return succeed(
         davxml.ACL(
             davxml.ACE(
                 davxml.Principal(davxml.Authenticated()),
                 davxml.Grant(davxml.Privilege(davxml.Read()), ),
                 davxml.Protected(),
                 TwistedACLInheritable(),
             ), ))
Пример #12
0
 def defaultAccessControlList(self):
     return succeed(
         davxml.ACL(
             # DAV:Read for all principals (includes anonymous)
             davxml.ACE(
                 davxml.Principal(davxml.All()),
                 davxml.Grant(davxml.Privilege(davxml.Read()), ),
                 davxml.Protected(),
             ), ))
    def defaultAccessControlList(self):
        if config.AnonymousDirectoryAddressBookAccess:
            # DAV:Read for all principals (includes anonymous)
            accessPrincipal = davxml.All()
        else:
            # DAV:Read for all authenticated principals (does not include anonymous)
            accessPrincipal = davxml.Authenticated()

        return succeed(
            davxml.ACL(
                davxml.ACE(
                    davxml.Principal(accessPrincipal),
                    davxml.Grant(
                        davxml.Privilege(davxml.Read()),
                        davxml.Privilege(
                            davxml.ReadCurrentUserPrivilegeSet())),
                    davxml.Protected(),
                    TwistedACLInheritable(),
                ), ))
Пример #14
0
class AuthAllResource(TestResource):
    """
    Give Authenticated principals all privileges and deny everyone else.
    """
    acl = davxml.ACL(
        davxml.ACE(
            davxml.Principal(davxml.Authenticated()),
            davxml.Grant(davxml.Privilege(davxml.All())),
            davxml.Protected(),
        ))
Пример #15
0
    def defaultAccessControlList(self):
        if config.EnableProxyPrincipals:
            myPrincipal = yield self.parent.principalForRecord()

            privs = (davxml.Privilege(caldavxml.ScheduleSend()), )
            if config.Scheduling.CalDAV.OldDraftCompatibility:
                privs += (davxml.Privilege(caldavxml.Schedule()), )

            returnValue(
                davxml.ACL(
                    # CalDAV:schedule for associated write proxies
                    davxml.ACE(
                        davxml.Principal(
                            davxml.HRef(
                                joinURL(myPrincipal.principalURL(),
                                        "calendar-proxy-write"))),
                        davxml.Grant(*privs),
                        davxml.Protected(),
                    ), ))
        else:
            returnValue(
                super(ScheduleOutboxResource, self).defaultAccessControlList())
Пример #16
0
    def setUp(self):
        TestCase.setUp(self)

        gooduser = TestDAVPrincipalResource("/users/gooduser")
        gooduser.writeDeadProperty(TwistedPasswordProperty("goodpass"))

        baduser = TestDAVPrincipalResource("/users/baduser")
        baduser.writeDeadProperty(TwistedPasswordProperty("badpass"))

        rootresource = TestPrincipalsCollection(
            "/", {
                "users":
                TestResource("/users/", {
                    "gooduser": gooduser,
                    "baduser": baduser
                })
            })

        protected = TestResource("/protected",
                                 principalCollections=[rootresource])

        protected.setAccessControlList(
            davxml.ACL(
                davxml.ACE(davxml.Principal(davxml.HRef("/users/gooduser")),
                           davxml.Grant(davxml.Privilege(davxml.All())),
                           davxml.Protected())))

        rootresource.children["protected"] = protected

        portal = Portal(DavRealm())
        portal.registerChecker(TwistedPropertyChecker())

        credentialFactories = (basic.BasicCredentialFactory(""), )

        loginInterfaces = (IPrincipal, )

        self.rootresource = rootresource
        self.site = Site(
            AuthenticationWrapper(
                self.rootresource,
                portal,
                credentialFactories,
                credentialFactories,
                loginInterfaces,
            ))
Пример #17
0
    def __init__(self, base_uri, errors):
        """
        An error response which is due to unsufficient privileges, as
        determined by L{DAVResource.checkPrivileges}.
        @param base_uri: the base URI for the resources with errors (the URI of
            the resource on which C{checkPrivileges} was called).
        @param errors: a sequence of tuples, as returned by
            C{checkPrivileges}.
        """
        denials = []

        for subpath, privileges in errors:
            if subpath is None:
                uri = base_uri
            else:
                uri = joinURL(base_uri, subpath)

            for p in privileges:
                denials.append(
                    element.Resource(element.HRef(uri), element.Privilege(p)))

        super(NeedPrivilegesResponse,
              self).__init__(responsecode.FORBIDDEN,
                             element.NeedPrivileges(*denials))
Пример #18
0
def getWikiACL(resource, request):
    """
    Ask the wiki server we're paired with what level of access the authnUser
    has.

    Returns an ACL.

    Wiki authentication is a bit tricky because the end-user accessing a group
    calendar may not actually be enabled for calendaring.  Therefore in that
    situation, the authzUser will have been replaced with the wiki principal
    in locateChild( ), so that any changes the user makes will have the wiki
    as the originator.  The authnUser will always be the end-user.
    """
    from twistedcaldav.directory.principal import DirectoryPrincipalResource

    if (not hasattr(resource, "record")
            or resource.record.recordType != RecordType.macOSXServerWiki):
        returnValue(None)

    if hasattr(request, 'wikiACL'):
        returnValue(request.wikiACL)

    wikiRecord = resource.record
    wikiID = wikiRecord.shortNames[0]
    userRecord = None

    try:
        url = request.authnUser.principalURL()
        principal = (yield request.locateResource(url))
        if isinstance(principal, DirectoryPrincipalResource):
            userRecord = principal.record
    except:
        # TODO: better error handling
        pass

    try:
        access = yield wikiRecord.accessForRecord(userRecord)

        # The ACL we returns has ACEs for the end-user and the wiki principal
        # in case authzUser is the wiki principal.
        if access == WikiAccessLevel.read:
            request.wikiACL = davxml.ACL(
                davxml.ACE(
                    (request.authnUser.principalElement()
                     if request.authnUser is not None else davxml.Principal(
                         davxml.Unauthenticated())),
                    davxml.Grant(
                        davxml.Privilege(davxml.Read()),
                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),

                        # We allow write-properties so that direct sharees can
                        # change e.g. calendar color properties
                        davxml.Privilege(davxml.WriteProperties()),
                    ),
                    TwistedACLInheritable(),
                ),
                davxml.ACE(
                    davxml.Principal(
                        davxml.HRef.fromString(
                            "/principals/wikis/{}/".format(wikiID))),
                    davxml.Grant(
                        davxml.Privilege(davxml.Read()),
                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
                    ),
                    TwistedACLInheritable(),
                ))
            returnValue(request.wikiACL)

        elif access == WikiAccessLevel.write:
            request.wikiACL = davxml.ACL(
                davxml.ACE(
                    (request.authnUser.principalElement()
                     if request.authnUser is not None else davxml.Principal(
                         davxml.Unauthenticated())),
                    davxml.Grant(
                        davxml.Privilege(davxml.Read()),
                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
                        davxml.Privilege(davxml.Write()),
                    ),
                    TwistedACLInheritable(),
                ),
                davxml.ACE(
                    davxml.Principal(
                        davxml.HRef.fromString(
                            "/principals/wikis/{}/".format(wikiID))),
                    davxml.Grant(
                        davxml.Privilege(davxml.Read()),
                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
                        davxml.Privilege(davxml.Write()),
                    ),
                    TwistedACLInheritable(),
                ))
            returnValue(request.wikiACL)

        else:  # "no-access":

            if userRecord is None:
                # Return a 401 so they have an opportunity to log in
                response = (yield UnauthorizedResponse.makeResponse(
                    request.credentialFactories,
                    request.remoteAddr,
                ))
                raise HTTPError(response)

            raise HTTPError(
                StatusResponse(responsecode.FORBIDDEN,
                               "You are not allowed to access this wiki"))

    except HTTPError:
        # pass through the HTTPError we might have raised above
        raise

    except Exception as e:
        log.error("Wiki ACL lookup failed: {error}", error=e)
        raise HTTPError(
            StatusResponse(responsecode.SERVICE_UNAVAILABLE,
                           "Wiki ACL lookup failed"))
Пример #19
0
 def grantInherit(*privileges):
     return element.ACL(*[
         element.ACE(element.Grant(element.Privilege(privilege)),
                     element.Principal(element.All()),
                     TwistedACLInheritable()) for privilege in privileges
     ])
Пример #20
0
    def shareeAccessControlList(self, request, *args, **kwargs):
        """
        Return WebDAV ACLs appropriate for the current user accessing the
        shared collection.  For an "invite" share we take the privilege granted
        to the sharee in the invite and map that to WebDAV ACLs.  For a
        "direct" share, if it is a wiki collection we map the wiki privileges
        into WebDAV ACLs, otherwise we use whatever privileges exist on the
        underlying shared collection.

        @param request: the request used to locate the owner resource.
        @type request: L{txweb2.iweb.IRequest}

        @param args: The arguments for
            L{txweb2.dav.idav.IDAVResource.accessControlList}

        @param kwargs: The keyword arguments for
            L{txweb2.dav.idav.IDAVResource.accessControlList}, plus
            keyword-only arguments.

        @return: the appropriate WebDAV ACL for the sharee
        @rtype: L{davxml.ACL}
        """

        assert self._isShareeResource, "Only call this for a sharee resource"
        assert self.isCalendarCollection() or self.isAddressBookCollection(
        ), "Only call this for a address book or calendar resource"

        sharee = yield self.principalForUID(
            self._newStoreObject.viewerHome().uid())
        access = yield self._checkAccessControl()

        if access == "original" and not self._newStoreObject.ownerHome(
        ).external():
            original = (yield request.locateResource(self._share_url))
            result = (yield original.accessControlList(request, *args,
                                                       **kwargs))
            returnValue(result)

        # Direct shares use underlying privileges of shared collection
        userprivs = []
        if access in (
                "read-only",
                "read-write",
        ):
            userprivs.append(element.Privilege(element.Read()))
            userprivs.append(element.Privilege(element.ReadACL()))
            userprivs.append(
                element.Privilege(element.ReadCurrentUserPrivilegeSet()))
        if access in ("read-only", ):
            userprivs.append(element.Privilege(element.WriteProperties()))
        if access in ("read-write", ):
            userprivs.append(element.Privilege(element.Write()))
        proxyprivs = list(userprivs)
        try:
            proxyprivs.remove(element.Privilege(element.ReadACL()))
        except ValueError:
            # If wiki says no-access then ReadACL won't be in the list
            pass

        aces = (
            # Inheritable specific access for the resource's associated principal.
            element.ACE(
                element.Principal(element.HRef(sharee.principalURL())),
                element.Grant(*userprivs),
                element.Protected(),
                TwistedACLInheritable(),
            ), )

        if self.isCalendarCollection():
            aces += (
                # Inheritable CALDAV:read-free-busy access for authenticated users.
                element.ACE(
                    element.Principal(element.Authenticated()),
                    element.Grant(element.Privilege(caldavxml.ReadFreeBusy())),
                    TwistedACLInheritable(),
                ), )

        # Give read access to config.ReadPrincipals
        aces += config.ReadACEs

        # Give all access to config.AdminPrincipals
        aces += config.AdminACEs

        if self.isCalendarCollection() and config.EnableProxyPrincipals:
            aces += (
                # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
                element.ACE(
                    element.Principal(
                        element.HRef(
                            joinURL(sharee.principalURL(),
                                    "calendar-proxy-read/"))),
                    element.Grant(
                        element.Privilege(element.Read()),
                        element.Privilege(
                            element.ReadCurrentUserPrivilegeSet()),
                        element.Privilege(element.WriteProperties()),
                    ),
                    element.Protected(),
                    TwistedACLInheritable(),
                ),
                # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
                element.ACE(
                    element.Principal(
                        element.HRef(
                            joinURL(sharee.principalURL(),
                                    "calendar-proxy-write/"))),
                    element.Grant(*proxyprivs),
                    element.Protected(),
                    TwistedACLInheritable(),
                ),
            )

        returnValue(element.ACL(*aces))
Пример #21
0
                "calendar-proxy-write-for",
        ):
            # name is required to be str
            from twistedcaldav.directory.calendaruserproxy import (
                CalendarUserProxyPrincipalResource)
            return succeed(CalendarUserProxyPrincipalResource(self, str(name)))
        else:
            return succeed(None)

    def listChildren(self):
        if config.EnableProxyPrincipals:
            return (
                "calendar-proxy-read",
                "calendar-proxy-write",
            )
        else:
            return ()


##
# Utilities
##

authReadACL = davxml.ACL(
    # Read access for authenticated users.
    davxml.ACE(
        davxml.Principal(davxml.Authenticated()),
        davxml.Grant(davxml.Privilege(davxml.Read())),
        davxml.Protected(),
    ), )
Пример #22
0
 def grant(*privileges):
     return element.ACL(*[
         element.ACE(element.Grant(element.Privilege(privilege)),
                     element.Principal(element.All()))
         for privilege in privileges
     ])