Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / cred / pamauth.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Support for asynchronously authenticating using PAM.
6 """
7
8
9 import PAM
10
11 import getpass, threading, os
12
13 from twisted.internet import threads, defer
14
15 def pamAuthenticateThread(service, user, conv):
16     def _conv(items):
17         from twisted.internet import reactor
18         try:
19             d = conv(items)
20         except:
21             import traceback
22             traceback.print_exc()
23             return
24         ev = threading.Event()
25         def cb(r):
26             ev.r = (1, r)
27             ev.set()
28         def eb(e):
29             ev.r = (0, e)
30             ev.set()
31         reactor.callFromThread(d.addCallbacks, cb, eb)
32         ev.wait()
33         done = ev.r
34         if done[0]:
35             return done[1]
36         else:
37             raise done[1].type, done[1].value
38
39     return callIntoPAM(service, user, _conv)
40
41 def callIntoPAM(service, user, conv):
42     """A testing hook.
43     """
44     pam = PAM.pam()
45     pam.start(service)
46     pam.set_item(PAM.PAM_USER, user)
47     pam.set_item(PAM.PAM_CONV, conv)
48     gid = os.getegid()
49     uid = os.geteuid()
50     os.setegid(0)
51     os.seteuid(0)
52     try:
53         pam.authenticate() # these will raise
54         pam.acct_mgmt()
55         return 1
56     finally:
57         os.setegid(gid)
58         os.seteuid(uid)
59
60 def defConv(items):
61     resp = []
62     for i in range(len(items)):
63         message, kind = items[i]
64         if kind == 1: # password
65             p = getpass.getpass(message)
66             resp.append((p, 0))
67         elif kind == 2: # text
68             p = raw_input(message)
69             resp.append((p, 0))
70         elif kind in (3,4):
71             print message
72             resp.append(("", 0))
73         else:
74             return defer.fail('foo')
75     d = defer.succeed(resp)
76     return d
77
78 def pamAuthenticate(service, user, conv):
79     return threads.deferToThread(pamAuthenticateThread, service, user, conv)