Summary: Adding user accounts in bulk

From: Mohammed Moin Uddin (pablo@elijah.crcc.uh.edu)
Date: Fri Oct 01 1993 - 10:17:39 CDT


original question:
____________________________________________________________________________
        We have a SS10/41 running sunos 4.1.3 and would like to add a few
hundred accounts at a time. I can do this by running the "add_user" script
in a "for each" loop, but I would also like to give each user a distinct initial
password. Is this possible without logging into each new account and running
the passwd command?
___________________________________________________________________________

        I apologise for not stating that I was looking for a way to avoid
setting the initial passwords manually.

selected responses:

>From zdv123@zam092.zam.kfa-juelich.de Wed Sep 29 06:18:12 1993

Hallo,
no problem. We have a joinuser script, which will work in interactive
and in noninteractive mode and is primarly based on add_user.
But it also supports an initial password, which is accomplished by an
relative short C-Program. You just have to
use:
    getpwent,
    crypt,
    putpwent.

Look at the related man pages.

>From storm@uni-paderborn.de Wed Sep 29 06:51:11 1993

I myself wouldn`t care too much and write a short C program instead (just append to
/etc/passwd, use the encrypt() system call to set the passwd column).

Regards, Markus

>From pjw@ccci.com Wed Sep 29 07:25:14 1993

Use expect to drive passwd -- stock example. Use archie to find expect.

>From stern@sunne.East.Sun.COM Wed Sep 29 07:47:08 1993

try
        # passwd fred

>From shandelm@jpmorgan.com Wed Sep 29 07:51:44 1993

Try:

1) Create a file with each persons UID and password (1st and 2nd field resp.)
then

foreach i (`nawk '{print $1}' /tmp/initial_passwds`)
    set initpass = `grep $i /tmp/initial_passwds | nawk '{print $2}'`
    passwd $i <<EOF
$initpass
$initpass
EOF
end

Or something along these lines.

   -- Joel

 
>From lmcguyb@LMC.ericsson.se Wed Sep 29 08:16:08 1993

Hi,

Just use the program below. It will give you a passwd based on what
you give it as an input (I use the user name as input).

You can change the "DG" for something else (it's the encryption key).

Good Luck.

***********************************************************

/* passkey.c - 93jan28 Guy Boudreault
 *
 * generates an encrypted password from the 1st argument.
 */

#include <stdio.h>

char *crypt();

main(argc, argv)
int argc;
char **argv;
{
char psw_crypt[13 + 1];

if ( argc < 2 ) {
        printf ("Usage: passkey <string>\n");
        exit (1);
        }

strcpy ( psw_crypt, crypt (argv[1], "DG") );

printf ( "%s\n", psw_crypt );

}

>From shelden@spoke.law.cornell.edu Wed Sep 29 08:54:53 1993

Sure. Whenever I write an adduser script, I have it generate a
random password, and use that password as the initial person's
password. Keeps many future problems at bay.

Below is some perl to generate and encrypt random passwords.
You could either use my code to roll your own adduser program,
or to filter /etc/passwd after you run add_user.

#! /usr/local/bin/perl -w

srand($$|time);
$ascii_passwd = &pw_generate; # What the user must type
$epasswd = &pw_encrypt($ascii_passwd); # What goes in /etc/passwd

#------------------------------------------------------------------------------
# Generate funky random password:
#------------------------------------------------------------------------------
sub pw_generate {
        local(@passset, $rnd_passwd, $randum_num);
        local($randum_num);
        
        # Since 1 ~= l and 0 =~ O, don't generate passwords with them.
        # This will just confuse people using ugly fonts.
        #
        @passset = ('a'..'k', 'm'..'z', 'A'..'N', 'P'..'Z', '2'..'9');
        $rnd_passwd = "";
        for ($i = 0; $i < 8; $i++) {
                $randum_num = int(rand($#passset + 1));
                $rnd_passwd .= @passset[$randum_num];
        }
        return $rnd_passwd;
}
#-----------------------------------------------------------------------------
# Returns its argument encrypted with a random salt.
#-----------------------------------------------------------------------------
sub pw_encrypt {
        local($passwd) = @_;
        local($ascii_salt, $randum_num, @passset, $epasswd);

        @passset = ('a'..'k', 'm'..'z', 'A'..'N', 'P'..'Z', '2'..'9');
        $ascii_salt = "";
        for ($i = 0; $i < 10; $i++) {
                $randum_num = int(rand($#passset + 1));
                $ascii_salt .= @passset[$randum_num];
        }
        $salt = `echo "$ascii_salt" | /usr/lib/makekey`;
        $epasswd = crypt($passwd, $salt);
        
        return $epasswd

}

>From RGolshan@UH.EDU Wed Sep 29 08:32:02 1993

#!/bin/sh5
# By Jerry on 1/14/92 to get rid of dumb questions.
# Again on 2/12/92 to do all of this in a daemonic way
# with metadata files sent over from abacus into /arroz/ssra/Add
# directory. Runs from root with cron every hour. If there are
# no .add files, it goes back to sleep, if there are .add files,
# it processes each of them.
if [ ! -f /arroz/ssra/Add/*.add ]
  then
    exit
fi
PATH=/etc/sec:/usr/etc/sec:/bin:/usr/local/bin:/usr/bin:/usr/ucb
export PATH
UID_MAX=32000
umask 022
if test ! -w /etc/passwd
  then
    echo "Please su to root first."
    exit 1
fi
# Trap signals
trap '/etc/unlockpw ; exit 1' 1 2
# Define location of metadata files
ADDDIR=/arroz/ssra/Add
# Get time of day in seconds
TICKS=`perl -e 'print time();'`
# Lock password file
/etc/lockpw
exstat="$?"
if test $exstat -ne 0
then
  exit $exstat
else
  trap '/etc/unlockpw ; exit 0' 0
fi
cd ${ADDDIR}
if [ "${?}" -ne 0 ]
  then
    echo "Unable to cd to add directory ${ADDDIR}"
    exit 1
fi
# Get new user's login name
# Start with the first line
# While there are .add files in the direcory, do this for each line&file
ADDFILE=$1
grep -iv nodecopy ${ADDDIR}/${ADDFILE} | sed 's/ //' | grep -v "^$" > ${ADDDIR}/add$$.tmp
mv ${ADDDIR}/add$$.tmp ${ADDDIR}/${ADDFILE}
REP=0
NUMLINES=`wc -l ${ADDDIR}/${ADDFILE} | awk '{print $1}'`
while [ $REP -lt $NUMLINES ]
        do
                REP=`expr $REP + 1`
                 cd ${ADDDIR}
                if [ "${?}" -ne 0 ]
                        then
                            echo "Unable to cd to add directory ${ADDDIR}"
                            exit 1
                fi
                RECORD=`sed -n ${REP}p $ADDFILE`
    USERNAME=`echo $RECORD | tr A-Z a-z | awk '{print $1}'`
    PASSWORD=`echo $RECORD | tr A-Z a-z | awk '{print $2}' | /var/adm/bin/crypt16`
    NAME=`echo $RECORD | sed -e 's/,//' | awk '{print $9, $8}'`
    LOGGROUP=`echo $RECORD | tr A-Z a-z | awk '{print $5}'`
# Give everyone csh by default
    LSHELL=/bin/csh
##### This should be based on filesystems.pl in future...#####
    PARENT=/fajitas
# See if it is a class account, st account, or other, for disk quota
    USERCODE=`echo $RECORD | awk '{print $4}'`
        n=`expr ${n}+1`
    case $USERCODE in
      3|4) QUOTA=1;;
      *) QUOTA=0;;
    esac
# See if user already exists in passwd file, if so exit.
    if grep -s "^${USERNAME}:" /etc/passwd
      then
        /etc/unlockpw
        echo "User ${USERNAME} already in /etc/passwd file."
        exit 5
    fi
# Get the user ID for the new user. Sort the passwd file on uid,
# get the largest uid, validity check it as a valid number,
# then add one to it to get the new uid.
  UID=`sort -nt: +2 -3 /etc/passwd | tail -1 | cut -d: -f3 | sed -n '/[0-9][0-9]*/p'`
# Check for valid UID
  if test ! "${UID}"
    then
      echo ''
      echo "The password file /etc/passwd may be corrupt!"
      echo "Exiting ${0} script. New entry not created!"
      /etc/unlockpw
      exit 1
   fi
   if test "${UID}" -gt ${UID_MAX}
     then
       echo ''
       echo "A uid greater that the maximum allowed," ${UID_MAX} "was found."
       echo "Exiting ${0} script. New entry not created!"
       /etc/unlockpw
       exit 1
   fi
   UID=`expr "${UID}" + 1`
# Get the group ID for the new user
   GID=`grep "^${LOGGROUP}:" /etc/group | cut -d: -f3`
   if test ! "${GID}"
     then
       GID=15
   fi
# Add the user to the password file.
   echo "${USERNAME}:*:${UID}:${GID}:${NAME}:${PARENT}/${USERNAME}:${LSHELL}" >> /etc/passwd
   if [ -f /usr/etc/mkpasswd -a -f /etc/passwd.pag ]
     then
        /etc/unlockpw
       ( cd /etc ; /usr/etc/mkpasswd -u passwd )
   fi
# Add the user to the auth file
   if `test -f /etc/auth.pag -a -f /usr/etc/sec/setauth`
     then
       DEFPASSMINLIFE=0
       DEFPASSMAXLIFE=180
       MAXPASSLIFE=`expr "${DEFPASSMAXLIFE}" \* 24 \* 60 \* 60`
       MINPASSLIFE=${DEFPASSMINLIFE}
       MINPASSLIFE=`expr "${DEFPASSMINLIFE}" \* 24 \* 60 \* 60`
       AUTHMASK=07
       echo "${UID}:$PASSWORD:${TICKS}:${MINPASSLIFE}:${MAXPASSLIFE}:${AUTHMASK}:0:${UID}:00:00:00" | /usr/etc/sec/setauth
   fi
# Give user a quota for parent disk
  PROTOUSER=`echo $PARENT | sed -e 's#\/##'`
  if test $QUOTA -eq 1
    then
      /etc/edquota -p ${PROTOUSER}5 $USERNAME
    else
      /etc/edquota -p ${PROTOUSER}10 $USERNAME
  fi
# Create home and bin directories, and set-up files
  cd "${PARENT}"
  if [ "${?}" -ne 0 ]
    then
      echo "Unable to cd to parent directory ${PARENT}"
      exit 1
  fi
# Create bin directory
  for I in "${USERNAME}" "${USERNAME}/bin"
    do
      if [ -d "${I}" ]
        then
          echo "${PARENT}/${I} already exists."
        else
          mkdir "${I}"
          chmod 0751 "${I}"
          /etc/chown "${USERNAME}" "${I}"
          chgrp "${LOGGROUP}" "${I}"
      fi
    done
# Create .profile, .login, .cshrc files in home directory
     for I in .profile .login .cshrc
       do
         if [ -s "${USERNAME}/${I}" ]
           then
             echo "${PARENT}/${USERNAME}/${I} already exists."
           else
             cp /usr/skel/${I} "${USERNAME}/${I}"
             chmod 0751 "${USERNAME}/${I}"
             /etc/chown "${USERNAME}" "${USERNAME}/${I}"
             chgrp "${LOGGROUP}" "${USERNAME}/${I}"
         fi
       done
# Loop back to beginning
done
# Unlock the password and group files
      /etc/unlockpw
# Get rid of this file, now that we are finished with it (hide it)
mv /arroz/ssra/Add/$ADDFILE /arroz/ssra/Add/Archive
exit 0

>From beck@amisk.cs.ualberta.ca Wed Sep 29 13:24:23 1993
 
        Yuck.. I manage the undergraduate user accounts here.. I have
to add on the order of 1500 at a time. I never use add_user, too slow
and awkward. The easy way that I have found is to simply write a
small perl (or shell) script that reads a list of names (for the gcos
(finger) field) and generates a file full of entries for /etc/passwd,
keeping a copy of plain text passwords to give to each user.

        Once I have the entries generated I then have a script to read
them, make their home directories, copy in my default rc files, and
chown everything to be owned by them.
< stuff deleted >
        

Thanks for your responses:

>From zdv123@zam092.zam.kfa-juelich.de Wed Sep 29 06:18:12 1993
>From Chris_Baldwin.DlosLC@xerox.com Wed Sep 29 06:42:51 1993
>From storm@uni-paderborn.de Wed Sep 29 06:51:11 1993
>From pjw@ccci.com Wed Sep 29 07:25:14 1993
>From stern@sunne.East.Sun.COM Wed Sep 29 07:47:08 1993
>From shandelm@jpmorgan.com Wed Sep 29 07:51:44 1993
>From lmcguyb@LMC.ericsson.se Wed Sep 29 08:16:08 1993
>From shelden@spoke.law.cornell.edu Wed Sep 29 08:54:53 1993
>From RGolshan@UH.EDU Wed Sep 29 08:32:02 1993
>From pjc@denver.ssds.COM Wed Sep 29 10:38:50 1993
>From beck@amisk.cs.ualberta.ca Wed Sep 29 13:24:23 1993
>From kmah@DCS-Systems.COM Wed Sep 29 15:06:26 1993
>From jingoro@rahul.net Wed Sep 29 20:11:07 1993
>From pluto!perryh@neon.rain.com Thu Sep 30 00:00:37 1993



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:08:20 CDT