pyceo/bin/csc-chsh

106 lines
2.9 KiB
Python
Executable File

#!/usr/bin/python2.4 --
"""
chsh - change login shell
This utility imitates chsh(1) from the shadow password suite, but makes its
changes in the LDAP directory rather than in the passwd file.
When run from an unprivileged account, authentication will be performed
before the shell is changed, and the new shell must be listed in /etc/shells.
"""
import os, sys, pwd, getopt, PAM
from csc.common.excep import InvalidArgument
from csc.adm import accounts
progname = os.path.basename(sys.argv[0])
def usage():
print "Usage: %s [-s shell] [username]" % progname
sys.exit(2)
def whoami():
uid = os.getuid()
username = os.getlogin()
if pwd.getpwnam(username).pw_uid != uid:
username = pwd.getpwuid(uid).pw_name
return (uid, username)
def authenticate(username):
auth = PAM.pam()
auth.start('chsh', username)
try:
auth.authenticate()
auth.acct_mgmt()
except PAM.error, resp:
print "%s: %s" % (progname, resp.args[0])
sys.exit(1)
def main():
pwuid, pwnam = whoami()
euid = os.geteuid()
os.setreuid(euid, euid)
try:
options, arguments = getopt.gnu_getopt(sys.argv[1:], 's:')
new_shell = None
for opt, val in options:
if opt == '-s':
new_shell = val
if len(arguments) > 1:
usage()
elif len(arguments) == 1:
username = arguments[0]
else:
username = pwnam
except getopt.GetoptError, e:
usage()
try:
if pwuid and pwd.getpwnam(username).pw_uid != pwuid:
print "%s: You may not change the shell for %s." % (progname, username)
sys.exit(1)
except KeyError:
print "%s: unknown user %s" % (progname, username)
sys.exit(1)
try:
accounts.connect()
current_shell = accounts.get_shell(username)
if pwuid:
authenticate(username)
if not new_shell:
print "Changing the login shell for %s" % username
print "Enter the new value, or press ENTER for the default"
print " Login Shell [%s]:" % current_shell,
new_shell = raw_input()
if not new_shell:
new_shell = current_shell
if new_shell != current_shell:
accounts.update_shell(username, new_shell, pwuid != 0)
except InvalidArgument, e:
if e.argname == 'shell':
print "%s: %s: invalid shell" % (progname, new_shell)
sys.exit(1)
else:
raise
if __name__ == '__main__':
exceps = ( accounts.ConfigurationException, accounts.LDAPException,
accounts.KrbException, accounts.AccountException )
try:
main()
except KeyboardInterrupt:
sys.exit(130)
except IOError, e:
print "%s: %s: %s" % (progname, e.filename, e.strerror)
sys.exit(1)
except exceps, e:
print "%s: %s" % (progname, e)
sys.exit(1)