ef0db49c78a84f0d5a9631f9fe715de933720506
[public/pyceo-broken.git] / bin / csc-chsh
1 #!/usr/bin/python2.4 --
2 """
3 chsh - change login shell
4
5 This utility imitates chsh(1) from the shadow password suite, but makes its
6 changes in the LDAP directory rather than in the passwd file.
7
8 When run from an unprivileged account, authentication will be performed
9 before the shell is changed, and the new shell must be listed in /etc/shells.
10 """
11 import os, sys, pwd, getopt, PAM
12
13 safe_environment = ['LOGNAME', 'USERNAME', 'USER', 'HOME', 'TERM', 'LANG'
14     'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY',
15     'LC_NUMERIC', 'LC_TIME', 'UID', 'GID', 'SSH_CONNECTION', 'SSH_AUTH_SOCK',
16     'SSH_CLIENT']
17
18 for key in os.environ.keys():
19     if key not in safe_environment:
20         del os.environ[key]
21
22 os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin'
23
24 for pathent in sys.path[:]:
25     if not pathent.find('/usr') == 0:
26         sys.path.remove(pathent)
27
28 from csc.common.excep import InvalidArgument
29 from csc.adm import accounts
30
31 progname = os.path.basename(sys.argv[0])
32
33 def usage():
34     print "Usage: %s [-s shell] [username]" % progname
35     sys.exit(2)
36
37 def whoami():
38     uid = os.getuid()
39     username = os.getlogin()
40     if pwd.getpwnam(username).pw_uid != uid:
41         username = pwd.getpwuid(uid).pw_name
42     return (uid, username)
43
44 def authenticate(username):
45     auth = PAM.pam()
46     auth.start('chsh', username)
47     try:
48         auth.authenticate()
49         auth.acct_mgmt()
50     except PAM.error, resp:
51         print "%s: %s" % (progname, resp.args[0])
52         sys.exit(1)
53
54 def main():
55
56     pwuid, pwnam = whoami()
57
58     try:
59         options, arguments = getopt.gnu_getopt(sys.argv[1:], 's:')
60         new_shell = None
61         for opt, val in options:
62             if opt == '-s':
63                 new_shell = val
64         if len(arguments) > 1:
65             usage()
66         elif len(arguments) == 1:
67             username = arguments[0]
68         else:
69             username = pwnam
70     except getopt.GetoptError, e:
71         usage()
72
73     try:
74         if pwuid and pwd.getpwnam(username).pw_uid != pwuid:
75             print "%s: You may not change the shell for %s." % (progname, username)
76             sys.exit(1)
77     except KeyError:
78         print "%s: unknown user %s" % (progname, username)
79         sys.exit(1)
80
81     try:
82         accounts.connect()
83         current_shell = accounts.get_shell(username)
84
85         if pwuid:
86             authenticate(username)
87
88         if not new_shell:
89             print "Changing the login shell for %s" % username
90             print "Enter the new value, or press ENTER for the default"
91             print "        Login Shell [%s]:" % current_shell,
92             new_shell = raw_input()
93             if not new_shell:
94                 new_shell = current_shell
95
96         if new_shell != current_shell:
97             accounts.update_shell(username, new_shell, pwuid != 0)
98
99     except InvalidArgument, e:
100         if e.argname == 'shell':
101             print "%s: %s: invalid shell" % (progname, new_shell)
102             sys.exit(1)
103         else:
104             raise
105
106 if __name__ == '__main__':
107     exceps = ( accounts.ConfigurationException, accounts.LDAPException,
108             accounts.KrbException, accounts.AccountException )
109     try:
110         main()
111     except KeyboardInterrupt:
112         sys.exit(130) 
113     except IOError, e:
114         print "%s: %s: %s" % (progname, e.filename, e.strerror)
115         sys.exit(1)
116     except exceps, e:
117         print "%s: %s" % (progname, e)
118         sys.exit(1)