| Log note : add my name in case anyone wants to blame Richard for this. |
changed: - The following example is used to login to Roundup via a Windows NT authentication process. This extension uses Windows SSPI services to enable the authentication process. To validate a user in a Windows Domain Controller use this service along with the NTLM protocol. You will need the <a href="http://sourceforge.net/projects/pywin32/">pywin32</a> extension. Try to install a current one as the SSPI services weren't added until recently (sometime in 2005). I know that version 205 already has it. This example is just a mix of LDAPLogin published in this wiki and the code in 'validate.py' that's included in pywin32 library. User profiles are also stored in Roundup database, to minimize code modifications. Also: - user can also be stored and authenticated only internally into Roundup database. - user's profile are not automatically created (I took it off just to simplify this code). In your 'extensions' directory, create a file 'sspilogin.py' with:: import win32security from sspi import ClientAuth, ServerAuth from roundup.cgi.actions import LoginAction from roundup.i18n import _ class SSPIloginAction(LoginAction): # parameters for NTLM authentication. domain = "" pkg_name = "NTLM" def verifyLocalPassword(self, password): ''' Verify the password that the user has supplied ''' stored = self.db.user.get(self.client.userid, 'password') if password == stored: return 1 if not password and not stored: return 1 return 0 def local_login (self, password): ''' Local authentication ''' # make sure the user exists try: self.client.userid = self.db.user.lookup(self.client.user) except KeyError: self.client.error_message.append(_('Unknown user "%s"')%self.client.user) return 0 # verify the password if not self.verifyLocalPassword(password): self.client.error_message.append(_('Invalid password')) return 0 return 1 def sspi_login (self, password): ''' Authentication via Windows SSPI ''' try: auth_info = self.client.user, self.domain, password ca = ClientAuth(self.pkg_name, auth_info = auth_info) sa = ServerAuth(self.pkg_name) data = err = None while err != 0: err, data = ca.authorize(data) err, data = sa.authorize(data) # If we get here without exception, we worked! except win32security.error, details: hr, func, msg = details self.client.error_message.append (_('Unknown SSPI account "%s"')% self.client.user) self.client.error_message.append (_('SSPIError = %s (%d)"') % (msg, hr)) return 0 return 1 def verifyLogin(self, username, password): # try to login throught SSPI or with local account sspi_ok = None if not self.local_login(password): sspi_ok = self.sspi_login(password) if not sspi_ok: self.client.make_user_anonymous () return self.client.error_message = [] # reload user profile try: self.client.userid = self.db.user.lookup(self.client.user) except: self.client.make_user_anonymous() self.client.error_message.append(_("No account created without SSPI account")) return def init(instance): instance.registerAction('login', SSPIloginAction) You only need to specify the Windows Domain of your users in case Roundup is not running in a server that belongs to this same domain. Otherwise leave it blank. Regards, -Hernan. (hfoffani@gmail.com)