Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / plugins / cred_unix.py
1 # -*- test-case-name: twisted.test.test_strcred -*-
2 #
3 # Copyright (c) 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