Changeset 467

Show
Ignore:
Timestamp:
03/05/03 00:41:51 (6 years ago)
Author:
sholloway
Message:

*** empty log message ***

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/RBMessaging/RBMessaging/Client/Handlers/Authentication.py

    r466 r467  
    8989        else: return OnAuthType(packet, *args, **kw) 
    9090 
    91     def AuthorizeAs(self, loginaddr, bShort=True): 
     91    def AuthorizeAs(self, loginaddr, kind="response"): 
    9292        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) 
    9794 
    9895    def SendPacket(self, packet, *args, **kw): 
     
    110107 
    111108    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
    117114 
    118115    def _type_options(self, packet, *args, **kw): 
     116        print "Available Authentication Types:", [method.type_ for method in packet['method',]] 
    119117        self._reply_select(packet, *args, **kw) 
    120118 
    121119    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) 
    130131 
    131132    def _type_challenge(self, packet, *args, **kw): 
     
    133134 
    134135    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) 
    139140 
    140141        if sendkey: 
    141142            # Use PublicKey 
    142             packet += AuthenticationMethods.RSAPublicKey() 
    143             packet[-1].Sign(sendkey, 'password') 
     143            response += AuthenticationMethods.RSAPublicKey() 
     144            response[-1].Sign(sendkey, 'password') 
    144145        else: 
    145             packet += AuthenticationMethods.SHAHash() 
    146             packet[-1].Sign('secret', 'password') 
     146            response += AuthenticationMethods.SHAHash() 
     147            response[-1].Sign('secret', 'password') 
    147148 
    148         self.SendPacket(packet
     149        self.SendPacket(response
    149150 
    150151    def _type_success(self, packet, *args, **kw): 
     
    155156 
    156157    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) 
    161162 
    162163        if sendkey: 
    163164            # Use PublicKey 
    164             packet += AuthenticationMethods.RSAPublicKey() 
    165             packet[-1].Sign(sendkey, 'password') 
     165            response += AuthenticationMethods.RSAPublicKey() 
     166            response[-1].Sign(sendkey, 'password') 
    166167        else: 
    167             packet += AuthenticationMethods.SHAHash() 
    168             packet[-1].Sign('secret', 'password') 
     168            response += AuthenticationMethods.SHAHash() 
     169            response[-1].Sign('secret', 'password') 
    169170 
    170         self.SendPacket(packet
     171        self.SendPacket(response
    171172 
  • trunk/RBMessaging/RBMessaging/Host/Handlers/Authentication.py

    r466 r467  
    3838        }) 
    3939 
     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 
    4071#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4172 
     
    75106        raise ErrorTypes.AuthenticationError('Authentication data not available') 
    76107 
     108    def _GetOptions(self, packet, subkey='method'): 
     109        try: 
     110            MethodFactory = packet.ElementFactories[subkey] 
     111            return MethodFactory.GetAvailableMethod() 
     112        except KeyError: 
     113            return () 
     114 
    77115    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    78116    #~ Protected Methods  
     
    86124 
    87125    def _reply_options(self, packet, *args, **kw): 
    88         raise NotImplementedError 
    89126        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() 
    93129        self.SendPacket(packet) 
    94130 
     
    97133 
    98134    def _reply_challenge(self, packet, *args, **kw): 
     135        """Sends a challenge to the client based upon the selected method(s).""" 
     136        as_ = packet.as_ 
    99137        packet.attrs['type'] = 'challenge' 
     138        for method in packet.iternodes('method'): 
     139            method.SetChallenge(self, as_.addr) 
    100140        self.SendPacket(packet) 
    101141 
    102142    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 
    110146        try: 
    111147            if method.Verify(self, as_.addr): 
     
    114150            else: 
    115151                self.connection.OnAuthenticated(False, as_.addr) 
    116                 raise ErrorTypes.AuthenticationError('Invalid authentication') 
    117152        except ErrorTypes.AuthenticationError, err: 
    118153            self.connection.OnAuthenticated(False, as_.addr) 
    119154            raise 
     155        raise ErrorTypes.AuthenticationError('Invalid authentication') 
    120156 
    121157    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.""" 
    123161        try: 
    124162            result = self._type_answer(packet, *args, **kw) 
     
    134172 
    135173    def _reply_success(self, packet, *args, **kw): 
     174        """Signals an authentication success to the client""" 
    136175        packet.delnodes('method') 
    137176        packet.attrs['type'] = 'success' 
     
    139178 
    140179    def _reply_failure(self, packet, *args, **kw): 
     180        """Signals an authentication failure to the client""" 
    141181        packet.delnodes('method') 
    142182        packet.attrs['type'] = 'failure' 
  • trunk/RBMessaging/RBMessaging/Packet/AuthenticationMethods.py

    r466 r467  
    2020##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    2121 
    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  
    2822#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    2923#~ Imports  
     
    4943        }) 
    5044    default_node = 'method' 
     45    nodebuilder = Elements.LeafElement 
    5146 
    5247    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    5348    #~ Properties  
    5449    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     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_) 
    5559 
    5660    def _get_challenge(self): 
     
    6064        elif len(challenge) == 1: 
    6165            challenge = ''.join(map(str, challenge[0].iterdata())) 
    62         else: challenge = None 
     66        else: challenge = '' 
    6367        return challenge 
    6468    def _set_challenge(self, challenge): 
    6569        self.delnodes('challenge') 
    6670        self.addnode('challenge').adddata(challenge) 
    67     def _del_challenge(self, challenge): 
     71    def _del_challenge(self): 
    6872        self.delnodes('challenge') 
    6973    challenge = property(_get_challenge, _set_challenge, _del_challenge) 
     
    7983    def _set_response(self, response): 
    8084        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): 
    8388        self.delnodes('response') 
    8489    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 
     106try: 
     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'),) 
     127except ImportError:  
     128    pass 
     129else:  
     130    AvailableMethods[None] = UnknownOrInvalid 
    85131 
    86132#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    104150            if challenge is not None: 
    105151                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') 
    108164            return result 
    109165except ImportError:  
     
    129185 
    130186        def Sign(self, reponse, challenge='password'): 
     187            self.response = response  
    131188            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 
    134196            password = handler.GetAccountData(asaddr, self.challenge or 'password') 
    135197            return self.response == password  
     
    159221            self.challenge = challenge 
    160222            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 
    162230            password = handler.GetAccountData(asaddr, 'md5-password', 'password') 
    163231            correct = md5.new(password + self.challenge).hexdigest() 
     
    168236    default_type = MD5Hash.default_attributes['type'] 
    169237    AvailableMethods[default_type] = MD5Hash 
    170     AvailableMethods['md5'] = MD5Hash 
    171238 
    172239#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    189256            self.challenge = challenge 
    190257            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 
    192265            password = handler.GetAccountData(asaddr, 'sha-password', 'password') 
    193266            correct = sha.new(password + self.challenge).hexdigest() 
     
    198271    default_type = SHAHash.default_attributes['type'] 
    199272    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 
     276try: 
     277    import Crypto.PublicKey 
     278    class PublicKey(AuthenticationBaseMethod): 
     279        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     280        #~ Constants / Variables / Etc.  
     281        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     282 
     283        __slots__ = [] 
     284        default_attributes = {'type':'publickey'} 
    213285 
    214286        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    219291            self.challenge = challenge 
    220292            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') 
    223301            signature = long(self.response) 
    224302            return key.verify(self.challenge, (signature,)) 
     
    226304    pass 
    227305else: 
    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 
    258308 
    259309#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    267317 
    268318    __slots__ = [] 
    269     AuthMethodTable = AvailableMethods.copy() 
     319    MethodTable = AvailableMethods.copy() 
    270320 
    271321    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    272322    #~ Public Methods  
    273323    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     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] 
    274328 
    275329    def BuildNode(self, owner, parent, node, attributes, namespacemap, *args, **kw): 
    276330        try: 
    277331            type_ = attributes['type'] 
    278             kw['nodebuilder'] = self.AuthMethodTable[type_] 
     332            kw['nodebuilder'] = self.MethodTable[type_] 
    279333        except KeyError:  
    280             pass 
     334            try: kw['nodebuilder'] = self.MethodTable[None] 
     335            except KeyError: pass 
    281336        return self.xmladaptor(owner, parent, node, attributes, namespacemap, *args, **kw) 
    282337