[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