parent
8577703511
commit
2828ed6997
@ -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) |
Loading…
Reference in new issue