forked from public/pyceo
Make CEO non-SUID
It now binds to the directory as the invoking user.
This commit is contained in:
parent
618bfa2d8d
commit
8c19dc63b6
32
bin/ceo
32
bin/ceo
|
@ -1,33 +1,3 @@
|
||||||
#!/usr/bin/python2.4 --
|
#!/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
|
import csc.apps.urwid.main
|
||||||
csc.apps.urwid.main.start(uid, gid)
|
csc.apps.urwid.main.start()
|
||||||
|
|
16
bin/csc-chfn
16
bin/csc-chfn
|
@ -9,22 +9,6 @@ When run from an unprivileged account, authentication will be performed
|
||||||
before the account information is changed.
|
before the account information is changed.
|
||||||
"""
|
"""
|
||||||
import os, sys, pwd, getopt, PAM
|
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.common.excep import InvalidArgument
|
||||||
from csc.adm import accounts
|
from csc.adm import accounts
|
||||||
|
|
||||||
|
|
16
bin/csc-chsh
16
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.
|
before the shell is changed, and the new shell must be listed in /etc/shells.
|
||||||
"""
|
"""
|
||||||
import os, sys, pwd, getopt, PAM
|
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.common.excep import InvalidArgument
|
||||||
from csc.adm import accounts
|
from csc.adm import accounts
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -2,15 +2,8 @@
|
||||||
|
|
||||||
PYTHON := python2.4
|
PYTHON := python2.4
|
||||||
|
|
||||||
build: build-stamp
|
build:
|
||||||
|
|
||||||
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
|
|
||||||
cd src && make
|
cd src && make
|
||||||
touch build-stamp
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
dh_testdir
|
dh_testdir
|
||||||
|
@ -30,8 +23,7 @@ install: build
|
||||||
dh_install pylib/* usr/lib/$(PYTHON)/site-packages/
|
dh_install pylib/* usr/lib/$(PYTHON)/site-packages/
|
||||||
dh_install etc/* etc/csc/
|
dh_install etc/* etc/csc/
|
||||||
|
|
||||||
dh_install bin/ceo bin/csc-chsh bin/csc-chfn usr/lib/csc/
|
dh_install bin/ceo bin/ceoquery bin/csc-chsh bin/csc-chfn src/addmember src/addclub usr/bin/
|
||||||
dh_install build/ceo bin/ceoquery build/csc-chsh build/csc-chfn src/addmember src/addclub usr/bin/
|
|
||||||
dh_install misc/csc.schema etc/ldap/schema/
|
dh_install misc/csc.schema etc/ldap/schema/
|
||||||
|
|
||||||
binary-arch: build install
|
binary-arch: build install
|
||||||
|
|
|
@ -9,8 +9,6 @@ member_min_id = 20001
|
||||||
member_max_id = 29999
|
member_max_id = 29999
|
||||||
member_shell = "/bin/bash"
|
member_shell = "/bin/bash"
|
||||||
member_home = "/users"
|
member_home = "/users"
|
||||||
member_desc = "CSC Member Account"
|
|
||||||
member_group = ""
|
|
||||||
|
|
||||||
### Club Account Options ###
|
### Club Account Options ###
|
||||||
|
|
||||||
|
@ -18,8 +16,6 @@ club_min_id = 30001
|
||||||
club_max_id = 39999
|
club_max_id = 39999
|
||||||
club_shell = "/bin/bash"
|
club_shell = "/bin/bash"
|
||||||
club_home = "/users"
|
club_home = "/users"
|
||||||
club_desc = "CSC Club Account"
|
|
||||||
club_group = ""
|
|
||||||
|
|
||||||
### Administrative Account Options
|
### Administrative Account Options
|
||||||
|
|
||||||
|
@ -27,26 +23,17 @@ admin_min_id = 10001
|
||||||
admin_max_id = 19999
|
admin_max_id = 19999
|
||||||
admin_shell = "/bin/bash"
|
admin_shell = "/bin/bash"
|
||||||
admin_home = "/users"
|
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 ###
|
### Home Directory Options ###
|
||||||
|
|
||||||
skeleton_dir = "/etc/skel"
|
skeleton_dir = "/etc/skel"
|
||||||
homedir_mode = 0755
|
homedir_mode = 0755
|
||||||
homedir_min_uid = 10000
|
|
||||||
quota_prototype = "ctdalek"
|
quota_prototype = "ctdalek"
|
||||||
|
|
||||||
### Validation Tuning ###
|
### Validation Tuning ###
|
||||||
|
|
||||||
username_regex = "^[a-z][-a-z0-9]*$"
|
username_regex = "^[a-z][-a-z0-9]*$"
|
||||||
groupname_regex = "^[a-z][-a-z0-9]*$"
|
|
||||||
homedir_regex = "^/users/[^\.]+$"
|
|
||||||
min_password_length = 4
|
min_password_length = 4
|
||||||
shells_file = "/etc/shells"
|
shells_file = "/etc/shells"
|
||||||
|
privileged_group = "staff"
|
||||||
|
notify_hook = "/etc/csc/thingie"
|
||||||
|
|
|
@ -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 <space>, <tab>, and <newline>. 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 <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
|
@ -24,16 +24,11 @@ cfg = {}
|
||||||
def configure():
|
def configure():
|
||||||
"""Load Members Configuration"""
|
"""Load Members Configuration"""
|
||||||
|
|
||||||
string_fields = [ 'member_shell', 'member_home', 'member_desc',
|
string_fields = [ 'username_regex', 'shells_file', 'server_url',
|
||||||
'member_group', 'club_shell', 'club_home', 'club_desc',
|
'users_base', 'groups_base', 'sasl_mech', 'sasl_realm',
|
||||||
'club_group', 'admin_shell', 'admin_home', 'admin_desc',
|
'admin_bind_keytab', 'admin_bind_userid', 'realm',
|
||||||
'admin_group', 'group_desc', 'username_regex', 'groupname_regex',
|
'admin_principal', 'admin_keytab' ]
|
||||||
'shells_file', 'server_url', 'users_base', 'groups_base',
|
numeric_fields = [ 'min_password_length' ]
|
||||||
'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' ]
|
|
||||||
|
|
||||||
# read configuration file
|
# read configuration file
|
||||||
cfg_tmp = conf.read(CONFIG_FILE)
|
cfg_tmp = conf.read(CONFIG_FILE)
|
||||||
|
@ -88,10 +83,9 @@ def connect():
|
||||||
"""Connect to LDAP."""
|
"""Connect to LDAP."""
|
||||||
|
|
||||||
configure()
|
configure()
|
||||||
|
|
||||||
ldap_connection.connect_sasl(cfg['server_url'], cfg['sasl_mech'],
|
ldap_connection.connect_sasl(cfg['server_url'], cfg['sasl_mech'],
|
||||||
cfg['sasl_realm'], cfg['admin_bind_userid'],
|
cfg['sasl_realm'], cfg['users_base'], cfg['groups_base'])
|
||||||
('keytab', cfg['admin_bind_keytab']), cfg['users_base'],
|
|
||||||
cfg['groups_base'])
|
|
||||||
|
|
||||||
def disconnect():
|
def disconnect():
|
||||||
"""Disconnect from LDAP."""
|
"""Disconnect from LDAP."""
|
||||||
|
@ -188,8 +182,7 @@ def list_name(name):
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
name - the name to match members against
|
name - the name to match members against
|
||||||
|
Returns: a list of member dictionaries
|
||||||
Returns: a list of member dictionaries
|
|
||||||
|
|
||||||
Example: list_name('Spang'): -> {
|
Example: list_name('Spang'): -> {
|
||||||
'mspang': { 'cn': 'Michael Spang', ... },
|
'mspang': { 'cn': 'Michael Spang', ... },
|
||||||
|
|
|
@ -20,18 +20,6 @@ def list_group_members(data):
|
||||||
search.member_list( mlist )
|
search.member_list( mlist )
|
||||||
|
|
||||||
def group_members(data):
|
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 = data.copy()
|
||||||
add_data['action'] = 'Add'
|
add_data['action'] = 'Add'
|
||||||
remove_data = data.copy()
|
remove_data = data.copy()
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import random
|
import random, ldap, urwid.curses_display
|
||||||
import urwid.curses_display
|
|
||||||
|
|
||||||
from csc.apps.urwid.widgets import *
|
from csc.apps.urwid.widgets import *
|
||||||
from csc.apps.urwid.window import *
|
from csc.apps.urwid.window import *
|
||||||
|
@ -73,10 +72,8 @@ def main_menu():
|
||||||
("Search", search_members, None),
|
("Search", search_members, None),
|
||||||
("Manage Club or Group Members", manage_group, None),
|
("Manage Club or Group Members", manage_group, None),
|
||||||
("Manage Positions", manage_positions, None),
|
("Manage Positions", manage_positions, None),
|
||||||
("Manage Office Staff", groups.group_members,
|
("Manage Office Staff", groups.group_members, office_data),
|
||||||
(office_data, ui.uid)),
|
("Manage Systems Committee", groups.group_members, syscom_data),
|
||||||
("Manage Systems Committee", groups.group_members,
|
|
||||||
(syscom_data, ui.uid)),
|
|
||||||
("Exit", raise_abort, None),
|
("Exit", raise_abort, None),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -153,11 +150,13 @@ def run():
|
||||||
push_window( main_menu(), program_name() )
|
push_window( main_menu(), program_name() )
|
||||||
event_loop( ui )
|
event_loop( ui )
|
||||||
|
|
||||||
def start(uid, gid):
|
def start():
|
||||||
ui.uid = uid
|
try:
|
||||||
ui.gid = gid
|
ui.run_wrapper( run )
|
||||||
ui.run_wrapper( run )
|
except ldap.LOCAL_ERROR, e:
|
||||||
|
print e[0]['info']
|
||||||
|
print "Hint: You may need to run 'kinit'"
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import os
|
import os
|
||||||
start(os.getuid(), os.getgid())
|
start()
|
||||||
|
|
|
@ -68,13 +68,13 @@ class LDAPConnection(object):
|
||||||
self.group_base = group_base
|
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
|
# open the connection
|
||||||
self.ldap = ldap.initialize(uri)
|
self.ldap = ldap.initialize(uri)
|
||||||
|
|
||||||
# authenticate
|
# authenticate
|
||||||
sasl = Sasl(mech, realm, userid, password)
|
sasl = Sasl(mech, realm)
|
||||||
self.ldap.sasl_interactive_bind_s('', sasl)
|
self.ldap.sasl_interactive_bind_s('', sasl)
|
||||||
|
|
||||||
self.user_base = user_base
|
self.user_base = user_base
|
||||||
|
@ -364,16 +364,9 @@ class LDAPConnection(object):
|
||||||
|
|
||||||
class Sasl:
|
class Sasl:
|
||||||
|
|
||||||
def __init__(self, mech, realm, userid, password):
|
def __init__(self, mech, realm):
|
||||||
self.mech = mech
|
self.mech = mech
|
||||||
if mech == 'GSSAPI':
|
self.realm = realm
|
||||||
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()
|
|
||||||
|
|
||||||
def callback(self, id, challenge, prompt, defresult):
|
def callback(self, id, challenge, prompt, defresult):
|
||||||
return ''
|
return ''
|
||||||
|
|
26
src/config.c
26
src/config.c
|
@ -15,7 +15,6 @@ char *groups_base = DEF_STR;
|
||||||
|
|
||||||
char *skeleton_dir = DEF_STR;
|
char *skeleton_dir = DEF_STR;
|
||||||
char *quota_prototype = DEF_STR;
|
char *quota_prototype = DEF_STR;
|
||||||
char *homedir_prefix = DEF_STR;
|
|
||||||
|
|
||||||
char *member_home = DEF_STR;
|
char *member_home = DEF_STR;
|
||||||
char *member_shell = DEF_STR;
|
char *member_shell = DEF_STR;
|
||||||
|
@ -29,6 +28,8 @@ long club_max_id = DEF_LONG;
|
||||||
|
|
||||||
char *notify_hook = DEF_STR;
|
char *notify_hook = DEF_STR;
|
||||||
|
|
||||||
|
long homedir_mode = DEF_LONG;
|
||||||
|
|
||||||
char *realm = DEF_STR;
|
char *realm = DEF_STR;
|
||||||
|
|
||||||
char *admin_principal = DEF_STR;
|
char *admin_principal = DEF_STR;
|
||||||
|
@ -42,24 +43,21 @@ char *sasl_mech = DEF_STR;
|
||||||
|
|
||||||
char *privileged_group = 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",
|
static char *strvarnames[] = { "server_url", "users_base", "admin_principal",
|
||||||
"admin_keytab", "skeleton_dir", "quota_prototype", "homedir_prefix",
|
"admin_keytab", "skeleton_dir", "quota_prototype", "member_home",
|
||||||
"member_home", "member_shell", "club_home", "club_shell", "realm",
|
"member_shell", "club_home", "club_shell", "realm", "admin_bind_userid",
|
||||||
"admin_bind_userid", "admin_bind_keytab", "groups_base",
|
"admin_bind_keytab", "groups_base", "privileged_group", "notify_hook",
|
||||||
"privileged_group", "notify_hook", "sasl_realm", "sasl_mech" };
|
"sasl_realm", "sasl_mech" };
|
||||||
static char **strvars[] = { &server_url, &users_base, &admin_principal,
|
static char **strvars[] = { &server_url, &users_base, &admin_principal,
|
||||||
&admin_keytab, &skeleton_dir, "a_prototype, &homedir_prefix,
|
&admin_keytab, &skeleton_dir, "a_prototype, &member_home,
|
||||||
&member_home, &member_shell, &club_home, &club_shell, &realm,
|
&member_shell, &club_home, &club_shell, &realm, &admin_bind_userid,
|
||||||
&admin_bind_userid, &admin_bind_keytab, &groups_base,
|
&admin_bind_keytab, &groups_base, &privileged_group, ¬ify_hook,
|
||||||
&privileged_group, ¬ify_hook, &sasl_realm, &sasl_mech };
|
&sasl_realm, &sasl_mech };
|
||||||
|
|
||||||
static char *longvarnames[] = { "member_min_id", "member_max_id",
|
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,
|
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) {
|
void config_var(char *var, char *val) {
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -4,12 +4,8 @@ extern char *server_url;
|
||||||
extern char *users_base;
|
extern char *users_base;
|
||||||
extern char *groups_base;
|
extern char *groups_base;
|
||||||
|
|
||||||
extern char *admin_bind_dn;
|
|
||||||
extern char *admin_bind_pw;
|
|
||||||
|
|
||||||
extern char *skeleton_dir;
|
extern char *skeleton_dir;
|
||||||
extern char *quota_prototype;
|
extern char *quota_prototype;
|
||||||
extern char *homedir_prefix;
|
|
||||||
|
|
||||||
extern char *member_home;
|
extern char *member_home;
|
||||||
extern char *member_shell;
|
extern char *member_shell;
|
||||||
|
@ -24,7 +20,6 @@ extern long club_max_id;
|
||||||
extern char *notify_hook;
|
extern char *notify_hook;
|
||||||
|
|
||||||
extern long homedir_mode;
|
extern long homedir_mode;
|
||||||
extern long homedir_min_uid;
|
|
||||||
|
|
||||||
extern char *realm;
|
extern char *realm;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue