Package flumotion :: Package twisted :: Module credentials
[hide private]

Source Code for Module flumotion.twisted.credentials

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_credentials -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """ 
 23  Flumotion Twisted credentials 
 24  """ 
 25   
 26  import crypt 
 27  import md5 
 28   
 29  import random 
 30   
 31  from flumotion.common import log 
 32  from twisted.cred import credentials 
 33  from flumotion.twisted.compat import implements 
 34   
35 -class Username:
36 """ 37 I am your average username and password credentials. 38 """ 39 implements(credentials.IUsernamePassword)
40 - def __init__(self, username, password=''):
41 self.username = username 42 self.password = password
43
44 - def checkPassword(self, password):
45 return password == self.password
46
47 -class IUsernameCryptPassword(credentials.ICredentials):
48 """ 49 I encapsulate a username and check crypted passwords. 50 51 This credential interface is used when a crypt password is received 52 from the party requesting authentication. 53 CredentialCheckers which check this kind of credential must store 54 the passwords in plaintext or crypt form. 55 56 @type username: C{str} 57 @ivar username: The username associated with these credentials. 58 """ 59
60 - def checkCryptPassword(self, cryptPassword):
61 """ 62 Validate these credentials against the correct crypt password. 63 64 @param cryptPassword: The correct, crypt password against which to 65 check. 66 67 @return: a deferred which becomes, or a boolean indicating if the 68 password matches. 69 """
70
71 -class UsernameCryptPasswordPlaintext:
72 """ 73 I take a username and a plaintext password. 74 I implement IUsernameCryptPassword. 75 """ 76 77 implements(IUsernameCryptPassword)
78 - def __init__(self, username, password):
79 self.username = username 80 self.password = password
81
82 - def checkCryptPassword(self, cryptPassword):
83 """Check credentials against the given cryptPassword.""" 84 salt = cryptPassword[:2] 85 encrypted = crypt.crypt(self.password, salt) 86 return encrypted == cryptPassword
87
88 -class UsernameCryptPasswordCrypt:
89 """ 90 I take a username and a crypt password. 91 When using me you should make sure the password was crypted with the 92 correct salt (which is stored in the crypt password backend of whatever 93 checker you use); otherwise your password may be a valid crypt, but 94 with a different salt. 95 I implement IUsernameCryptPassword. 96 """ 97 98 implements(IUsernameCryptPassword)
99 - def __init__(self, username, cryptPassword=None):
100 self.username = username 101 self.cryptPassword = cryptPassword
102
103 - def setPasswordSalt(self, password, salt):
104 """ 105 Given the plaintext password and the salt, 106 set the correct cryptPassword. 107 """ 108 assert len(salt) == 2 109 110 self.cryptPassword = crypt.crypt(password, salt)
111
112 - def checkCryptPassword(self, cryptPassword):
113 """ 114 Check credentials against the given cryptPassword. 115 """ 116 return self.cryptPassword == cryptPassword
117
118 -def cryptRespond(challenge, cryptPassword):
119 """ 120 Respond to a given crypt challenge with our cryptPassword. 121 """ 122 import md5 123 md = md5.new() 124 md.update(cryptPassword) 125 md.update(challenge) 126 return md.digest()
127
128 -def dataToHex(data):
129 """ 130 Take a string of bytes, and return a string of two-digit hex values. 131 """ 132 l = [] 133 for c in data: 134 l.append("%02x" % ord(c)) 135 return "".join(l)
136 137 # copied from twisted.spread.pb.challenge()
138 -def cryptChallenge():
139 """ 140 I return some random data. 141 """ 142 crap = '' 143 for x in range(random.randrange(15,25)): 144 crap = crap + chr(random.randint(65,90) + x - x) # pychecker madness 145 crap = md5.new(crap).digest() 146 return crap
147
148 -class UsernameCryptPasswordCryptChallenger:
149 """ 150 I take a username. 151 152 Authenticator will give me a salt and challenge me. 153 Requester will respond to the challenge. 154 At that point I'm ready to be used by a checker. 155 The response function used is 156 L{flumotion.twisted.credentials.cryptRespond()} 157 158 I implement IUsernameCryptPassword. 159 """ 160 161 implements(IUsernameCryptPassword) 162
163 - def __init__(self, username):
164 self.username = username 165 self.salt = None # set by authenticator 166 self.challenge = None # set by authenticator 167 self.response = None # set by requester
168
169 - def setPassword(self, password):
170 """ 171 I encode a given plaintext password using the salt, and respond 172 to the challenge. 173 """ 174 assert self.salt 175 assert self.challenge 176 assert len(self.salt) == 2 177 cryptPassword = crypt.crypt(password, self.salt) 178 self.response = cryptRespond(self.challenge, cryptPassword)
179
180 - def checkCryptPassword(self, cryptPassword):
181 """ 182 Check credentials against the given cryptPassword. 183 """ 184 if not self.response: 185 return False 186 187 expected = cryptRespond(self.challenge, cryptPassword) 188 return self.response == expected
189
190 -class IToken(credentials.ICredentials):
191 """I encapsulate a token. 192 193 This credential is used when a token is received from the 194 party requesting authentication. 195 196 @type token: C{str} 197 @ivar token: The token associated with these credentials. 198 """
199
200 -class Token:
201 implements(IToken) 202
203 - def __init__(self, token):
204 self.token = token
205
206 -class IUsernameSha256Password(credentials.ICredentials):
207 """ 208 I encapsulate a username and check SHA-256 passwords. 209 210 This credential interface is used when a SHA-256 algorithm is used 211 on the password by the party requesting authentication.. 212 CredentialCheckers which check this kind of credential must store 213 the passwords in plaintext or SHA-256 form. 214 215 @type username: C{str} 216 @ivar username: The username associated with these credentials. 217 """ 218
219 - def checkSha256Password(self, sha256Password):
220 """ 221 Validate these credentials against the correct SHA-256 password. 222 223 @param sha256Password: The correct SHA-256 password against which to 224 check. 225 226 @return: a deferred which becomes, or a boolean indicating if the 227 password matches. 228 """
229 230 # our Sha256 passwords are salted; 231 # ie the password string is salt + dataToHex(SHA256 digest(salt + password))
232 -class UsernameSha256PasswordCryptChallenger:
233 """ 234 I take a username. 235 236 Authenticator will give me a salt and challenge me. 237 Requester will respond to the challenge. 238 At that point I'm ready to be used by a checker. 239 The response function used is 240 L{flumotion.twisted.credentials.cryptRespond()} 241 242 I implement IUsernameSha256Password. 243 """ 244 245 implements(IUsernameSha256Password) 246
247 - def __init__(self, username):
248 self.username = username 249 self.salt = None # set by authenticator 250 self.challenge = None # set by authenticator 251 self.response = None # set by requester
252
253 - def setPassword(self, password):
254 """ 255 I encode a given plaintext password using the salt, and respond 256 to the challenge. 257 """ 258 assert self.salt 259 assert self.challenge 260 from Crypto.Hash import SHA256 261 hasher = SHA256.new() 262 hasher.update(self.salt) 263 hasher.update(password) 264 sha256Password = self.salt + dataToHex(hasher.digest()) 265 self.response = cryptRespond(self.challenge, sha256Password)
266
267 - def checkSha256Password(self, sha256Password):
268 """ 269 Check credentials against the given sha256Password. 270 """ 271 if not self.response: 272 return False 273 274 expected = cryptRespond(self.challenge, sha256Password) 275 return self.response == expected
276