Revision: 4111 http://trac.macosforge.org/projects/calendarserver/changeset/4111 Author: wsanchez@apple.com Date: 2009-04-29 10:43:31 -0700 (Wed, 29 Apr 2009) Log Message: ----------- Enable Kerberos authentication in CalDAVClientLibrary. Contributed by rziai@sfs.uni-tuebingen.de Fixes #334 Modified Paths: -------------- CalDAVClientLibrary/trunk/src/client/clientsession.py Added Paths: ----------- CalDAVClientLibrary/trunk/src/protocol/http/authentication/gssapi.py Modified: CalDAVClientLibrary/trunk/src/client/clientsession.py =================================================================== --- CalDAVClientLibrary/trunk/src/client/clientsession.py 2009-04-29 16:55:32 UTC (rev 4110) +++ CalDAVClientLibrary/trunk/src/client/clientsession.py 2009-04-29 17:43:31 UTC (rev 4111) @@ -25,6 +25,7 @@ from protocol.webdav.principalmatch import PrincipalMatch from protocol.http.authentication.basic import Basic from protocol.http.authentication.digest import Digest +from protocol.http.authentication.gssapi import Kerberos from protocol.webdav.proppatch import PropPatch from xml.etree.ElementTree import Element from protocol.webdav.get import Get @@ -664,6 +665,8 @@ return Basic(self.user, self.pswd), False elif item.lower().startswith("digest"): return Digest(self.user, self.pswd, wwwhdrs), False + elif item.lower().startswith("negotiate"): + return Kerberos(self.user), False else: return None, True Added: CalDAVClientLibrary/trunk/src/protocol/http/authentication/gssapi.py =================================================================== --- CalDAVClientLibrary/trunk/src/protocol/http/authentication/gssapi.py (rev 0) +++ CalDAVClientLibrary/trunk/src/protocol/http/authentication/gssapi.py 2009-04-29 17:43:31 UTC (rev 4111) @@ -0,0 +1,112 @@ +# Copyright (c) 2006-2007 Apple Inc. All rights reserved. +# Copyright (c) 2008 Lime Nest LLC +# Copyright (c) 2008 Lime Spot LLC +# Copyright (c) 2009 Ramon Ziai +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## + +''' +Parts of the following are inspired by urllib2_kerberos, +which is also under the Apache 2.0 License, +see http://limedav.com/hg/urllib2_kerberos +''' + +from protocol.http.authentication.authenticator import Authenticator +from protocol.http.definitions import headers +import re +import kerberos + +class Kerberos(Authenticator): + + def __init__(self, user): + self.user = user + self.context = None + + def addHeaders(self, hdrs, request): + neg_value = self.negotiate_value(hdrs) + header = self.generate_request_header(request, hdrs, neg_value) + + # Generate header + hdrs.append((headers.Authorization, header)) + self.clean_context() + + def negotiate_value(self, headers): + """checks for "Negotiate" in proper auth header + taken from urllib2_kerberos, see http://limedav.com/hg/urllib2_kerberos + """ + authreq = None + for hdr in headers: + if hdr[0].lower == "www-authenticate" and "Negotiate" in hdr[1]: + authreq = hdr[1] + + if authreq: + rx = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I) + mo = rx.search(authreq) + if mo: + return mo.group(1) + else: + # regex failed + pass + + else: + pass + # header not found + + return None + + def generate_request_header(self, req, headers, neg_value): + """ + taken from urllib2_kerberos, see http://limedav.com/hg/urllib2_kerberos + """ + + host = None + # assuming that "Host" is one of the headers, which is usually the case + for hdr in headers: + if hdr[0] == "Host": + host = hdr[1] + + tail, sep, head = host.rpartition(':') + domain = tail if tail else head + + # do GSS init + result, self.context = kerberos.authGSSClientInit("http@%s" % domain) + + if result < 1: + # authGSSClientInit returned negative result + return None + + # authGSSClientInit() succeeded + data = "" + if neg_value != None: + data = neg_value + result = kerberos.authGSSClientStep(self.context, data) + + if result < 0: + # authGSSClientStep returned bad result + return None + + # authGSSClientStep() succeeded + + response = kerberos.authGSSClientResponse(self.context) + # authGSSClientResponse() succeeded + + return "Negotiate %s" % response + + def clean_context(self): + """ + taken from urllib2_kerberos, see http://limedav.com/hg/urllib2_kerberos + """ + if self.context is not None: + kerberos.authGSSClientClean(self.context) + self.context = None
participants (1)
-
source_changes@macosforge.org