| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.test.test_strcred -*- | |
| 2 # | |
| 3 # Copyright (c) 2007-2008 Twisted Matrix Laboratories. | |
| 4 # See LICENSE for details. | |
| 5 | |
| 6 """ | |
| 7 Cred plugin for UNIX user accounts. | |
| 8 """ | |
| 9 | |
| 10 from zope.interface import implements | |
| 11 | |
| 12 from twisted import plugin | |
| 13 from twisted.cred.strcred import ICheckerFactory | |
| 14 from twisted.cred.checkers import ICredentialsChecker | |
| 15 from twisted.cred.credentials import IUsernamePassword | |
| 16 from twisted.cred.error import UnauthorizedLogin | |
| 17 from twisted.internet import defer | |
| 18 | |
| 19 | |
| 20 | |
| 21 def verifyCryptedPassword(crypted, pw): | |
| 22 if crypted[0] == '$': # md5_crypt encrypted | |
| 23 salt = '$1$' + crypted.split('$')[2] | |
| 24 else: | |
| 25 salt = crypted[:2] | |
| 26 try: | |
| 27 import crypt | |
| 28 except ImportError: | |
| 29 crypt = None | |
| 30 | |
| 31 if crypt is None: | |
| 32 raise NotImplementedError("cred_unix not supported on this platform") | |
| 33 return crypt.crypt(pw, salt) == crypted | |
| 34 | |
| 35 | |
| 36 | |
| 37 class UNIXChecker(object): | |
| 38 """ | |
| 39 A credentials checker for a UNIX server. This will check that | |
| 40 an authenticating username/password is a valid user on the system. | |
| 41 | |
| 42 Does not work on Windows. | |
| 43 | |
| 44 Right now this supports Python's pwd and spwd modules, if they are | |
| 45 installed. It does not support PAM. | |
| 46 """ | |
| 47 implements(ICredentialsChecker) | |
| 48 credentialInterfaces = (IUsernamePassword,) | |
| 49 | |
| 50 | |
| 51 def checkPwd(self, pwd, username, password): | |
| 52 try: | |
| 53 cryptedPass = pwd.getpwnam(username)[1] | |
| 54 except KeyError: | |
| 55 return defer.fail(UnauthorizedLogin()) | |
| 56 else: | |
| 57 if cryptedPass in ('*', 'x'): | |
| 58 # Allow checkSpwd to take over | |
| 59 return None | |
| 60 elif verifyCryptedPassword(cryptedPass, password): | |
| 61 return defer.succeed(username) | |
| 62 | |
| 63 | |
| 64 def checkSpwd(self, spwd, username, password): | |
| 65 try: | |
| 66 cryptedPass = spwd.getspnam(username)[1] | |
| 67 except KeyError: | |
| 68 return defer.fail(UnauthorizedLogin()) | |
| 69 else: | |
| 70 if verifyCryptedPassword(cryptedPass, password): | |
| 71 return defer.succeed(username) | |
| 72 | |
| 73 | |
| 74 def requestAvatarId(self, credentials): | |
| 75 username, password = credentials.username, credentials.password | |
| 76 | |
| 77 try: | |
| 78 import pwd | |
| 79 except ImportError: | |
| 80 pwd = None | |
| 81 | |
| 82 if pwd is not None: | |
| 83 checked = self.checkPwd(pwd, username, password) | |
| 84 if checked is not None: | |
| 85 return checked | |
| 86 | |
| 87 try: | |
| 88 import spwd | |
| 89 except ImportError: | |
| 90 spwd = None | |
| 91 | |
| 92 if spwd is not None: | |
| 93 checked = self.checkSpwd(spwd, username, password) | |
| 94 if checked is not None: | |
| 95 return checked | |
| 96 # TODO: check_pam? | |
| 97 # TODO: check_shadow? | |
| 98 return defer.fail(UnauthorizedLogin()) | |
| 99 | |
| 100 | |
| 101 | |
| 102 unixCheckerFactoryHelp = """ | |
| 103 This checker will attempt to use every resource available to | |
| 104 authenticate against the list of users on the local UNIX system. | |
| 105 (This does not support Windows servers for very obvious reasons.) | |
| 106 | |
| 107 Right now, this includes support for: | |
| 108 | |
| 109 * Python's pwd module (which checks /etc/passwd) | |
| 110 * Python's spwd module (which checks /etc/shadow) | |
| 111 | |
| 112 Future versions may include support for PAM authentication. | |
| 113 """ | |
| 114 | |
| 115 | |
| 116 | |
| 117 class UNIXCheckerFactory(object): | |
| 118 """ | |
| 119 A factory for L{UNIXChecker}. | |
| 120 """ | |
| 121 implements(ICheckerFactory, plugin.IPlugin) | |
| 122 authType = 'unix' | |
| 123 authHelp = unixCheckerFactoryHelp | |
| 124 argStringFormat = 'No argstring required.' | |
| 125 credentialInterfaces = UNIXChecker.credentialInterfaces | |
| 126 | |
| 127 def generateChecker(self, argstring): | |
| 128 """ | |
| 129 This checker factory ignores the argument string. Everything | |
| 130 needed to generate a user database is pulled out of the local | |
| 131 UNIX environment. | |
| 132 """ | |
| 133 return UNIXChecker() | |
| 134 | |
| 135 | |
| 136 | |
| 137 theUnixCheckerFactory = UNIXCheckerFactory() | |
| 138 | |
| OLD | NEW |