| Index: third_party/twisted_8_1/twisted/words/protocols/jabber/sasl_mechanisms.py
|
| diff --git a/third_party/twisted_8_1/twisted/words/protocols/jabber/sasl_mechanisms.py b/third_party/twisted_8_1/twisted/words/protocols/jabber/sasl_mechanisms.py
|
| deleted file mode 100644
|
| index 841b1680fe72a0c774007b2f8e23149d9e499366..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/words/protocols/jabber/sasl_mechanisms.py
|
| +++ /dev/null
|
| @@ -1,224 +0,0 @@
|
| -# -*- test-case-name: twisted.words.test.test_jabbersaslmechanisms -*-
|
| -#
|
| -# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -"""
|
| -Protocol agnostic implementations of SASL authentication mechanisms.
|
| -"""
|
| -
|
| -import md5, binascii, random, time, os
|
| -
|
| -from zope.interface import Interface, Attribute, implements
|
| -
|
| -class ISASLMechanism(Interface):
|
| - name = Attribute("""Common name for the SASL Mechanism.""")
|
| -
|
| - def getInitialResponse():
|
| - """
|
| - Get the initial client response, if defined for this mechanism.
|
| -
|
| - @return: initial client response string.
|
| - @rtype: L{str}.
|
| - """
|
| -
|
| -
|
| - def getResponse(challenge):
|
| - """
|
| - Get the response to a server challenge.
|
| -
|
| - @param challenge: server challenge.
|
| - @type challenge: L{str}.
|
| - @return: client response.
|
| - @rtype: L{str}.
|
| - """
|
| -
|
| -
|
| -
|
| -class Plain(object):
|
| - """
|
| - Implements the PLAIN SASL authentication mechanism.
|
| -
|
| - The PLAIN SASL authentication mechanism is defined in RFC 2595.
|
| - """
|
| - implements(ISASLMechanism)
|
| -
|
| - name = 'PLAIN'
|
| -
|
| - def __init__(self, authzid, authcid, password):
|
| - self.authzid = authzid or ''
|
| - self.authcid = authcid or ''
|
| - self.password = password or ''
|
| -
|
| -
|
| - def getInitialResponse(self):
|
| - return "%s\x00%s\x00%s" % (self.authzid.encode('utf-8'),
|
| - self.authcid.encode('utf-8'),
|
| - self.password.encode('utf-8'))
|
| -
|
| -
|
| -
|
| -class DigestMD5(object):
|
| - """
|
| - Implements the DIGEST-MD5 SASL authentication mechanism.
|
| -
|
| - The DIGEST-MD5 SASL authentication mechanism is defined in RFC 2831.
|
| - """
|
| - implements(ISASLMechanism)
|
| -
|
| - name = 'DIGEST-MD5'
|
| -
|
| - def __init__(self, serv_type, host, serv_name, username, password):
|
| - self.username = username
|
| - self.password = password
|
| - self.defaultRealm = host
|
| -
|
| - self.digest_uri = '%s/%s' % (serv_type, host)
|
| - if serv_name is not None:
|
| - self.digest_uri += '/%s' % serv_name
|
| -
|
| -
|
| - def getInitialResponse(self):
|
| - return None
|
| -
|
| -
|
| - def getResponse(self, challenge):
|
| - directives = self._parse(challenge)
|
| -
|
| - # Compat for implementations that do not send this along with
|
| - # a succesful authentication.
|
| - if 'rspauth' in directives:
|
| - return ''
|
| -
|
| - try:
|
| - realm = directives['realm']
|
| - except KeyError:
|
| - realm = self.defaultRealm
|
| -
|
| - return self._gen_response(directives['charset'],
|
| - realm,
|
| - directives['nonce'])
|
| -
|
| - def _parse(self, challenge):
|
| - """
|
| - Parses the server challenge.
|
| -
|
| - Splits the challenge into a dictionary of directives with values.
|
| -
|
| - @return: challenge directives and their values.
|
| - @rtype: L{dict} of L{str} to L{str}.
|
| - """
|
| - s = challenge
|
| - paramDict = {}
|
| - cur = 0
|
| - remainingParams = True
|
| - while remainingParams:
|
| - # Parse a param. We can't just split on commas, because there can
|
| - # be some commas inside (quoted) param values, e.g.:
|
| - # qop="auth,auth-int"
|
| -
|
| - middle = s.index("=", cur)
|
| - name = s[cur:middle].lstrip()
|
| - middle += 1
|
| - if s[middle] == '"':
|
| - middle += 1
|
| - end = s.index('"', middle)
|
| - value = s[middle:end]
|
| - cur = s.find(',', end) + 1
|
| - if cur == 0:
|
| - remainingParams = False
|
| - else:
|
| - end = s.find(',', middle)
|
| - if end == -1:
|
| - value = s[middle:].rstrip()
|
| - remainingParams = False
|
| - else:
|
| - value = s[middle:end].rstrip()
|
| - cur = end + 1
|
| - paramDict[name] = value
|
| -
|
| - for param in ('qop', 'cipher'):
|
| - if param in paramDict:
|
| - paramDict[param] = paramDict[param].split(',')
|
| -
|
| - return paramDict
|
| -
|
| - def _unparse(self, directives):
|
| - """
|
| - Create message string from directives.
|
| -
|
| - @param directives: dictionary of directives (names to their values).
|
| - For certain directives, extra quotes are added, as
|
| - needed.
|
| - @type directives: L{dict} of L{str} to L{str}
|
| - @return: message string.
|
| - @rtype: L{str}.
|
| - """
|
| -
|
| - directive_list = []
|
| - for name, value in directives.iteritems():
|
| - if name in ('username', 'realm', 'cnonce',
|
| - 'nonce', 'digest-uri', 'authzid', 'cipher'):
|
| - directive = '%s="%s"' % (name, value)
|
| - else:
|
| - directive = '%s=%s' % (name, value)
|
| -
|
| - directive_list.append(directive)
|
| -
|
| - return ','.join(directive_list)
|
| -
|
| -
|
| - def _gen_response(self, charset, realm, nonce):
|
| - """
|
| - Generate response-value.
|
| -
|
| - Creates a response to a challenge according to section 2.1.2.1 of
|
| - RFC 2831 using the L{charset}, L{realm} and L{nonce} directives
|
| - from the challenge.
|
| - """
|
| -
|
| - def H(s):
|
| - return md5.new(s).digest()
|
| -
|
| - def HEX(n):
|
| - return binascii.b2a_hex(n)
|
| -
|
| - def KD(k, s):
|
| - return H('%s:%s' % (k, s))
|
| -
|
| - try:
|
| - username = self.username.encode(charset)
|
| - password = self.password.encode(charset)
|
| - except UnicodeError:
|
| - # TODO - add error checking
|
| - raise
|
| -
|
| - nc = '%08x' % 1 # TODO: support subsequent auth.
|
| - cnonce = self._gen_nonce()
|
| - qop = 'auth'
|
| -
|
| - # TODO - add support for authzid
|
| - a1 = "%s:%s:%s" % (H("%s:%s:%s" % (username, realm, password)),
|
| - nonce,
|
| - cnonce)
|
| - a2 = "AUTHENTICATE:%s" % self.digest_uri
|
| -
|
| - response = HEX( KD ( HEX(H(a1)),
|
| - "%s:%s:%s:%s:%s" % (nonce, nc,
|
| - cnonce, "auth", HEX(H(a2)))))
|
| -
|
| - directives = {'username': username,
|
| - 'realm' : realm,
|
| - 'nonce' : nonce,
|
| - 'cnonce' : cnonce,
|
| - 'nc' : nc,
|
| - 'qop' : qop,
|
| - 'digest-uri': self.digest_uri,
|
| - 'response': response,
|
| - 'charset': charset}
|
| -
|
| - return self._unparse(directives)
|
| -
|
| -
|
| - def _gen_nonce(self):
|
| - return md5.new("%s:%s:%s" % (str(random.random()) , str(time.gmtime()),str(os.getpid()))).hexdigest()
|
|
|