Added "addhomedir", a utility to create home directories for new users.

This commit is contained in:
Michael Spang 2007-01-29 01:42:42 -05:00 committed by Michael Spang
parent 8577703511
commit 2828ed6997
6 changed files with 172 additions and 2 deletions

152
bin/addhomedir Executable file
View File

@ -0,0 +1,152 @@
#!/usr/bin/python2.4 --
"""
addhomedir - a script to create home directories for new users
For the most part, this script mimics the behavior of adduser(8) when
creating a home directory. It creates the directory, copies files
from /etc/skel, sets permissions, and sets quotas.
"""
import os, sys, re, pwd, getopt, stat
CONFIG_FILE = '/etc/csc/accounts.cf'
safe_environment = ['LOGNAME', 'USERNAME', 'USER', 'HOME', 'TERM', 'LANG'
'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGE', 'LC_MONETARY',
'LC_NUMERIC', 'LC_TIME', 'UID', 'GID', 'SSH_CONNECTION', 'SSH_AUTH_SOCK',
'SSH_CLIENT']
for key in os.environ.keys():
if not key in safe_environment:
del os.environ[key]
os.environ['PATH'] = '/usr/sbin:/sbin:/usr/bin:/bin'
os.umask(0)
for pathent in sys.path[:]:
if not pathent.find('/usr') == 0:
sys.path.remove(pathent)
from csc.common import conf
usage = "usage: %s [--quiet] username" % sys.argv[0]
try:
options, arguments = getopt.gnu_getopt(sys.argv[1:], '', ['quiet'])
except getopt.GetoptError, e:
print usage
sys.exit(2)
if len(arguments) != 1:
print usage
sys.exit(2)
quiet = ('--quiet','') in options
program = os.path.basename(sys.argv[0])
username = arguments[0]
def fail(message):
print >> sys.stderr, "%s: %s" % (program, message)
sys.exit(1)
def debug(message):
if not quiet:
print message
def warn(message):
print >> sys.stderr, "warning: %s" % message
try:
cfg = conf.read(CONFIG_FILE)
except conf.ConfigurationException:
fail("could not import configuration from %s" % CONFIG_FILE)
try:
string_fields = ['homedir_regex', 'skeleton_dir', 'quota_prototype']
integer_fields = ['homedir_min_uid', 'homedir_mode']
conf.check_string_fields(CONFIG_FILE, string_fields, cfg)
conf.check_integer_fields(CONFIG_FILE, integer_fields, cfg)
except conf.ConfigurationException, e:
fail(e)
if not os.path.isdir(cfg['skeleton_dir']):
fail("invalid skeleton dir %s" % cfg['skeleton_dir'])
try:
pwent = pwd.getpwnam(username)
uid = pwent.pw_uid
gid = pwent.pw_gid
homedir = pwent.pw_dir
except KeyError:
fail("%s: invalid user" % username)
if uid < cfg['homedir_min_uid']:
fail("uid of account %s is less than homedir_min_uid" % username)
if not re.match(cfg['homedir_regex'], homedir):
fail("homedir of account %s does not match homedir_regex" % username)
if os.path.exists(homedir):
fail("home directory %s exists" % homedir)
parentdir = os.path.dirname(homedir)
if not os.path.isdir(parentdir):
fail("parent directory %s does not exist" % parentdir)
try:
debug("creating %s" % homedir)
os.mkdir(homedir, cfg['homedir_mode'])
os.chown(homedir, uid, gid)
# copy files from /etc/skel or similar (location is configurable)
skel_files = os.listdir(cfg['skeleton_dir'])
for filename in skel_files:
srcpath = cfg['skeleton_dir'] + '/' + filename
destpath = homedir + '/' + filename
srcstat = os.lstat(srcpath)
perm = srcstat.st_mode & 0777
if srcstat.st_uid or srcstat.st_gid:
warn("skipping %s due to ownership" % srcpath)
continue
if stat.S_ISLNK(srcstat.st_mode):
linkdest = os.readlink(srcpath)
debug("linking %s to %s" % (destpath, linkdest))
os.symlink(linkdest, destpath)
os.lchown(destpath, uid, gid)
elif stat.S_ISDIR(srcstat.st_mode):
debug("adding directory %s" % destpath)
os.mkdir(destpath, perm)
os.chown(destpath, uid, gid)
elif stat.S_ISREG(srcstat.st_mode):
debug("adding %s" % destpath)
src = open(srcpath)
destfd = os.open(destpath, os.O_CREAT|os.O_EXCL|os.O_WRONLY, perm)
dest = os.fdopen(destfd, 'w')
dest.write(src.read())
src.close()
dest.close()
os.chown(destpath, uid, gid)
else:
warn("file type of %s not supported" % srcpath)
# set the user's quota
setquota = '/usr/sbin/setquota'
if os.access(setquota, os.X_OK):
protouser = cfg['quota_prototype']
debug("copying quotas from %s to %s" % (protouser, username))
args = [ setquota, '-u', '-p', protouser, username, '-a' ]
result = os.spawnv(os.P_WAIT, setquota, args)
if result:
warn("setquota returned error code %d" % result)
else:
warn("cannot find setquota, not setting quota")
debug("done!")
except OSError, e:
fail(e)

1
debian/control vendored
View File

@ -8,6 +8,7 @@ Standards-Version: 3.7.2
Package: csc Package: csc
Architecture: any Architecture: any
Depends: python, python2.4, python2.4-ldap, python2.4-pygresql, krb5-user, less, ${shlibs:Depends} Depends: python, python2.4, python2.4-ldap, python2.4-pygresql, krb5-user, less, ${shlibs:Depends}
Recommends: quota
Description: Computer Science Club Administrative Utilities Description: Computer Science Club Administrative Utilities
This package contains the CSC Electronic Office This package contains the CSC Electronic Office
and other Computer Science Club administrative and other Computer Science Club administrative

4
debian/postinst vendored
View File

@ -21,6 +21,10 @@ case "$1" in
dpkg-statoverride --add --update $CEO $OFFICE $SUID /usr/bin/ceo dpkg-statoverride --add --update $CEO $OFFICE $SUID /usr/bin/ceo
fi fi
if ! dpkg-statoverride --list /usr/bin/addhomedir > /dev/null; then
dpkg-statoverride --add --update root $OFFICE $SUID /usr/bin/addhomedir
fi
if [ -f /etc/csc/ldap.cf ] && ! dpkg-statoverride --list /etc/csc/ldap.cf > /dev/null; then 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 dpkg-statoverride --add --update $CEO staff 640 /etc/csc/ldap.cf
fi fi

4
debian/postrm vendored
View File

@ -7,6 +7,10 @@ case "$1" in
dpkg-statoverride --remove /usr/bin/ceo || true dpkg-statoverride --remove /usr/bin/ceo || true
fi fi
if dpkg-statoverride --list /usr/bin/addhomedir > /dev/null; then
dpkg-statoverride --remove /usr/bin/addhomedir || true
fi
if dpkg-statoverride --list /etc/csc/ldap.cf > /dev/null; then if dpkg-statoverride --list /etc/csc/ldap.cf > /dev/null; then
dpkg-statoverride --remove /etc/csc/ldap.cf || true dpkg-statoverride --remove /etc/csc/ldap.cf || true
fi fi

5
debian/rules vendored
View File

@ -7,6 +7,7 @@ build: build-stamp
build-stamp: build-stamp:
mkdir build mkdir build
$(CC) -DFULL_PATH='"/usr/lib/csc/ceo"' -o build/ceo misc/setuid-prog.c $(CC) -DFULL_PATH='"/usr/lib/csc/ceo"' -o build/ceo misc/setuid-prog.c
$(CC) -DFULL_PATH='"/usr/lib/csc/addhomedir"' -o build/addhomedir misc/setuid-prog.c
touch build-stamp touch build-stamp
clean: clean:
@ -27,8 +28,8 @@ install: build
dh_install etc/* etc/csc/ dh_install etc/* etc/csc/
dh_install sql/* usr/share/csc/ dh_install sql/* usr/share/csc/
dh_install bin/ceo usr/lib/csc/ dh_install bin/ceo bin/addhomedir usr/lib/csc/
dh_install build/ceo usr/bin/ dh_install build/ceo build/addhomedir usr/bin/
binary-arch: build install binary-arch: build install
dh_testdir dh_testdir

View File

@ -36,9 +36,17 @@ group_min_id = 10000
group_max_id = 14999 group_max_id = 14999
group_desc = "CSC Group" group_desc = "CSC Group"
### Home Directory Options ###
skeleton_dir = "/etc/skel"
homedir_mode = 0755
homedir_min_uid = 10000
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]*$" 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"