[CalendarServer-changes] [1542] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon May 21 11:23:56 PDT 2007
Revision: 1542
http://trac.macosforge.org/projects/calendarserver/changeset/1542
Author: cdaboo at apple.com
Date: 2007-05-21 11:23:56 -0700 (Mon, 21 May 2007)
Log Message:
-----------
Have the server auto-detect its own Kerberos principal given the hostname.
Modified Paths:
--------------
CalendarServer/trunk/run
CalendarServer/trunk/twistedcaldav/authkerb.py
CalendarServer/trunk/twistedcaldav/tap.py
CalendarServer/trunk/twistedcaldav/test/test_kerberos.py
CalendarServer/trunk/twistedcaldav/test/test_tap.py
Modified: CalendarServer/trunk/run
===================================================================
--- CalendarServer/trunk/run 2007-05-21 18:01:59 UTC (rev 1541)
+++ CalendarServer/trunk/run 2007-05-21 18:23:56 UTC (rev 1542)
@@ -464,7 +464,7 @@
if ! py_have_module kerberos; then
kerberos="${top}/PyKerberos";
- svn_get "PyKerberos" "${kerberos}" "${svn_uri_base}/PyKerberos/trunk" 1213;
+ svn_get "PyKerberos" "${kerberos}" "${svn_uri_base}/PyKerberos/trunk" 1541;
py_build "PyKerberos" "${kerberos}" false; # FIXME: make optional
py_install "PyKerberos" "${kerberos}";
Modified: CalendarServer/trunk/twistedcaldav/authkerb.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/authkerb.py 2007-05-21 18:01:59 UTC (rev 1541)
+++ CalendarServer/trunk/twistedcaldav/authkerb.py 2007-05-21 18:23:56 UTC (rev 1542)
@@ -55,6 +55,17 @@
"""
def __init__(self, username, password, service, realm):
+ """
+
+ @param username: user name of user to authenticate
+ @type username: str
+ @param password: password for user being authenticated
+ @type password: str
+ @param service: service principal
+ @type service: str
+ @param hostname: realm
+ @type hostname: str
+ """
credentials.UsernamePassword.__init__(self, username, password)
# Convert Kerberos principal spec into service and realm
@@ -73,15 +84,43 @@
scheme = 'basic'
- def __init__(self, service, realm):
+ def __init__(self, principal=None, type=None, hostname=None):
"""
- The realm string can be of the form service/realm at domain. We split that
- into service at domain, and realm.
+
+ @param principal: full Kerberos principal (e.g., 'http/server.example.com at EXAMPLE.COM'). If C{None}
+ then the type and hostname arguments are used instead.
+ @type service: str
+ @param type: service type for Kerberos (e.g., 'http'). Must be C{None} if principal used.
+ @type type: str
+ @param hostname: hostname for this server. Must be C{None} if principal used.
+ @type hostname: str
"""
- self.service = service
+
+ # Only certain combinations of arguments allowed
+ assert (principal and not type and not hostname) or (not principal and type and hostname)
+
+ if not principal:
+ # Look up the Kerberos principal given the service type and hostname, and extract
+ # the realm and a service principal value for later use.
+ try:
+ principal = kerberos.getServerPrincipalDetails(type, hostname)
+ except kerberos.KrbError, ex:
+ logging.err("getServerPrincipalDetails: %s" % (ex[0],), system="BasicKerberosCredentialFactory")
+ raise ValueError('Authentication System Failure: %s' % (ex[0],))
+
+ try:
+ splits = principal.split("/")
+ servicetype = splits[0]
+ splits = splits[1].split("@")
+ realm = splits[1]
+ except IndexError:
+ logging.err("Invalid Kerberos principal: %s" % (principal,), system="BasicKerberosCredentialFactory")
+ raise ValueError('Authentication System Failure: Invalid Kerberos principal: %s' % (principal,))
+
+ self.service = "%s@%s" % (servicetype, realm,)
self.realm = realm
- def getChallenge(self, peer):
+ def getChallenge(self, _ignore_peer):
return {'realm': self.realm}
def decode(self, response, request): #@UnusedVariable
@@ -142,19 +181,50 @@
scheme = 'negotiate'
- def __init__(self, service, realm):
+ def __init__(self, principal=None, type=None, hostname=None):
+ """
+
+ @param principal: full Kerberos principal (e.g., 'http/server.example.com at EXAMPLE.COM'). If C{None}
+ then the type and hostname arguments are used instead.
+ @type service: str
+ @param type: service type for Kerberos (e.g., 'http'). Must be C{None} if principal used.
+ @type type: str
+ @param hostname: hostname for this server. Must be C{None} if principal used.
+ @type hostname: str
+ """
- self.service = service
+ # Only certain combinations of arguments allowed
+ assert (principal and not type and not hostname) or (not principal and type and hostname)
+
+ if not principal:
+ # Look up the Kerberos principal given the service type and hostname, and extract
+ # the realm and a service principal value for later use.
+ try:
+ principal = kerberos.getServerPrincipalDetails(type, hostname)
+ except kerberos.KrbError, ex:
+ logging.err("getServerPrincipalDetails: %s" % (ex[0],), system="NegotiateCredentialFactory")
+ raise ValueError('Authentication System Failure: %s' % (ex[0],))
+
+ try:
+ splits = principal.split("/")
+ servicetype = splits[0]
+ splits = splits[1].split("@")
+ realm = splits[1]
+ except IndexError:
+ logging.err("Invalid Kerberos principal: %s" % (principal,), system="NegotiateCredentialFactory")
+ raise ValueError('Authentication System Failure: Invalid Kerberos principal: %s' % (principal,))
+
+ self.service = "%s@%s" % (servicetype, realm,)
self.realm = realm
- def getChallenge(self, peer):
+ def getChallenge(self, _ignore_peer):
return {}
def decode(self, base64data, request):
# Init GSSAPI first
try:
- result, context = kerberos.authGSSServerInit(self.service);
+ _ignore_result, context = kerberos.authGSSServerInit(self.service);
except kerberos.GSSError, ex:
logging.err("authGSSServerInit: %s(%s)" % (ex[0][0], ex[1][0],), system="NegotiateCredentialFactory")
raise error.LoginFailed('Authentication System Failure: %s(%s)' % (ex[0][0], ex[1][0],))
@@ -191,7 +261,7 @@
# Close the context
try:
- result = kerberos.authGSSServerClean(context);
+ kerberos.authGSSServerClean(context);
except kerberos.GSSError, ex:
logging.err("authGSSServerClean: %s" % (ex[0][0], ex[1][0],), system="NegotiateCredentialFactory")
raise error.LoginFailed('Authentication System Failure %s(%s)' % (ex[0][0], ex[1][0],))
Modified: CalendarServer/trunk/twistedcaldav/tap.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/tap.py 2007-05-21 18:01:59 UTC (rev 1541)
+++ CalendarServer/trunk/twistedcaldav/tap.py 2007-05-21 18:23:56 UTC (rev 1542)
@@ -415,18 +415,12 @@
log.msg("Kerberos support not available")
continue
- service = schemeConfig['ServicePrincipal']
-
- if '@' in service:
- rest, kerbRealm = service.split('@', 1)
+ principal = schemeConfig['ServicePrincipal']
+ if not principal:
+ credFactory = NegotiateCredentialFactory(type="http", hostname=config.ServerHostName)
else:
- kerbRealm = config.ServerHostName
+ credFactory = NegotiateCredentialFactory(principal=principal)
- credFactory = NegotiateCredentialFactory(
- service,
- kerbRealm
- )
-
elif scheme == 'digest':
credFactory = QopDigestCredentialFactory(
schemeConfig['Algorithm'],
Modified: CalendarServer/trunk/twistedcaldav/test/test_kerberos.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_kerberos.py 2007-05-21 18:01:59 UTC (rev 1541)
+++ CalendarServer/trunk/twistedcaldav/test/test_kerberos.py 2007-05-21 18:23:56 UTC (rev 1542)
@@ -34,18 +34,25 @@
authkerb.BasicKerberosCredentials("test", "test", "http/example.com at EXAMPLE.COM", "EXAMPLE.COM")
def test_BasicKerberosCredentialFactory(self):
- factory = authkerb.BasicKerberosCredentialFactory("http/example.com at EXAMPLE.COM", "EXAMPLE.COM")
+ factory = authkerb.BasicKerberosCredentialFactory(principal="http/server.example.com at EXAMPLE.COM")
challenge = factory.getChallenge("peer")
expected_challenge = {'realm': "EXAMPLE.COM"}
self.assertTrue(challenge == expected_challenge,
msg="BasicKerberosCredentialFactory challenge %s != %s" % (challenge, expected_challenge))
+ def test_BasicKerberosCredentialFactoryInvalidPrincipal(self):
+ self.assertRaises(
+ ValueError,
+ authkerb.BasicKerberosCredentialFactory,
+ principal="http/server.example.com/EXAMPLE.COM"
+ )
+
def test_NegotiateCredentials(self):
authkerb.NegotiateCredentials("test")
def test_NegotiateCredentialFactory(self):
- factory = authkerb.NegotiateCredentialFactory("http/example.com at EXAMPLE.COM", "EXAMPLE.COM")
+ factory = authkerb.NegotiateCredentialFactory(principal="http/server.example.com at EXAMPLE.COM")
challenge = factory.getChallenge("peer")
expected_challenge = {}
@@ -61,3 +68,10 @@
self.fail(msg="NegotiateCredentialFactory decode failed with exception: %s" % (ex,))
else:
self.fail(msg="NegotiateCredentialFactory decode did not fail")
+
+ def test_NegotiateCredentialFactoryInvalidPrincipal(self):
+ self.assertRaises(
+ ValueError,
+ authkerb.NegotiateCredentialFactory,
+ principal="http/server.example.com/EXAMPLE.COM"
+ )
Modified: CalendarServer/trunk/twistedcaldav/test/test_tap.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_tap.py 2007-05-21 18:01:59 UTC (rev 1541)
+++ CalendarServer/trunk/twistedcaldav/test/test_tap.py 2007-05-21 18:23:56 UTC (rev 1542)
@@ -413,6 +413,7 @@
"""
self.config['Authentication']['Digest']['Enabled'] = True
self.config['Authentication']['Kerberos']['Enabled'] = True
+ self.config['Authentication']['Kerberos']['ServicePrincipal'] = 'http/hello at bob'
self.config['Authentication']['Basic']['Enabled'] = True
self.writeConfig()
@@ -432,23 +433,18 @@
self.assertEquals(len(expectedSchemes),
len(authWrapper.credentialFactories))
- def test_servicePrincipalNoRealm(self):
+ def test_servicePrincipalNone(self):
"""
- Test that the Kerberos Realm defaults to the ServerHostName when
- the principal is not in the form of proto/host at realm
+ Test that the Kerberos principal look is attempted if the principal is empty.
"""
- self.config['Authentication']['Kerberos']['ServicePrincipal'] = 'http/hello'
+ self.config['Authentication']['Kerberos']['ServicePrincipal'] = ''
self.config['Authentication']['Kerberos']['Enabled'] = True
self.writeConfig()
- site = self.getSite()
+ self.assertRaises(
+ ValueError,
+ self.getSite)
- authWrapper = site.resource.resource
-
- ncf = authWrapper.credentialFactories['negotiate']
- self.assertEquals(ncf.service, 'http/hello')
- self.assertEquals(ncf.realm, 'localhost')
-
- def test_servicePrincipalWithRealm(self):
+ def test_servicePrincipal(self):
"""
Test that the kerberos realm is the realm portion of a principal
in the form proto/host at realm
@@ -461,7 +457,7 @@
authWrapper = site.resource.resource
ncf = authWrapper.credentialFactories['negotiate']
- self.assertEquals(ncf.service, 'http/hello at bob')
+ self.assertEquals(ncf.service, 'http at bob')
self.assertEquals(ncf.realm, 'bob')
def test_AuthWrapperPartialEnabled(self):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070521/3b7bec12/attachment.html
More information about the calendarserver-changes
mailing list