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  __revision__="$Id: plain.py 714 2010-04-05 10:20:10Z jajcus $" 
 24  __docformat__="restructuredtext en" 
 25   
 26  import logging 
 27   
 28  from pyxmpp.utils import to_utf8,from_utf8 
 29  from pyxmpp.sasl.core import ClientAuthenticator,ServerAuthenticator 
 30  from pyxmpp.sasl.core import Success,Failure,Challenge,Response 
 31   
32 -class PlainClientAuthenticator(ClientAuthenticator):
33 """Provides PLAIN SASL authentication for a client.""" 34
35 - def __init__(self,password_manager):
36 """Initialize a `PlainClientAuthenticator` object. 37 38 :Parameters: 39 - `password_manager`: name of the password manager object providing 40 authentication credentials. 41 :Types: 42 - `password_manager`: `PasswordManager`""" 43 ClientAuthenticator.__init__(self,password_manager) 44 self.username=None 45 self.finished=None 46 self.password=None 47 self.authzid=None 48 self.__logger=logging.getLogger("pyxmpp.sasl.PlainClientAuthenticator")
49
50 - def start(self,username,authzid):
51 """Start the authentication process and return the initial response. 52 53 :Parameters: 54 - `username`: username (authentication id). 55 - `authzid`: authorization id. 56 :Types: 57 - `username`: `unicode` 58 - `authzid`: `unicode` 59 60 :return: the initial response or a failure indicator. 61 :returntype: `sasl.Response` or `sasl.Failure`""" 62 self.username=username 63 if authzid: 64 self.authzid=authzid 65 else: 66 self.authzid="" 67 self.finished=0 68 return self.challenge("")
69
70 - def challenge(self, challenge):
71 """Process the challenge and return the response. 72 73 :Parameters: 74 - `challenge`: the challenge. 75 :Types: 76 - `challenge`: `str` 77 78 :return: the response or a failure indicator. 79 :returntype: `sasl.Response` or `sasl.Failure`""" 80 _unused = challenge 81 if self.finished: 82 self.__logger.debug("Already authenticated") 83 return Failure("extra-challenge") 84 self.finished=1 85 if self.password is None: 86 self.password,pformat=self.password_manager.get_password(self.username) 87 if not self.password or pformat!="plain": 88 self.__logger.debug("Couldn't retrieve plain password") 89 return Failure("password-unavailable") 90 return Response("%s\000%s\000%s" % ( to_utf8(self.authzid), 91 to_utf8(self.username), 92 to_utf8(self.password)))
93
94 - def finish(self,data):
95 """Handle authentication succes information from the server. 96 97 :Parameters: 98 - `data`: the optional additional data returned with the success. 99 :Types: 100 - `data`: `str` 101 102 :return: a success indicator. 103 :returntype: `Success`""" 104 _unused = data 105 return Success(self.username,None,self.authzid)
106
107 -class PlainServerAuthenticator(ServerAuthenticator):
108 """Provides PLAIN SASL authentication for a server.""" 109
110 - def __init__(self,password_manager):
111 """Initialize a `PlainServerAuthenticator` object. 112 113 :Parameters: 114 - `password_manager`: name of the password manager object providing 115 authentication credential verification. 116 :Types: 117 - `password_manager`: `PasswordManager`""" 118 ServerAuthenticator.__init__(self,password_manager) 119 self.__logger=logging.getLogger("pyxmpp.sasl.PlainServerAuthenticator")
120
121 - def start(self,response):
122 """Start the authentication process. 123 124 :Parameters: 125 - `response`: the initial response from the client. 126 :Types: 127 - `response`: `str` 128 129 :return: a challenge, a success indicator or a failure indicator. 130 :returntype: `sasl.Challenge`, `sasl.Success` or `sasl.Failure`""" 131 if not response: 132 return Challenge("") 133 return self.response(response)
134
135 - def response(self,response):
136 """Process a client reponse. 137 138 :Parameters: 139 - `response`: the response from the client. 140 :Types: 141 - `response`: `str` 142 143 :return: a challenge, a success indicator or a failure indicator. 144 :returntype: `sasl.Challenge`, `sasl.Success` or `sasl.Failure`""" 145 s=response.split("\000") 146 if len(s)!=3: 147 self.__logger.debug("Bad response: %r" % (response,)) 148 return Failure("not-authorized") 149 authzid,username,password=s 150 authzid=from_utf8(authzid) 151 username=from_utf8(username) 152 password=from_utf8(password) 153 if not self.password_manager.check_password(username,password): 154 self.__logger.debug("Bad password. Response was: %r" % (response,)) 155 return Failure("not-authorized") 156 info={"mechanism":"PLAIN","username":username} 157 if self.password_manager.check_authzid(authzid,info): 158 return Success(username,None,authzid) 159 else: 160 self.__logger.debug("Authzid verification failed.") 161 return Failure("invalid-authzid")
162 163 # vi: sts=4 et sw=4 164