[CalendarServer-changes] [13074] CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools

source_changes at macosforge.org source_changes at macosforge.org
Mon Mar 31 18:03:36 PDT 2014


Revision: 13074
          http://trac.calendarserver.org//changeset/13074
Author:   wsanchez at apple.com
Date:     2014-03-31 18:03:36 -0700 (Mon, 31 Mar 2014)
Log Message:
-----------
Use twext.who instead of OD module.

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/agent.py
    CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_agent.py

Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/agent.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/agent.py	2014-04-01 00:58:20 UTC (rev 13073)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/agent.py	2014-04-01 01:03:36 UTC (rev 13074)
@@ -26,130 +26,38 @@
 
 from __future__ import print_function
 
+__all__ = [
+    "makeAgentService",
+]
+
 import cStringIO
+from plistlib import readPlistFromString, writePlistToString
 import socket
 
 from calendarserver.tap.util import getRootResource
-from plistlib import readPlistFromString, writePlistToString
+from twext.python.launchd import getLaunchDSocketFDs
+from twext.python.log import Logger
+from twext.who.checker import HTTPDigestCredentialChecker
+from twext.who.opendirectory import (
+    DirectoryService as OpenDirectoryDirectoryService,
+    NoQOPDigestCredentialFactory
+)
 from twisted.application.internet import StreamServerEndpointService
-from twisted.cred.checkers import ICredentialsChecker
-from twisted.cred.credentials import IUsernameHashedPassword
-from twisted.cred.error import UnauthorizedLogin
 from twisted.cred.portal import IRealm, Portal
-from twisted.internet.defer import inlineCallbacks, returnValue, succeed, fail
+from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.internet.endpoints import AdoptedStreamServerEndpoint
 from twisted.internet.protocol import Factory
 from twisted.protocols import amp
-from twisted.web.guard import HTTPAuthSessionWrapper, DigestCredentialFactory
+from twisted.web.guard import HTTPAuthSessionWrapper
 from twisted.web.resource import IResource, Resource, ForbiddenResource
 from twisted.web.server import Site, NOT_DONE_YET
 from zope.interface import implements
-from twext.python.launchd import getLaunchDSocketFDs
-from twext.python.log import Logger
 
+
 log = Logger()
 
 
 
-class DirectoryServiceChecker(object):
-    """
-    A checker that knows how to ask OpenDirectory to authenticate via Digest
-    """
-    implements(ICredentialsChecker)
-
-    credentialInterfaces = (IUsernameHashedPassword,)
-
-    from calendarserver.platform.darwin.od import opendirectory
-    directoryModule = opendirectory
-
-    def __init__(self, node):
-        """
-        @param node: the name of the OpenDirectory node to use, e.g.
-            C{"/Local/Default"}
-        """
-        self.node = node
-        self.directory = self.directoryModule.odInit(node)
-
-
-    def requestAvatarId(self, credentials):
-        record = self.directoryModule.getUserRecord(
-            self.directory, credentials.username
-        )
-
-        if record is not None:
-            try:
-                if "algorithm" not in credentials.fields:
-                    credentials.fields["algorithm"] = "md5"
-
-                challenge = (
-                    'Digest realm="{realm}", nonce="{nonce}", '
-                    'algorithm={algorithm}'
-                    .format(**credentials.fields)
-                )
-
-                response = (
-                    'Digest username="{username}", '
-                    'realm="{realm}", '
-                    'nonce="{nonce}", '
-                    'uri="{uri}", '
-                    'response="{response}",'
-                    'algorithm={algorithm}'
-                ).format(**credentials.fields)
-
-            except KeyError as e:
-                log.error(
-                    "OpenDirectory (node={checker.node}) error while "
-                    "performing digest authentication for user "
-                    "{credentials.username}: missing digest response field: "
-                    "{field} in: {credentials.fields}"
-                    .format(
-                        checker=self, credentials=credentials, field=e
-                    )
-                )
-                return fail(UnauthorizedLogin())
-
-            try:
-                if self.directoryModule.authenticateUserDigest(
-                    self.directory,
-                    self.node,
-                    credentials.username,
-                    challenge,
-                    response,
-                    credentials.method
-                ):
-                    return succeed(credentials.username)
-                else:
-                    log.error(
-                        "Failed digest auth with response: {response}",
-                        response=response
-                    )
-                    return fail(UnauthorizedLogin())
-            except Exception as e:
-                log.error(
-                    "OpenDirectory error while performing digest "
-                    "authentication for user {credentials.username}: "
-                    "{error}",
-                    credentials=credentials, error=e
-                )
-                return fail(UnauthorizedLogin())
-
-        else:
-            return fail(UnauthorizedLogin())
-
-
-
-class CustomDigestCredentialFactory(DigestCredentialFactory):
-    """
-    DigestCredentialFactory without qop, to interop with OD.
-    """
-
-    def getChallenge(self, address):
-        result = DigestCredentialFactory.getChallenge(self, address)
-        del result["qop"]
-        return result
-
-
-
 class AgentRealm(object):
     """
     Only allow a specified list of avatar IDs to access the site
@@ -277,12 +185,15 @@
         )
     )
 
-    realmName = "/Local/Default"
+    directory = OpenDirectoryDirectoryService("/Local/Default")
+
     portal = Portal(
         AgentRealm(root, ["com.apple.calendarserver"]),
-        [DirectoryServiceChecker(realmName)]
+        [HTTPDigestCredentialChecker(directory)]
     )
-    credentialFactory = CustomDigestCredentialFactory("md5", realmName)
+    credentialFactory = NoQOPDigestCredentialFactory(
+        "md5", "CalendarServer Agent Realm"
+    )
     wrapper = HTTPAuthSessionWrapper(portal, [credentialFactory])
 
     site = Site(wrapper)

Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_agent.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_agent.py	2014-04-01 00:58:20 UTC (rev 13073)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_agent.py	2014-04-01 01:03:36 UTC (rev 13074)
@@ -16,84 +16,18 @@
 
 try:
     from calendarserver.tools.agent import AgentRealm
-    from calendarserver.tools.agent import CustomDigestCredentialFactory
-    from calendarserver.tools.agent import DirectoryServiceChecker
     from calendarserver.tools.agent import InactivityDetector
     from twistedcaldav.test.util import TestCase
-    from twisted.internet.defer import inlineCallbacks
     from twisted.internet.task import Clock
-    from twisted.cred.error import UnauthorizedLogin
     from twisted.web.resource import IResource
     from twisted.web.resource import ForbiddenResource
-    RUN_TESTS = True
+
 except ImportError:
-    RUN_TESTS = False
+    pass
 
-
-
-if RUN_TESTS:
+else:
     class AgentTestCase(TestCase):
 
-        def test_CustomDigestCredentialFactory(self):
-            f = CustomDigestCredentialFactory("md5", "/Local/Default")
-            challenge = f.getChallenge(FakeRequest())
-            self.assertTrue("qop" not in challenge)
-            self.assertEquals(challenge["algorithm"], "md5")
-            self.assertEquals(challenge["realm"], "/Local/Default")
-
-        @inlineCallbacks
-        def test_DirectoryServiceChecker(self):
-            c = DirectoryServiceChecker("/Local/Default")
-            fakeOpenDirectory = FakeOpenDirectory()
-            c.directoryModule = fakeOpenDirectory
-
-            fields = {
-                "username": "foo",
-                "realm": "/Local/Default",
-                "nonce": 1,
-                "uri": "/gateway",
-                "response": "abc",
-                "algorithm": "md5",
-            }
-            creds = FakeCredentials("foo", fields)
-
-            # Record does not exist:
-            fakeOpenDirectory.returnThisRecord(None)
-            try:
-                yield c.requestAvatarId(creds)
-            except UnauthorizedLogin:
-                pass
-            else:
-                self.fail("Didn't raise UnauthorizedLogin")
-
-            # Record exists, but invalid credentials
-            fakeOpenDirectory.returnThisRecord("fooRecord")
-            fakeOpenDirectory.returnThisAuthResponse(False)
-            try:
-                yield c.requestAvatarId(creds)
-            except UnauthorizedLogin:
-                pass
-            else:
-                self.fail("Didn't raise UnauthorizedLogin")
-
-            # Record exists, valid credentials
-            fakeOpenDirectory.returnThisRecord("fooRecord")
-            fakeOpenDirectory.returnThisAuthResponse(True)
-            avatar = (yield c.requestAvatarId(creds))
-            self.assertEquals(avatar, "foo")
-
-            # Record exists, but missing fields in credentials
-            del creds.fields["nonce"]
-            fakeOpenDirectory.returnThisRecord("fooRecord")
-            fakeOpenDirectory.returnThisAuthResponse(False)
-            try:
-                yield c.requestAvatarId(creds)
-            except UnauthorizedLogin:
-                pass
-            else:
-                self.fail("Didn't raise UnauthorizedLogin")
-
-
         def test_AgentRealm(self):
             realm = AgentRealm("root", ["abc"])
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140331/ab7a05a8/attachment-0001.html>


More information about the calendarserver-changes mailing list