Package pyxmpp :: Package sasl :: Module plain
[hide private]

Source Code for Module pyxmpp.sasl.plain

  1  # 
  2  # (C) Copyright 2003-2010 Jacek Konieczny <jajcus@jajcus.net> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU Lesser General Public License Version 
  6  # 2.1 as published by the Free Software Foundation. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 11  # GNU Lesser General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU Lesser General Public 
 14  # License along with this program; if not, write to the Free Software 
 15  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 16  # 
 17  """PLAIN authentication mechanism for PyXMPP SASL implementation. 
 18   
 19  Normative reference: 
 20    - `RFC 2595 <http://www.ietf.org/rfc/rfc2595.txt>`__ 
 21  """ 
 22   
 23  __docformat__="restructuredtext en" 
 24   
 25  import logging 
 26   
 27  from pyxmpp.utils import to_utf8,from_utf8 
 28  from pyxmpp.sasl.core import ClientAuthenticator,ServerAuthenticator 
 29  from pyxmpp.sasl.core import Success,Failure,Challenge,Response 
 30   
31 -class PlainClientAuthenticator(ClientAuthenticator):
32 """Provides PLAIN SASL authentication for a client.""" 33
34 - def __init__(self,password_manager):
35 """Initialize a `PlainClientAuthenticator` object. 36 37 :Parameters: 38 - `password_manager`: name of the password manager object providing 39 authentication credentials. 40 :Types: 41 - `password_manager`: `PasswordManager`""" 42 ClientAuthenticator.__init__(self,password_manager) 43 self.username=None 44 self.finished=None 45 self.password=None 46 self.authzid=None 47 self.__logger=logging.getLogger("pyxmpp.sasl.PlainClientAuthenticator")
48
49 - def start(self,username,authzid):
50 """Start the authentication process and return the initial response. 51 52 :Parameters: 53 - `username`: username (authentication id). 54 - `authzid`: authorization id. 55 :Types: 56 - `username`: `unicode` 57 - `authzid`: `unicode` 58 59 :return: the initial response or a failure indicator. 60 :returntype: `sasl.Response` or `sasl.Failure`""" 61 self.username=username 62 if authzid: 63 self.authzid=authzid 64 else: 65 self.authzid="" 66 self.finished=0 67 return self.challenge("")
68
69 - def challenge(self, challenge):
70 """Process the challenge and return the response. 71 72 :Parameters: 73 - `challenge`: the challenge. 74 :Types: 75 - `challenge`: `str` 76 77 :return: the response or a failure indicator. 78 :returntype: `sasl.Response` or `sasl.Failure`""" 79 _unused = challenge 80 if self.finished: 81 self.__logger.debug("Already authenticated") 82 return Failure("extra-challenge") 83 self.finished=1 84 if self.password is None: 85 self.password,pformat=self.password_manager.get_password(self.username) 86 if not self.password or pformat!="plain": 87 self.__logger.debug("Couldn't retrieve plain password") 88 return Failure("password-unavailable") 89 return Response("%s\000%s\000%s" % ( to_utf8(self.authzid), 90 to_utf8(self.username), 91 to_utf8(self.password)))
92
93 - def finish(self,data):
94 """Handle authentication succes information from the server. 95 96 :Parameters: 97 - `data`: the optional additional data returned with the success. 98 :Types: 99 - `data`: `str` 100 101 :return: a success indicator. 102 :returntype: `Success`""" 103 _unused = data 104 return Success(self.username,None,self.authzid)
105
106 -class PlainServerAuthenticator(ServerAuthenticator):
107 """Provides PLAIN SASL authentication for a server.""" 108
109 - def __init__(self,password_manager):
110 """Initialize a `PlainServerAuthenticator` object. 111 112 :Parameters: 113 - `password_manager`: name of the password manager object providing 114 authentication credential verification. 115 :Types: 116 - `password_manager`: `PasswordManager`""" 117 ServerAuthenticator.__init__(self,password_manager) 118 self.__logger=logging.getLogger("pyxmpp.sasl.PlainServerAuthenticator")
119
120 - def start(self,response):
121 """Start the authentication process. 122 123 :Parameters: 124 - `response`: the initial response from the client. 125 :Types: 126 - `response`: `str` 127 128 :return: a challenge, a success indicator or a failure indicator. 129 :returntype: `sasl.Challenge`, `sasl.Success` or `sasl.Failure`""" 130 if not response: 131 return Challenge("") 132 return self.response(response)
133
134 - def response(self,response):
135 """Process a client reponse. 136 137 :Parameters: 138 - `response`: the response from the client. 139 :Types: 140 - `response`: `str` 141 142 :return: a challenge, a success indicator or a failure indicator. 143 :returntype: `sasl.Challenge`, `sasl.Success` or `sasl.Failure`""" 144 s=response.split("\000") 145 if len(s)!=3: 146 self.__logger.debug("Bad response: %r" % (response,)) 147 return Failure("not-authorized") 148 authzid,username,password=s 149 authzid=from_utf8(authzid) 150 username=from_utf8(username) 151 password=from_utf8(password) 152 if not self.password_manager.check_password(username,password): 153 self.__logger.debug("Bad password. Response was: %r" % (response,)) 154 return Failure("not-authorized") 155 info={"mechanism":"PLAIN","username":username} 156 if self.password_manager.check_authzid(authzid,info): 157 return Success(username,None,authzid) 158 else: 159 self.__logger.debug("Authzid verification failed.") 160 return Failure("invalid-authzid")
161 162 # vi: sts=4 et sw=4 163