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 |