Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/twisted_8_1/twisted/words/protocols/jabber/sasl_mechanisms.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.words.test.test_jabbersaslmechanisms -*-
2 #
3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6 """
7 Protocol agnostic implementations of SASL authentication mechanisms.
8 """
9
10 import md5, binascii, random, time, os
11
12 from zope.interface import Interface, Attribute, implements
13
14 class ISASLMechanism(Interface):
15 name = Attribute("""Common name for the SASL Mechanism.""")
16
17 def getInitialResponse():
18 """
19 Get the initial client response, if defined for this mechanism.
20
21 @return: initial client response string.
22 @rtype: L{str}.
23 """
24
25
26 def getResponse(challenge):
27 """
28 Get the response to a server challenge.
29
30 @param challenge: server challenge.
31 @type challenge: L{str}.
32 @return: client response.
33 @rtype: L{str}.
34 """
35
36
37
38 class Plain(object):
39 """
40 Implements the PLAIN SASL authentication mechanism.
41
42 The PLAIN SASL authentication mechanism is defined in RFC 2595.
43 """
44 implements(ISASLMechanism)
45
46 name = 'PLAIN'
47
48 def __init__(self, authzid, authcid, password):
49 self.authzid = authzid or ''
50 self.authcid = authcid or ''
51 self.password = password or ''
52
53
54 def getInitialResponse(self):
55 return "%s\x00%s\x00%s" % (self.authzid.encode('utf-8'),
56 self.authcid.encode('utf-8'),
57 self.password.encode('utf-8'))
58
59
60
61 class DigestMD5(object):
62 """
63 Implements the DIGEST-MD5 SASL authentication mechanism.
64
65 The DIGEST-MD5 SASL authentication mechanism is defined in RFC 2831.
66 """
67 implements(ISASLMechanism)
68
69 name = 'DIGEST-MD5'
70
71 def __init__(self, serv_type, host, serv_name, username, password):
72 self.username = username
73 self.password = password
74 self.defaultRealm = host
75
76 self.digest_uri = '%s/%s' % (serv_type, host)
77 if serv_name is not None:
78 self.digest_uri += '/%s' % serv_name
79
80
81 def getInitialResponse(self):
82 return None
83
84
85 def getResponse(self, challenge):
86 directives = self._parse(challenge)
87
88 # Compat for implementations that do not send this along with
89 # a succesful authentication.
90 if 'rspauth' in directives:
91 return ''
92
93 try:
94 realm = directives['realm']
95 except KeyError:
96 realm = self.defaultRealm
97
98 return self._gen_response(directives['charset'],
99 realm,
100 directives['nonce'])
101
102 def _parse(self, challenge):
103 """
104 Parses the server challenge.
105
106 Splits the challenge into a dictionary of directives with values.
107
108 @return: challenge directives and their values.
109 @rtype: L{dict} of L{str} to L{str}.
110 """
111 s = challenge
112 paramDict = {}
113 cur = 0
114 remainingParams = True
115 while remainingParams:
116 # Parse a param. We can't just split on commas, because there can
117 # be some commas inside (quoted) param values, e.g.:
118 # qop="auth,auth-int"
119
120 middle = s.index("=", cur)
121 name = s[cur:middle].lstrip()
122 middle += 1
123 if s[middle] == '"':
124 middle += 1
125 end = s.index('"', middle)
126 value = s[middle:end]
127 cur = s.find(',', end) + 1
128 if cur == 0:
129 remainingParams = False
130 else:
131 end = s.find(',', middle)
132 if end == -1:
133 value = s[middle:].rstrip()
134 remainingParams = False
135 else:
136 value = s[middle:end].rstrip()
137 cur = end + 1
138 paramDict[name] = value
139
140 for param in ('qop', 'cipher'):
141 if param in paramDict:
142 paramDict[param] = paramDict[param].split(',')
143
144 return paramDict
145
146 def _unparse(self, directives):
147 """
148 Create message string from directives.
149
150 @param directives: dictionary of directives (names to their values).
151 For certain directives, extra quotes are added, as
152 needed.
153 @type directives: L{dict} of L{str} to L{str}
154 @return: message string.
155 @rtype: L{str}.
156 """
157
158 directive_list = []
159 for name, value in directives.iteritems():
160 if name in ('username', 'realm', 'cnonce',
161 'nonce', 'digest-uri', 'authzid', 'cipher'):
162 directive = '%s="%s"' % (name, value)
163 else:
164 directive = '%s=%s' % (name, value)
165
166 directive_list.append(directive)
167
168 return ','.join(directive_list)
169
170
171 def _gen_response(self, charset, realm, nonce):
172 """
173 Generate response-value.
174
175 Creates a response to a challenge according to section 2.1.2.1 of
176 RFC 2831 using the L{charset}, L{realm} and L{nonce} directives
177 from the challenge.
178 """
179
180 def H(s):
181 return md5.new(s).digest()
182
183 def HEX(n):
184 return binascii.b2a_hex(n)
185
186 def KD(k, s):
187 return H('%s:%s' % (k, s))
188
189 try:
190 username = self.username.encode(charset)
191 password = self.password.encode(charset)
192 except UnicodeError:
193 # TODO - add error checking
194 raise
195
196 nc = '%08x' % 1 # TODO: support subsequent auth.
197 cnonce = self._gen_nonce()
198 qop = 'auth'
199
200 # TODO - add support for authzid
201 a1 = "%s:%s:%s" % (H("%s:%s:%s" % (username, realm, password)),
202 nonce,
203 cnonce)
204 a2 = "AUTHENTICATE:%s" % self.digest_uri
205
206 response = HEX( KD ( HEX(H(a1)),
207 "%s:%s:%s:%s:%s" % (nonce, nc,
208 cnonce, "auth", HEX(H(a2)))))
209
210 directives = {'username': username,
211 'realm' : realm,
212 'nonce' : nonce,
213 'cnonce' : cnonce,
214 'nc' : nc,
215 'qop' : qop,
216 'digest-uri': self.digest_uri,
217 'response': response,
218 'charset': charset}
219
220 return self._unparse(directives)
221
222
223 def _gen_nonce(self):
224 return md5.new("%s:%s:%s" % (str(random.random()) , str(time.gmtime()),s tr(os.getpid()))).hexdigest()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698