diff --git a/bin/ceo b/bin/ceo index 9c87819..74d60fb 100755 --- a/bin/ceo +++ b/bin/ceo @@ -1,33 +1,3 @@ #!/usr/bin/python2.4 -- -"""CEO SUID Python Wrapper Script""" -import os, sys - -safe_environment = ['LOGNAME', 'USERNAME', 'USER', 'HOME', 'TERM', 'LANG' - 'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', - 'LC_NUMERIC', 'LC_TIME', 'UID', 'GID', 'SSH_CONNECTION', 'SSH_AUTH_SOCK', - 'SSH_CLIENT'] - -for key in os.environ.keys(): - if key not in safe_environment: - del os.environ[key] - -os.environ['LESSSECURE'] = '1' -os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' - -for pathent in sys.path[:]: - if not pathent.find('/usr') == 0 and not pathent.find('/var') == 0: - sys.path.remove(pathent) - -euid = os.geteuid() -egid = os.getegid() -uid = os.getuid() -gid = os.getgid() -try: - os.setreuid(euid, euid) - os.setregid(egid, egid) -except OSError, e: - print str(e) - sys.exit(1) - import csc.apps.urwid.main -csc.apps.urwid.main.start(uid, gid) +csc.apps.urwid.main.start() diff --git a/bin/csc-chfn b/bin/csc-chfn index f723984..cf97c4d 100755 --- a/bin/csc-chfn +++ b/bin/csc-chfn @@ -9,22 +9,6 @@ When run from an unprivileged account, authentication will be performed before the account information is changed. """ import os, sys, pwd, getopt, PAM - -safe_environment = ['LOGNAME', 'USERNAME', 'USER', 'HOME', 'TERM', 'LANG' - 'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', - 'LC_NUMERIC', 'LC_TIME', 'UID', 'GID', 'SSH_CONNECTION', 'SSH_AUTH_SOCK', - 'SSH_CLIENT'] - -for key in os.environ.keys(): - if key not in safe_environment: - del os.environ[key] - -os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' - -for pathent in sys.path[:]: - if not pathent.find('/usr') == 0: - sys.path.remove(pathent) - from csc.common.excep import InvalidArgument from csc.adm import accounts diff --git a/bin/csc-chsh b/bin/csc-chsh index 25013a1..e8b1970 100755 --- a/bin/csc-chsh +++ b/bin/csc-chsh @@ -9,22 +9,6 @@ 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 - -safe_environment = ['LOGNAME', 'USERNAME', 'USER', 'HOME', 'TERM', 'LANG' - 'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', - 'LC_NUMERIC', 'LC_TIME', 'UID', 'GID', 'SSH_CONNECTION', 'SSH_AUTH_SOCK', - 'SSH_CLIENT'] - -for key in os.environ.keys(): - if key not in safe_environment: - del os.environ[key] - -os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' - -for pathent in sys.path[:]: - if not pathent.find('/usr') == 0: - sys.path.remove(pathent) - from csc.common.excep import InvalidArgument from csc.adm import accounts diff --git a/debian/postinst b/debian/postinst deleted file mode 100644 index 67c790c..0000000 --- a/debian/postinst +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash -e - -case "$1" in - configure|upgrade) - - if getent passwd ceo > /dev/null; then - CEO=ceo - SUID=4750 - SUIDALL=4755 - else - CEO=root - SUID=755 - SUIDALL=755 - fi - - if getent group office > /dev/null; then - OFFICE=office - else - OFFICE=root - fi - - if ! dpkg-statoverride --list /usr/bin/ceo > /dev/null; then - dpkg-statoverride --add --update $CEO $OFFICE $SUID /usr/bin/ceo - fi - - if ! dpkg-statoverride --list /usr/bin/addmember > /dev/null; then - dpkg-statoverride --add --update root $OFFICE $SUID /usr/bin/addmember - fi - - if ! dpkg-statoverride --list /usr/bin/addclub > /dev/null; then - dpkg-statoverride --add --update root $OFFICE $SUID /usr/bin/addclub - fi - - if ! dpkg-statoverride --list /usr/bin/ceoquery > /dev/null; then - dpkg-statoverride --add --update root root 755 /usr/bin/ceoquery - fi - - if ! dpkg-statoverride --list /usr/bin/csc-chsh > /dev/null; then - dpkg-statoverride --add --update $CEO root $SUIDALL /usr/bin/csc-chsh - fi - - if ! dpkg-statoverride --list /usr/bin/csc-chfn > /dev/null; then - dpkg-statoverride --add --update $CEO root $SUIDALL /usr/bin/csc-chfn - fi - - if [ -f /etc/csc/ldap.cf ] && ! dpkg-statoverride --list /etc/csc/ldap.cf > /dev/null; then - dpkg-statoverride --add --update $CEO staff 640 /etc/csc/ldap.cf - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \"$1\"" >&2 - exit 1 - ;; -esac - -#DEBHELPER# - -exit 0 diff --git a/debian/postrm b/debian/postrm deleted file mode 100644 index eca813f..0000000 --- a/debian/postrm +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -e - -case "$1" in - purge) - - if dpkg-statoverride --list /usr/bin/ceo > /dev/null; then - dpkg-statoverride --remove /usr/bin/ceo || true - fi - - if dpkg-statoverride --list /usr/bin/ceoquery > /dev/null; then - dpkg-statoverride --remove /usr/bin/ceoquery || true - fi - - if dpkg-statoverride --list /usr/bin/csc-chsh > /dev/null; then - dpkg-statoverride --remove /usr/bin/csc-chsh || true - fi - - if dpkg-statoverride --list /usr/bin/csc-chfn > /dev/null; then - dpkg-statoverride --remove /usr/bin/csc-chfn || true - fi - - if dpkg-statoverride --list /etc/csc/ldap.cf > /dev/null; then - dpkg-statoverride --remove /etc/csc/ldap.cf || true - fi - - if dpkg-statoverride --list /etc/csc/ceo.keytab > /dev/null; then - dpkg-statoverride --remove /etc/csc/ceo.keytab || true - fi - - rmdir --ignore-fail-on-non-empty /etc/csc - - ;; - - remove|failed-upgrade|upgrade) - ;; - - *) - echo "postrm called with invalid argument \"$1\"" >&2 - exit 1 - ;; -esac - -#DEBHELPER# - -exit 0 diff --git a/debian/rules b/debian/rules index d029f87..b319fb6 100755 --- a/debian/rules +++ b/debian/rules @@ -2,15 +2,8 @@ PYTHON := python2.4 -build: build-stamp - -build-stamp: - mkdir build - $(CC) -DFULL_PATH='"/usr/lib/csc/ceo"' -o build/ceo misc/setuid-prog.c - $(CC) -DFULL_PATH='"/usr/lib/csc/csc-chfn"' -o build/csc-chfn misc/setuid-prog.c - $(CC) -DFULL_PATH='"/usr/lib/csc/csc-chsh"' -o build/csc-chsh misc/setuid-prog.c +build: cd src && make - touch build-stamp clean: dh_testdir @@ -30,8 +23,7 @@ install: build dh_install pylib/* usr/lib/$(PYTHON)/site-packages/ dh_install etc/* etc/csc/ - dh_install bin/ceo bin/csc-chsh bin/csc-chfn usr/lib/csc/ - dh_install build/ceo bin/ceoquery build/csc-chsh build/csc-chfn src/addmember src/addclub usr/bin/ + dh_install bin/ceo bin/ceoquery bin/csc-chsh bin/csc-chfn src/addmember src/addclub usr/bin/ dh_install misc/csc.schema etc/ldap/schema/ binary-arch: build install diff --git a/etc/accounts.cf b/etc/accounts.cf index 2884472..64408c8 100644 --- a/etc/accounts.cf +++ b/etc/accounts.cf @@ -9,8 +9,6 @@ member_min_id = 20001 member_max_id = 29999 member_shell = "/bin/bash" member_home = "/users" -member_desc = "CSC Member Account" -member_group = "" ### Club Account Options ### @@ -18,8 +16,6 @@ club_min_id = 30001 club_max_id = 39999 club_shell = "/bin/bash" club_home = "/users" -club_desc = "CSC Club Account" -club_group = "" ### Administrative Account Options @@ -27,26 +23,17 @@ admin_min_id = 10001 admin_max_id = 19999 admin_shell = "/bin/bash" admin_home = "/users" -admin_desc = "CSC Administrative Account" -admin_group = "" - -### Account Group Options ### - -group_min_id = 10001 -group_max_id = 19999 -group_desc = "CSC Group" ### Home Directory Options ### skeleton_dir = "/etc/skel" homedir_mode = 0755 -homedir_min_uid = 10000 quota_prototype = "ctdalek" ### Validation Tuning ### username_regex = "^[a-z][-a-z0-9]*$" -groupname_regex = "^[a-z][-a-z0-9]*$" -homedir_regex = "^/users/[^\.]+$" min_password_length = 4 shells_file = "/etc/shells" +privileged_group = "staff" +notify_hook = "/etc/csc/thingie" diff --git a/misc/setuid-prog.c b/misc/setuid-prog.c deleted file mode 100644 index 88055e4..0000000 --- a/misc/setuid-prog.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - Template for a setuid program that calls a script. - - The script should be in an unwritable directory and should itself - be unwritable. In fact all parent directories up to the root - should be unwritable. The script must not be setuid, that's what - this program is for. - - This is a template program. You need to fill in the name of the - script that must be executed. This is done by changing the - definition of FULL_PATH below. - - There are also some rules that should be adhered to when writing - the script itself. - - The first and most important rule is to never, ever trust that the - user of the program will behave properly. Program defensively. - Check your arguments for reasonableness. If the user is allowed to - create files, check the names of the files. If the program depends - on argv[0] for the action it should perform, check it. - - Assuming the script is a Bourne shell script, the first line of the - script should be - #!/bin/sh - - The - is important, don't omit it. If you're using esh, the first - line should be - #!/usr/local/bin/esh -f - and for ksh, the first line should be - #!/usr/local/bin/ksh -p - The script should then set the variable IFS to the string - consisting of , , and . After this (*not* - before!), the PATH variable should be set to a reasonable value and - exported. Do not expect the PATH to have a reasonable value, so do - not trust the old value of PATH. You should then set the umask of - the program by calling - umask 077 # or 022 if you want the files to be readable - If you plan to change directories, you should either unset CDPATH - or set it to a good value. Setting CDPATH to just ``.'' (dot) is a - good idea. - If, for some reason, you want to use csh, the first line should be - #!/bin/csh -fb - You should then set the path variable to something reasonable, - without trusting the inherited path. Here too, you should set the - umask using the command - umask 077 # or 022 if you want the files to be readable -*/ - -#include -#include -#include -#include -#include -#include - -/* CONFIGURATION SECTION */ - -#ifndef FULL_PATH /* so that this can be specified from the Makefile */ -/* Uncomment the following line: -#define FULL_PATH "/full/path/of/script" -* Then comment out the #error line. */ -#error "You must define FULL_PATH somewhere" -#endif -#ifndef UMASK -#define UMASK 077 -#endif - -/* END OF CONFIGURATION SECTION */ - -#if defined(__STDC__) && defined(__sgi) -#define environ _environ -#endif - -/* don't change def_IFS */ -char def_IFS[] = "IFS= \t\n"; -/* you may want to change def_PATH, but you should really change it in */ -/* your script */ -#ifdef __sgi -char def_PATH[] = "PATH=/usr/bsd:/usr/bin:/bin:/usr/local/bin:/usr/sbin"; -#else -char def_PATH[] = "PATH=/usr/ucb:/usr/bin:/bin:/usr/local/bin"; -#endif -/* don't change def_CDPATH */ -char def_CDPATH[] = "CDPATH=."; -/* don't change def_ENV */ -char def_ENV[] = "ENV=:"; - -/* - This function changes all environment variables that start with LD_ - into variables that start with XD_. This is important since we - don't want the script that is executed to use any funny shared - libraries. - - The other changes to the environment are, strictly speaking, not - needed here. They can safely be done in the script. They are done - here because we don't trust the script writer (just like the script - writer shouldn't trust the user of the script). - If IFS is set in the environment, set it to space,tab,newline. - If CDPATH is set in the environment, set it to ``.''. - Set PATH to a reasonable default. -*/ -void -clean_environ(void) -{ - char **p; - extern char **environ; - - for (p = environ; *p; p++) { - if (strncmp(*p, "LD_", 3) == 0) - **p = 'X'; - else if (strncmp(*p, "_RLD", 4) == 0) - **p = 'X'; - else if (strncmp(*p, "PYTHON", 6) == 0) - **p = 'X'; - else if (strncmp(*p, "IFS=", 4) == 0) - *p = def_IFS; - else if (strncmp(*p, "CDPATH=", 7) == 0) - *p = def_CDPATH; - else if (strncmp(*p, "ENV=", 4) == 0) - *p = def_ENV; - } - putenv(def_PATH); -} - -int -main(int argc, char **argv) -{ - struct stat statb; - gid_t egid = getegid(); - uid_t euid = geteuid(); - - /* - Sanity check #1. - This check should be made compile-time, but that's not possible. - If you're sure that you specified a full path name for FULL_PATH, - you can omit this check. - */ - if (FULL_PATH[0] != '/') { - fprintf(stderr, "%s: %s is not a full path name\n", argv[0], - FULL_PATH); - fprintf(stderr, "You can only use this wrapper if you\n"); - fprintf(stderr, "compile it with an absolute path.\n"); - exit(1); - } - - /* - Sanity check #2. - Check that the owner of the script is equal to either the - effective uid or the super user. - */ - if (stat(FULL_PATH, &statb) < 0) { - perror("stat"); - exit(1); - } - if (statb.st_uid != 0 && statb.st_uid != euid) { - fprintf(stderr, "%s: %s has the wrong owner\n", argv[0], - FULL_PATH); - fprintf(stderr, "The script should be owned by root,\n"); - fprintf(stderr, "and shouldn't be writeable by anyone.\n"); - exit(1); - } - - //if (setregid(egid, egid) < 0) - // perror("setregid"); - //if (setreuid(euid, euid) < 0) - // perror("setreuid"); - - clean_environ(); - - umask(UMASK); - - while (**argv == '-') /* don't let argv[0] start with '-' */ - (*argv)++; - execv(FULL_PATH, argv); - fprintf(stderr, "%s: could not execute the script\n", argv[0]); - exit(1); -} diff --git a/pylib/csc/adm/members.py b/pylib/csc/adm/members.py index bf6dbf7..b46f3fa 100644 --- a/pylib/csc/adm/members.py +++ b/pylib/csc/adm/members.py @@ -24,16 +24,11 @@ cfg = {} def configure(): """Load Members Configuration""" - string_fields = [ 'member_shell', 'member_home', 'member_desc', - 'member_group', 'club_shell', 'club_home', 'club_desc', - 'club_group', 'admin_shell', 'admin_home', 'admin_desc', - 'admin_group', 'group_desc', 'username_regex', 'groupname_regex', - 'shells_file', 'server_url', 'users_base', 'groups_base', - 'sasl_mech', 'sasl_realm', 'admin_bind_keytab', - 'admin_bind_userid', 'realm', 'admin_principal', 'admin_keytab' ] - numeric_fields = [ 'member_min_id', 'member_max_id', 'club_min_id', - 'club_max_id', 'admin_min_id', 'admin_max_id', 'group_min_id', - 'group_max_id', 'min_password_length' ] + string_fields = [ 'username_regex', 'shells_file', 'server_url', + 'users_base', 'groups_base', 'sasl_mech', 'sasl_realm', + 'admin_bind_keytab', 'admin_bind_userid', 'realm', + 'admin_principal', 'admin_keytab' ] + numeric_fields = [ 'min_password_length' ] # read configuration file cfg_tmp = conf.read(CONFIG_FILE) @@ -88,10 +83,9 @@ def connect(): """Connect to LDAP.""" configure() + ldap_connection.connect_sasl(cfg['server_url'], cfg['sasl_mech'], - cfg['sasl_realm'], cfg['admin_bind_userid'], - ('keytab', cfg['admin_bind_keytab']), cfg['users_base'], - cfg['groups_base']) + cfg['sasl_realm'], cfg['users_base'], cfg['groups_base']) def disconnect(): """Disconnect from LDAP.""" @@ -188,8 +182,7 @@ def list_name(name): Parameters: name - the name to match members against - - Returns: a list of member dictionaries +Returns: a list of member dictionaries Example: list_name('Spang'): -> { 'mspang': { 'cn': 'Michael Spang', ... }, diff --git a/pylib/csc/apps/urwid/groups.py b/pylib/csc/apps/urwid/groups.py index 3b01258..db3ca8a 100644 --- a/pylib/csc/apps/urwid/groups.py +++ b/pylib/csc/apps/urwid/groups.py @@ -20,18 +20,6 @@ def list_group_members(data): search.member_list( mlist ) def group_members(data): - data, uid = data - - # only syscom may modify non-club groups - if data['group'] != 'office': - user = pwd.getpwuid(uid).pw_name - users = grp.getgrnam('syscom').gr_mem - if user not in users: - member = members.get(data['group']) - if member is None or 'objectClass' not in member \ - or 'club' not in member['objectClass']: - return - add_data = data.copy() add_data['action'] = 'Add' remove_data = data.copy() diff --git a/pylib/csc/apps/urwid/main.py b/pylib/csc/apps/urwid/main.py index 8e116cb..fdf0574 100644 --- a/pylib/csc/apps/urwid/main.py +++ b/pylib/csc/apps/urwid/main.py @@ -1,5 +1,4 @@ -import random -import urwid.curses_display +import random, ldap, urwid.curses_display from csc.apps.urwid.widgets import * from csc.apps.urwid.window import * @@ -73,10 +72,8 @@ def main_menu(): ("Search", search_members, None), ("Manage Club or Group Members", manage_group, None), ("Manage Positions", manage_positions, None), - ("Manage Office Staff", groups.group_members, - (office_data, ui.uid)), - ("Manage Systems Committee", groups.group_members, - (syscom_data, ui.uid)), + ("Manage Office Staff", groups.group_members, office_data), + ("Manage Systems Committee", groups.group_members, syscom_data), ("Exit", raise_abort, None), ] @@ -153,11 +150,13 @@ def run(): push_window( main_menu(), program_name() ) event_loop( ui ) -def start(uid, gid): - ui.uid = uid - ui.gid = gid - ui.run_wrapper( run ) +def start(): + try: + ui.run_wrapper( run ) + except ldap.LOCAL_ERROR, e: + print e[0]['info'] + print "Hint: You may need to run 'kinit'" if __name__ == '__main__': import os - start(os.getuid(), os.getgid()) + start() diff --git a/pylib/csc/backends/ldapi.py b/pylib/csc/backends/ldapi.py index d54584d..23e2ee0 100644 --- a/pylib/csc/backends/ldapi.py +++ b/pylib/csc/backends/ldapi.py @@ -68,13 +68,13 @@ class LDAPConnection(object): self.group_base = group_base - def connect_sasl(self, uri, mech, realm, userid, password, user_base, group_base): + def connect_sasl(self, uri, mech, realm, user_base, group_base): # open the connection self.ldap = ldap.initialize(uri) # authenticate - sasl = Sasl(mech, realm, userid, password) + sasl = Sasl(mech, realm) self.ldap.sasl_interactive_bind_s('', sasl) self.user_base = user_base @@ -364,16 +364,9 @@ class LDAPConnection(object): class Sasl: - def __init__(self, mech, realm, userid, password): + def __init__(self, mech, realm): self.mech = mech - if mech == 'GSSAPI': - credtype, cred = password - kinit_args = [ '/usr/bin/kinit', '%s@%s' % (userid, realm) ] - if credtype == 'keytab': - kinit_args += [ '-kt', cred ] - - kinit = Popen(kinit_args, stdin=PIPE, stdout=PIPE, stderr=PIPE) - kinit.wait() + self.realm = realm def callback(self, id, challenge, prompt, defresult): return '' diff --git a/src/config.c b/src/config.c index 13b4219..93065d0 100644 --- a/src/config.c +++ b/src/config.c @@ -15,7 +15,6 @@ char *groups_base = DEF_STR; char *skeleton_dir = DEF_STR; char *quota_prototype = DEF_STR; -char *homedir_prefix = DEF_STR; char *member_home = DEF_STR; char *member_shell = DEF_STR; @@ -29,6 +28,8 @@ long club_max_id = DEF_LONG; char *notify_hook = DEF_STR; +long homedir_mode = DEF_LONG; + char *realm = DEF_STR; char *admin_principal = DEF_STR; @@ -42,24 +43,21 @@ char *sasl_mech = DEF_STR; char *privileged_group = DEF_STR; -long homedir_mode = DEF_LONG; -long homedir_min_uid = DEF_LONG; - static char *strvarnames[] = { "server_url", "users_base", "admin_principal", - "admin_keytab", "skeleton_dir", "quota_prototype", "homedir_prefix", - "member_home", "member_shell", "club_home", "club_shell", "realm", - "admin_bind_userid", "admin_bind_keytab", "groups_base", - "privileged_group", "notify_hook", "sasl_realm", "sasl_mech" }; + "admin_keytab", "skeleton_dir", "quota_prototype", "member_home", + "member_shell", "club_home", "club_shell", "realm", "admin_bind_userid", + "admin_bind_keytab", "groups_base", "privileged_group", "notify_hook", + "sasl_realm", "sasl_mech" }; static char **strvars[] = { &server_url, &users_base, &admin_principal, - &admin_keytab, &skeleton_dir, "a_prototype, &homedir_prefix, - &member_home, &member_shell, &club_home, &club_shell, &realm, - &admin_bind_userid, &admin_bind_keytab, &groups_base, - &privileged_group, ¬ify_hook, &sasl_realm, &sasl_mech }; + &admin_keytab, &skeleton_dir, "a_prototype, &member_home, + &member_shell, &club_home, &club_shell, &realm, &admin_bind_userid, + &admin_bind_keytab, &groups_base, &privileged_group, ¬ify_hook, + &sasl_realm, &sasl_mech }; static char *longvarnames[] = { "member_min_id", "member_max_id", - "homedir_mode", "homedir_min_uid", "club_min_id", "club_max_id" }; + "homedir_mode", "club_min_id", "club_max_id" }; static long *longvars[] = { &member_min_id, &member_max_id, &homedir_mode, - &homedir_min_uid, &club_min_id, &club_max_id }; + &club_min_id, &club_max_id }; void config_var(char *var, char *val) { int i; diff --git a/src/config.h b/src/config.h index 3cce5ea..c3d905e 100644 --- a/src/config.h +++ b/src/config.h @@ -4,12 +4,8 @@ extern char *server_url; extern char *users_base; extern char *groups_base; -extern char *admin_bind_dn; -extern char *admin_bind_pw; - extern char *skeleton_dir; extern char *quota_prototype; -extern char *homedir_prefix; extern char *member_home; extern char *member_shell; @@ -24,7 +20,6 @@ extern long club_max_id; extern char *notify_hook; extern long homedir_mode; -extern long homedir_min_uid; extern char *realm;