move pcucontrol package into pcucontrol module.
[pcucontrol.git] / pcucontrol / transports / pyssh / fssa.py
1 # vi:et:ts=4:tw=0
2 """ fssa.py
3
4     Search for an ssh-agent for the calling user and attach to it
5     if found.
6
7     Tested on poxix only
8 """
9 # This is a Python port of Steve Allen's fsa.sh script found
10 # at http://www.ucolick.org/~sla/ssh/sshcron.html
11 # Ported by Mark W. Alexander <slash@dotnetslash.net>
12
13 import os
14 if os.name == 'posix':
15     import pwd, stat, sys
16     from commands import getoutput
17     def fssa(key=None):
18         """ fssa(key=None)
19
20         Searches /tmp/ssh-* owned by the calling user for ssh-agent
21         sockets. If key is provided, only sockets matching the key will be
22         considered. If key is not provided, the calling users username
23         will be used instead.
24         """
25         user, pw, uid, gid, gecos, home, shell = pwd.getpwuid(os.getuid())
26         if key is None:
27             key = user
28
29         # Find /tmp/ssh-* dirs owned by this user
30         candidate_dirs=[]
31         for filename in os.listdir('/tmp'):
32             file_stat = os.stat("/tmp/%s" % (filename))
33             if file_stat[stat.ST_UID] == os.getuid() \
34             and stat.S_ISDIR(file_stat[stat.ST_MODE]) \
35             and filename.find('ssh-') == 0:
36                 candidate_dirs.append("/tmp/%s" % filename)
37
38         candidate_sockets=[]
39         for d in candidate_dirs:
40             for f in os.listdir(d):
41                 file_stat = os.stat("%s/%s" % (d, f))
42                 if file_stat[stat.ST_UID] == os.getuid() \
43                 and stat.S_ISSOCK(file_stat[stat.ST_MODE]) \
44                 and f.find('agent.') == 0:
45                     candidate_sockets.append("%s/%s" % (d, f))
46         alive = None
47         # order by pid, prefering sockets where the parent pid
48         # is gone. This gives preference to agents running in the
49         # background and reaped by init (maybe). Only works on
50         # systems with a /proc filesystem
51         if stat.S_ISDIR(os.stat("/proc")[stat.ST_MODE]):
52             reorder=[]
53             for s in candidate_sockets:
54                 pid = s[s.find('.')+1:]
55                 try:
56                     stat.S_ISDIR(os.stat("/proc/%s" % pid)[stat.ST_MODE])
57                     reorder.append(s)
58                 except:
59                     reorder.insert(0,s)
60             candidate_sockets = reorder
61
62         for s in candidate_sockets:
63             os.environ['SSH_AUTH_SOCK'] = s
64             try:
65                 pubkey = getoutput("ssh-add -l 2>/dev/null")
66             except:
67                 continue
68             if pubkey.find(key):
69                 alive = 1
70                 break
71             os.environ.pop('SSH_AUTH_SOCK')
72         if alive:
73             return pubkey
74         else:
75             return None