#!/usr/bin/perl -w # This perl script will add several accounts. It can be called thusly: # # addusers foo # # foo should contain one line per account to be added. The format of each # line is two comma delimited fields, as follows: # # GECOS name # username ($USERIDLEN characters or less) # # The script attempts to create the accounts, add file quotas (be careful # check that the prototype user exists and is on the same filesystem), # and create a public_html directory. # # The script creates the file foo.pw which is foo with the account passwords. # # For now, the quota system is not in use. # # Passwords are randomly generated and consist of ($PWLEN-2) alpha # characters, followed by 2 non-alpha characters (numerals, math symbols, # punctuation, etc.). $PWLEN = 8; # Password length. $USERIDLEN = 8; # Max length of userid. $PASSWD = "/etc/passwd"; # Location of password file. # Locations of various system utilities $USERADD = "/usr/sbin/useradd"; $EDQUOTA = "/usr/sbin/edquota"; #$MKDIR = "/usr/bin/mkdir"; #$CHMOD = "/usr/bin/chmod"; #$CHOWN = "/usr/bin/chown"; # Command line arguments for useradd. $GROUP = "-g student"; $GECOS = "-c"; #$HOMEPATH = "/export/home"; $HOME = "-m"; $SHELL = "-s /bin/bash"; #$SHELL = "-s /usr/local/shells/noshell"; $PASSWDARG = "-p"; #$SKEL = "-k /usr/local/skel"; $QUOTA = "-p quotprot"; # Quota prototype user. @SCHARS = ("a".."z","A".."Z","0".."9",".","/"); # Salt characters. $SSIZE = scalar(@SCHARS); # Length of salt array. ###################################################################### umask 022; srand(time|$$); # Generate random seed. if ($#ARGV != 0) { die "$0: expecting an account file name.\n"; } if (-f "$ARGV[0].pw") { die "$0: $ARGV[0].pw already exists.\n"; } # Read account records. open(ACCOUNTS, "<$ARGV[0]") || die "$0: couldn't open $ARGV[0].\n"; @accounts = ; close(ACCOUNTS); chop(@accounts); # Read password file so that we can check that we aren't trying to # recreate existing accounts. open(OLDIDS, "<$PASSWD") || die "$0: couldn't open $PASSWD.\n"; $i = 0; while () { ($oldids[$i]) = split(/:/, $_, 2); ++$i; } close(OLDIDS); $i = 0; foreach (@accounts) # Split records apart. { ($names[$i], $ids[$i]) = split(/,/, $_, 2); # Split on comma delimiter. $ids[$i] = substr($ids[$i], 0, $USERIDLEN); # Chop, if necessary. while (substr($names[$i], -1, 1) eq " " # Remove trailing whitespace. || substr($names[$i], -1, 1) eq "\t") { chop($names[$i]); } while (substr($ids[$i], -1, 1) eq " " # Ditto. || substr($ids[$i], -1, 1) eq "\t") { chop($ids[$i]); } $passwords[$i] = &genpwd; # Create the password. $encrypts[$i] = crypt($passwords[$i], &salt); # Encrypt the password # with a random salt. # $_ .= "\t\t" . $passwords[$i]; # Append password to accounts. $_ .= "," . $passwords[$i]; # Append password to accounts. ++$i; } # Write an account file containing passwords. if (-f "$ARGV[0].pw") { die "$0: $ARGV[0].pw already exists.\n"; } open(ACCOUNTS, ">$ARGV[0].pw") || die "$0: couldn't open $ARGV[0].pw.\n"; # Create the accounts. for ($i = 0, $limit = scalar(@accounts); $i < $limit; ++$i) { if (&match($ids[$i])) # Make sure the account isn't already # in use. { print "$ids[$i] already has an account.\n"; $status = 1; # 1 actually means fail. } else { print ACCOUNTS "$names[$i]\t\t$ids[$i]\t\t$passwords[$i]\n"; $status = system("$USERADD $GROUP " . "$GECOS \"$names[$i]\" " . "$PASSWDARG \"$encrypts[$i]\" " . # "$HOME $SHELL $SKEL " . "$HOME $SHELL " . "$ids[$i] > /dev/null 2>&1"); } if ($status) { print "Couldn't create account for $names[$i].\n"; } else { print "Added account for $names[$i].\n"; $status = system("$EDQUOTA $QUOTA $ids[$i]"); if ($status) { print "Couldn't create storage quotas for $names[$i].\n"; } } } close(ACCOUNTS); chmod(0600, "$ARGV[0].pw"); chown((getpwnam("kelliher"))[2,3], "$ARGV[0].pw"); exit 0; ###################################################################### # Generate a random password. sub genpwd() { my $i; my $password = ""; my $numPunct = "!#\$%&()*+,-./0123456789:;<=>?@[]{}"; my $numPunctLen = length($numPunct); my $alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; my $alphaLen = length($alpha); for ($i = 0; $i < $PWLEN - 2; ++$i) { $password .= substr($alpha, int(rand($alphaLen)), 1); } for ($i = 0; $i < 2; ++$i) { $password .= substr($numPunct, int(rand($numPunctLen)), 1); } $password; } ###################################################################### # Generate a random salt for encryting a password. sub salt { my $salt; $salt = "$SCHARS[int(rand($SSIZE))]$SCHARS[int(rand($SSIZE))]"; } ###################################################################### # Make sure a userid isn't already in use. @oldids must have # the old ids in it. sub match { foreach (@oldids) { if ($_ eq $_[0]) { return 1; } } 0; }