#!/usr/bin/python """ 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 ceo import accounts from ceo.excep import InvalidArgument 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)