OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2008 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) | |
OLD | NEW |