Changeset 467
- Timestamp:
- 03/05/03 00:41:51 (6 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/RBMessaging/RBMessaging/Client/Handlers/Authentication.py
r466 r467 89 89 else: return OnAuthType(packet, *args, **kw) 90 90 91 def AuthorizeAs(self, loginaddr, bShort=True):91 def AuthorizeAs(self, loginaddr, kind="response"): 92 92 self.loginaddr = URIAddress.URIAddress(loginaddr) 93 if bShort: 94 self._reply_response(None) 95 else: 96 self._reply_query(None) 93 getattr(self, '_reply_'+kind)(None) 97 94 98 95 def SendPacket(self, packet, *args, **kw): … … 110 107 111 108 def _reply_query(self, packet, *args, **kw): 112 packet= authentication()113 packet.attrs['type'] = 'query'114 packet+= 'as',115 packet[-1].attrs['addr'] = str(self.loginaddr)116 self.SendPacket( packet)109 response = authentication() 110 response.attrs['type'] = 'query' 111 response += 'as', 112 response[-1].attrs['addr'] = str(self.loginaddr) 113 self.SendPacket(response) 117 114 118 115 def _type_options(self, packet, *args, **kw): 116 print "Available Authentication Types:", [method.type_ for method in packet['method',]] 119 117 self._reply_select(packet, *args, **kw) 120 118 121 119 def _reply_select(self, packet, *args, **kw): 122 raise NotImplementedError 123 packet = authentication() 124 packet.attrs['type'] = 'select' 125 packet += 'as', 126 packet[-1].attrs['addr'] = str(self.loginaddr) 127 packet += AuthenticationMethods.AuthenticationBaseMethod() 128 packet[-1].attrs['type'] = 'plaintext' 129 self.SendPacket(packet) 120 #raise NotImplementedError 121 response = authentication() 122 response.attrs['type'] = 'select' 123 response += 'as', 124 response[-1].attrs['addr'] = str(self.loginaddr) 125 126 # Select method 127 response += AuthenticationMethods.AuthenticationBaseMethod() 128 response[-1].attrs['type'] = 'sha-hash' 129 130 self.SendPacket(response) 130 131 131 132 def _type_challenge(self, packet, *args, **kw): … … 133 134 134 135 def _reply_response(self, packet, *args, **kw): 135 packet= authentication()136 packet.attrs['type'] = 'response'137 packet+= 'as',138 packet[-1].attrs['addr'] = str(self.loginaddr)136 response = authentication() 137 response.attrs['type'] = 'response' 138 response += 'as', 139 response[-1].attrs['addr'] = str(self.loginaddr) 139 140 140 141 if sendkey: 141 142 # Use PublicKey 142 packet+= AuthenticationMethods.RSAPublicKey()143 packet[-1].Sign(sendkey, 'password')143 response += AuthenticationMethods.RSAPublicKey() 144 response[-1].Sign(sendkey, 'password') 144 145 else: 145 packet+= AuthenticationMethods.SHAHash()146 packet[-1].Sign('secret', 'password')146 response += AuthenticationMethods.SHAHash() 147 response[-1].Sign('secret', 'password') 147 148 148 self.SendPacket( packet)149 self.SendPacket(response) 149 150 150 151 def _type_success(self, packet, *args, **kw): … … 155 156 156 157 def _reply_answer(self, packet, *args, **kw): 157 packet= authentication()158 packet.attrs['type'] = 'answer'159 packet+= 'as',160 packet[-1].attrs['addr'] = str(self.loginaddr)158 response = authentication() 159 response.attrs['type'] = 'answer' 160 response += 'as', 161 response[-1].attrs['addr'] = str(self.loginaddr) 161 162 162 163 if sendkey: 163 164 # Use PublicKey 164 packet+= AuthenticationMethods.RSAPublicKey()165 packet[-1].Sign(sendkey, 'password')165 response += AuthenticationMethods.RSAPublicKey() 166 response[-1].Sign(sendkey, 'password') 166 167 else: 167 packet+= AuthenticationMethods.SHAHash()168 packet[-1].Sign('secret', 'password')168 response += AuthenticationMethods.SHAHash() 169 response[-1].Sign('secret', 'password') 169 170 170 self.SendPacket( packet)171 self.SendPacket(response) 171 172 trunk/RBMessaging/RBMessaging/Host/Handlers/Authentication.py
r466 r467 38 38 }) 39 39 40 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 #~ Public Methods 42 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 44 #~ type_ property ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 46 def _get_type_(self): 47 return self.attrs.get('type') 48 def _set_type_(self, value): 49 self.attrs['type'] = value 50 def _del_type_(self): 51 try: del self.attrs['type'] 52 except KeyError: pass 53 type_ = property(_get_type_, _set_type_, _del_type_) 54 55 #~ as_ property ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 56 57 def _get_as_(self): 58 try: return self['as',][0] 59 except (LookupError), e: 60 raise ErrorTypes.AuthenticationError('Did not find response "as" element') 61 as_ = property(_get_as_) 62 63 #~ method_ property ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 64 65 def _get_method(self): 66 try: return self['method',][0] 67 except (LookupError), e: 68 raise ErrorTypes.AuthenticationError('Did not find response "method" element') 69 method = property(_get_method) 70 40 71 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 72 … … 75 106 raise ErrorTypes.AuthenticationError('Authentication data not available') 76 107 108 def _GetOptions(self, packet, subkey='method'): 109 try: 110 MethodFactory = packet.ElementFactories[subkey] 111 return MethodFactory.GetAvailableMethod() 112 except KeyError: 113 return () 114 77 115 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78 116 #~ Protected Methods … … 86 124 87 125 def _reply_options(self, packet, *args, **kw): 88 raise NotImplementedError89 126 packet.attrs['type'] = 'options' 90 for authmethod in ('passkey', 'plaintext', 'md5-hash', 'sha-hash', 'publickey', 'radius'): 91 packet += AuthenticationMethods.AuthenticationBaseMethod() 92 packet[-1].attrs['type'] = authmethod 127 for authtype, authmethod in self._GetOptions(packet): 128 packet += authmethod() 93 129 self.SendPacket(packet) 94 130 … … 97 133 98 134 def _reply_challenge(self, packet, *args, **kw): 135 """Sends a challenge to the client based upon the selected method(s).""" 136 as_ = packet.as_ 99 137 packet.attrs['type'] = 'challenge' 138 for method in packet.iternodes('method'): 139 method.SetChallenge(self, as_.addr) 100 140 self.SendPacket(packet) 101 141 102 142 def _type_answer(self, packet, *args, **kw): 103 try: as_ = packet['as',][0] 104 except (LookupError), e: 105 raise ErrorTypes.AuthenticationError('Did not find response "as" element') 106 try: method = packet['method',][0] 107 except (LookupError), e: 108 raise ErrorTypes.AuthenticationError('Did not find response "method" element') 109 143 """Handles authentication answers: the actual authentication.""" 144 as_ = packet.as_ 145 method = packet.method 110 146 try: 111 147 if method.Verify(self, as_.addr): … … 114 150 else: 115 151 self.connection.OnAuthenticated(False, as_.addr) 116 raise ErrorTypes.AuthenticationError('Invalid authentication')117 152 except ErrorTypes.AuthenticationError, err: 118 153 self.connection.OnAuthenticated(False, as_.addr) 119 154 raise 155 raise ErrorTypes.AuthenticationError('Invalid authentication') 120 156 121 157 def _type_response(self, packet, *args, **kw): 122 """Like the "answer" packet type, only with a "success" or "failure" response.""" 158 """Handles authentication repsonses. 159 Uses _type_answer to do the authentication work, then additionally 160 sends a "success" or "failure" response.""" 123 161 try: 124 162 result = self._type_answer(packet, *args, **kw) … … 134 172 135 173 def _reply_success(self, packet, *args, **kw): 174 """Signals an authentication success to the client""" 136 175 packet.delnodes('method') 137 176 packet.attrs['type'] = 'success' … … 139 178 140 179 def _reply_failure(self, packet, *args, **kw): 180 """Signals an authentication failure to the client""" 141 181 packet.delnodes('method') 142 182 packet.attrs['type'] = 'failure' trunk/RBMessaging/RBMessaging/Packet/AuthenticationMethods.py
r466 r467 20 20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 21 22 """23 TODO: Implement challenge validity checking to prevent replay attacks.24 """25 26 print "TODO: Implement challenge validity checking to prevent replay attacks."27 28 22 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 23 #~ Imports … … 49 43 }) 50 44 default_node = 'method' 45 nodebuilder = Elements.LeafElement 51 46 52 47 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 48 #~ Properties 54 49 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 50 51 def _get_type_(self): 52 return self.attrs.get('type') 53 def _set_type_(self, value): 54 self.attrs['type'] = value 55 def _del_type_(self): 56 try: del self.attrs['type'] 57 except KeyError: pass 58 type_ = property(_get_type_, _set_type_, _del_type_) 55 59 56 60 def _get_challenge(self): … … 60 64 elif len(challenge) == 1: 61 65 challenge = ''.join(map(str, challenge[0].iterdata())) 62 else: challenge = None66 else: challenge = '' 63 67 return challenge 64 68 def _set_challenge(self, challenge): 65 69 self.delnodes('challenge') 66 70 self.addnode('challenge').adddata(challenge) 67 def _del_challenge(self , challenge):71 def _del_challenge(self): 68 72 self.delnodes('challenge') 69 73 challenge = property(_get_challenge, _set_challenge, _del_challenge) … … 79 83 def _set_response(self, response): 80 84 self.delnodes('response') 81 self.addnode('response').adddata(response) 82 def _del_response(self, response): 85 if response: 86 self.addnode('response').adddata(response) 87 def _del_response(self): 83 88 self.delnodes('response') 84 89 response = property(_get_response, _set_response, _del_response) 90 91 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 #~ Public Methods 93 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 94 95 def Sign(self, *args, **kw): 96 raise NotImplementedError 97 98 def SetChallenge(self, handler, asaddr): 99 raise NotImplementedError 100 101 def Verify(self, handler, asaddr): 102 raise NotImplementedError 103 104 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 106 try: 107 class UnknownOrInvalid(AuthenticationBaseMethod): 108 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 109 #~ Constants / Variables / Etc. 110 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111 112 __slots__ = [] 113 default_attributes = {'type': None} 114 115 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 116 #~ Public Methods 117 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 118 119 def Sign(self, *args, **kw): 120 raise ErrorTypes.AuthenticationError, 'Unknown or invalid authentication method type "%s".' % (self.attrs.get('type'),) 121 122 def SetChallenge(self, handler, asaddr): 123 raise ErrorTypes.AuthenticationError, 'Unknown or invalid authentication method type "%s".' % (self.attrs.get('type'),) 124 125 def Verify(self, handler, asaddr): 126 raise ErrorTypes.AuthenticationError, 'Unknown or invalid authentication method type "%s".' % (self.attrs.get('type'),) 127 except ImportError: 128 pass 129 else: 130 AvailableMethods[None] = UnknownOrInvalid 85 131 86 132 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 104 150 if challenge is not None: 105 151 self.challenge = challenge 106 def Verify(self, handler, asaddr): 107 result = handler.GetAccountData(asaddr, 'passkey:'+self.challenge) 152 153 def SetChallenge(self, handler, asaddr): 154 self.response = None 155 self.challenge = "passkey" 156 157 def Verify(self, handler, asaddr): 158 # TODO: Need to verify challenge is valid -- no reply attack 159 challenge = self.challenge or '' 160 if challenge: 161 result = handler.GetAccountData(asaddr, 'passkey:' + challenge) 162 else: 163 result = handler.GetAccountData(asaddr, 'passkey') 108 164 return result 109 165 except ImportError: … … 129 185 130 186 def Sign(self, reponse, challenge='password'): 187 self.response = response 131 188 self.challenge = challenge 132 self.response = response 133 def Verify(self, handler, asaddr): 189 190 def SetChallenge(self, handler, asaddr): 191 self.response = None 192 handler.__challenge = self.challenge = "password" 193 194 def Verify(self, handler, asaddr): 195 # TODO: Need to verify challenge is valid -- no reply attack 134 196 password = handler.GetAccountData(asaddr, self.challenge or 'password') 135 197 return self.response == password … … 159 221 self.challenge = challenge 160 222 self.response = md5.new(reponse + challenge).hexdigest() 161 def Verify(self, handler, asaddr): 223 224 def SetChallenge(self, handler, asaddr): 225 self.response = None 226 handler.__challenge = self.challenge = str(id(self) ^ id(handler)) 227 228 def Verify(self, handler, asaddr): 229 # TODO: Need to verify challenge is valid -- no reply attack 162 230 password = handler.GetAccountData(asaddr, 'md5-password', 'password') 163 231 correct = md5.new(password + self.challenge).hexdigest() … … 168 236 default_type = MD5Hash.default_attributes['type'] 169 237 AvailableMethods[default_type] = MD5Hash 170 AvailableMethods['md5'] = MD5Hash171 238 172 239 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 189 256 self.challenge = challenge 190 257 self.response = sha.new(reponse + challenge).hexdigest() 191 def Verify(self, handler, asaddr): 258 259 def SetChallenge(self, handler, asaddr): 260 self.response = None 261 handler.__challenge = self.challenge = str(id(self) ^ id(handler)) 262 263 def Verify(self, handler, asaddr): 264 # TODO: Need to verify challenge is valid -- no reply attack 192 265 password = handler.GetAccountData(asaddr, 'sha-password', 'password') 193 266 correct = sha.new(password + self.challenge).hexdigest() … … 198 271 default_type = SHAHash.default_attributes['type'] 199 272 AvailableMethods[default_type] = SHAHash 200 AvailableMethods['sha'] = SHAHash 201 202 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 203 204 try: 205 from Crypto.PublicKey import RSA 206 class RSAPublicKey(AuthenticationBaseMethod): 207 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 208 #~ Constants / Variables / Etc. 209 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 210 211 __slots__ = [] 212 default_attributes = {'type':'rsa-publickey'} 273 274 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 275 276 try: 277 import Crypto.PublicKey 278 class PublicKey(AuthenticationBaseMethod): 279 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 280 #~ Constants / Variables / Etc. 281 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 282 283 __slots__ = [] 284 default_attributes = {'type':'publickey'} 213 285 214 286 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 219 291 self.challenge = challenge 220 292 self.response = str(key.sign(self.challenge)[0]) 221 def Verify(self, handler, asaddr): 222 key = handler.GetAccountData(asaddr, 'rsa-publickey', 'publickey') 293 294 def SetChallenge(self, handler, asaddr): 295 self.response = None 296 handler.__challenge = self.challenge = str(id(self) ^ id(handler)) 297 298 def Verify(self, handler, asaddr): 299 # TODO: Need to verify challenge is valid -- no reply attack 300 key = handler.GetAccountData(asaddr, 'rsa-publickey', 'dsa-publickey', 'publickey') 223 301 signature = long(self.response) 224 302 return key.verify(self.challenge, (signature,)) … … 226 304 pass 227 305 else: 228 default_type = RSAPublicKey.default_attributes['type'] 229 AvailableMethods[default_type] = RSAPublicKey 230 AvailableMethods['publickey'] = RSAPublicKey 231 232 try: 233 from Crypto.PublicKey import DSA 234 class DSAPublicKey(AuthenticationBaseMethod): 235 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 236 #~ Constants / Variables / Etc. 237 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 238 239 __slots__ = [] 240 default_attributes = {'type':'dsa-publickey'} 241 242 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 243 #~ Public Methods 244 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 245 246 def Sign(self, key, challenge): 247 self.challenge = challenge 248 self.response = str(key.sign(self.challenge)[0]) 249 def Verify(self, handler, asaddr): 250 key = handler.GetAccountData(asaddr, 'dsa-publickey') 251 signature = long(self.response) 252 return key.verify(self.challenge, (signature,)) 253 except ImportError: 254 pass 255 else: 256 default_type = DSAPublicKey.default_attributes['type'] 257 AvailableMethods[default_type] = DSAPublicKey 306 default_type = PublicKey.default_attributes['type'] 307 AvailableMethods[default_type] = PublicKey 258 308 259 309 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 267 317 268 318 __slots__ = [] 269 AuthMethodTable = AvailableMethods.copy()319 MethodTable = AvailableMethods.copy() 270 320 271 321 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 272 322 #~ Public Methods 273 323 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 324 325 def GetAvailableMethod(self): 326 result = dict([(x.default_attributes.get('type'), x) for x in self.MethodTable.values()]) 327 return [x for x in result.items() if x[0] is not None] 274 328 275 329 def BuildNode(self, owner, parent, node, attributes, namespacemap, *args, **kw): 276 330 try: 277 331 type_ = attributes['type'] 278 kw['nodebuilder'] = self. AuthMethodTable[type_]332 kw['nodebuilder'] = self.MethodTable[type_] 279 333 except KeyError: 280 pass 334 try: kw['nodebuilder'] = self.MethodTable[None] 335 except KeyError: pass 281 336 return self.xmladaptor(owner, parent, node, attributes, namespacemap, *args, **kw) 282 337
