[1739] in SIPB_Linux_Development

home help back first fref pref prev next nref lref last post

adduser/cleanusers scripts

daemon@ATHENA.MIT.EDU (Edwin Foo)
Tue Jul 29 10:53:17 1997

To: linux-dev@MIT.EDU
Cc: efoo@MIT.EDU, fubob@MIT.EDU
Reply-To: efoo@MIT.EDU
Date: Tue, 29 Jul 1997 10:52:46 -0400
From: Edwin Foo <efoo@hesed.mit.edu>


Hi,

Seeing as how people often want to add local users to their systems
(including me), I thought it be might nice to hack the default adduser
script to DTRT. I've been using this now for a few months on my own box and
it seems to work fine; I thought maybe you guys might see fit to clean it
up and add it to the Linux-Athena distribution if you think it is useful.

I've come up with two scripts, adduser and cleanusers. Adduser is derived
from the default /usr/sbin/adduser script (which should be renamed to
adduser.old after installation). It is responsible only for adding local
accounts, and is aware of passwd.local and group.local as well. Cleanusers
introduces a new userlist in /etc/athenausers, which handles maintenance of
the athena-logins.

After running adduser to add a new local user, you run cleanusers to
regenerate the real /etc/passwd file along with allowed Athena logins. My
premise was that I wanted passwd.local and group.local to truly only
contain "local" information, and that I'd want Athena login information to
stay out of it (this dates back to when people automatically got added to
/etc/passwd if they logged in at the console; I wanted to immediately flush
their entries after they left and allow only people on my list to log in
through telnet).

I guess it'd be simpler for you to just look at the code, so here it
is. I'm not a csh/bash hacker, so don't laugh too hard. But let me know
what you think.

------- /usr/local/sbin/adduser --------

#!/bin/bash
# 
# GNU public license left out for brevity
#
# Modified by Marc Ewing <marc@redhat.com> for Red Hat Linux
# Modified by Michael K. Johnson <johnsonm@redhat.com> for optional
# shadow password support.
# Modified by Michael K. Johnson <johnsonm@redhat.com> to make it safer
# Modified by Edwin Foo <efoo@mit.edu> to work better with Linux-Athena
#    [1] FIRST_UID and FIRST_GID = 32000 instead of 500 to avoid conflicts w/
#        Moira
#    [2] Propagate changes to passwd.local and group.local, not passwd and
#        group (let cleanusers copy back over)
#    [3] comment out support for shadow passwords (not used on Linux-Athena)
#    [4] add username to list in /etc/localusers
#    [5] restart sendmail to make local maildrop active
#
#

# Everything happens too fast, so don't let the user interrupt.
trap "" 1 2 3 15

# Set a few important variables before getting started.
NUMARG=$#
LOGIN="$1"
EXIST=0

NOHOME="$2"

PASSWD="/etc/passwd.local"
PBAK="/etc/passwd.local-"	# Some programs use /etc/passwd-, others use
				# /etc/passwd.OLD.  Take your pick.
PNEW="/etc/passwd.local.new"

SHADOW="/etc/shadow.local"
SBAK="/etc/shadow.local-"
SNEW="/etc/shadow.local.new"

GROUP="/etc/group.local"
GBAK="/etc/group.local-"
GNEW="/etc/group.local.new"

PLOCK="/etc/.pwd.lock"		# Standard method of locking the password file.

DSHELL="/bin/tcsh"
DHOME="/home"
SKEL="/etc/skel"
SPOOL="/var/spool/mail"
FIRST_UID=32000
FIRST_GID=32000

LOCALUSERS="/usr/local/etc/localusers"
LBAK="/usr/local/etc/localusers-"
LNEW="/usr/local/etc/localusers.new"
CLEANUSERS="/usr/local/sbin/cleanusers"

# A few sanity checks...
if [ `id -u` != 0 ]; then
	echo "Only root may add users to the system." ; exit 1
fi

if [ $NUMARG = 0 ]; then
	echo "You need to specify the login to add; for example, \`adduser redneck'." ; exit 1
# this is the donnie memorial shell script...
fi

if id "$LOGIN" >/dev/null 2>&1 ; then
	echo "User $LOGIN already exists"
	exit 1
fi

if [ $(echo "$LOGIN" | wc -c | tr -d ' ') -gt 9 ] ; then
	# that 9 is intentional -- it counts the newline, too...
	echo "$LOGIN is over eight characters"
	exit 1
fi

if echo "$LOGIN" | grep -q : ; then
	echo "$LOGIN contains a \`:' character"
	exit 1
fi

id $LOGIN >/dev/null 2>/dev/null && EXIST=1

if [ $EXIST = 1 ]; then
	echo "The login $LOGIN already exists."
	exit 1
fi

if ln $PASSWD $PLOCK; then : ; else
	echo "$PASSWD is locked.  Try again later." ; exit 1
fi

die ()
{
  rm -f $PLOCK
  exit 1
}

# And now the program begins: 
echo "" ; echo -n "Looking for first available UID..."
NUID=`cut -f 3 -d ":" $PASSWD | sort -n | awk -v uid=$FIRST_UID '
		{ if ($1 == uid) uid = uid + 1; }
END		{ print uid; }
'`

if [ $NUID -ge 65535 ]; then
	echo "Sorry, ran out of uids."
	die
fi
echo " $NUID"


echo -n "Looking for first available GID..."
NGID=`cut -f 3 -d ":" $GROUP | sort -n | awk -v gid=$FIRST_GID '
		{ if ($1 == gid) gid = gid + 1; }
END		{ print gid; }
'`

if [ $NGID -lt $FIRST_GID ]; then
	NGID=$FIRST_GID
fi

if [ $NGID -ge 65535 ]; then
	echo "Sorry, ran out of gids."
	die
fi
echo " $NGID"

echo "" ; echo -n "Adding login: $LOGIN..."


cp $PASSWD $PBAK || die
cp $PASSWD $PNEW || die
if [ -f "$SHADOW" ] ; then
  echo "$LOGIN:x:$NUID:$NGID:RHS Linux User:$DHOME/$LOGIN:$DSHELL" | \
     cat >> $PNEW || die
  # need cat because echo won't return a return code
  cp $SHADOW $SBAK || die
  cp $SHADOW $SNEW || die
  # The date invocation is non-standard, but works with GNU date.
  # It fills in the "last changed" field with the number of DAYS
  # since epoch (86400 seconds per day; %s is second since epoch).
  echo "$LOGIN:*:$(($(date '+%s')/86400))::::::" | \
    cat >> $SNEW || die
else
  echo "$LOGIN:*:$NUID:$NGID:RHS Linux User:$DHOME/$LOGIN:$DSHELL" | \
    cat >> $PNEW || die
fi

# Add user to users group
cp $GROUP $GBAK || die
cp $GROUP $GNEW || die
sed "s/^\(users:.*[^:]\)\$/\1,$LOGIN/"'
   '"s/^\(users:.*:\)\$/\1$LOGIN/" < $GBAK > $GNEW || die

echo "$LOGIN::$NGID:$LOGIN" | cat >> $GNEW || die

mv $GNEW $GROUP
if [ -f "$SHADOW" ] ; then
  mv $SNEW $SHADOW
fi
mv $PNEW $PASSWD

rm -f $PLOCK
echo "done."

if [ "x$NOHOME" = "x" ]; then
	echo -n "Creating home directory: $DHOME/$LOGIN..."
	mkdir $DHOME/$LOGIN
	chmod 2775 $DHOME/$LOGIN
	cp -a $SKEL/.??* $SKEL/* $DHOME/$LOGIN >/dev/null 2>/dev/null
	chown -R $NUID.$NGID $DHOME/$LOGIN
	echo "done."
fi

echo -n "Creating mailbox: $SPOOL/$LOGIN..."
touch $SPOOL/$LOGIN ; chmod 660 $SPOOL/$LOGIN ; chown $NUID.mail $SPOOL/$LOGIN
echo "done."

echo ""
echo "Don't forget to set the password."
if [ "x$NOHOME" != "x" ]; then
	echo ""
	echo "The home directory for $LOGIN was set to $DHOME/$LOGIN but the directory"
	echo "was not created.  Be sure that you set it up properly."
fi

# add user to localusers file
echo Adding entry to $LOCALUSERS ...
cp $LOCALUSERS $LBAK || die
cp $LOCALUSERS $LNEW || die
echo "$LOGIN" | cat >> $LNEW || die
mv $LNEW $LOCALUSERS

# restart sendmail
/etc/rc.d/init.d/sendmail.init stop
/etc/rc.d/init.d/sendmail.init start

$CLEANUSERS

#passwd $LOGIN
#chfn $LOGIN

# EOF

------- /usr/local/sbin/cleanusers --------

#!/bin/tcsh

# clean up /etc/passwd and /etc/group by copying from passwd.local and
# group.local, then adding hesinfo information from /etc/athenausers
# to generate dialup userlist.

# Written by Edwin Foo <efoo@mit.edu> 7/25/97

echo Backing up current /etc/passwd and /etc/group...
cp -f /etc/passwd /etc/passwd-
cp -f /etc/group /etc/group-

echo Cleaning up passwd and group files...
cp -f /etc/passwd.local /etc/passwd
cp -f /etc/group.local /etc/group

echo Regenerating dialup userlist...
foreach user (`cat /etc/athenausers`)
   echo "   $user"
   /bin/athena/hesinfo $user passwd >> /etc/passwd
end

echo Done.

--------- end files ----------

-------------
MIT Computer Science '98 - Systems and Architecture    | The FooBunny
                                                       | efoo@mit.edu
DEC Cambridge Research Lab - Parallel Computing Group  | (617) 225-8826
Residential Computing Consultant (RCC) - New House     | Romans 12:9

"Love must be sincere; Hate what is evil; cling to what is good."    ><>
-------------

home help back first fref pref prev next nref lref last post