Date: Wed, 7 Nov 2001 11:10:37 +0300 From: Odhiambo Washington <wash@wananchi.com> To: FBSD-Q <freebsd-questions@freebsd.org> Subject: Enteruser.pl - with attachments Message-ID: <20011107111037.C37545@ns2.wananchi.com>
next in thread | raw e-mail | index | archive | help
--NU0Ex4SbNnrxsi6C Content-Type: multipart/mixed; boundary="1UWUbFP1cBYEclgG" Content-Disposition: inline --1UWUbFP1cBYEclgG Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable [Sorry I forgot to attach the files in the previous mail] Hello list, I'm experiencing a problem with the perl script referred in the subject. I hope that there is someone already using it. My problem is just to get this script to use the group that I have specified in pw.conf. I have tried mang= ling abit but no success. If it can be prodded to prompt for a group (there is s= ome=20 section which seems to allow that although when I enable it it doesn't seem= to read and accept my input) that would be really nice. If it could also be modified to have the default shell in the Shell: [shell= s] - as in Shell: [no] that would also be neat. Below is the output of a test session. I'm attaching my pw.conf and the ent= eruser.pl script just in case someone needs to take a quick look. The only mod I've d= one to =20 the perl script is to add the organization variable. [root@ns2]#./enteruser.pl Username: test4 Full Name: Test Account 4 Password: [random] test4 Shell: [shells] -Wash S y s t e m s A d m i n i s t r a t o r -- ~\\_ =20 Odhiambo Washington \\\\ =20 Wananchi Online Ltd., `\\\\\ =20 1st Flr Loita Hse, Loita Street |\\\\\ =20 PO Box 10286,00100-NAIROBI,KE. \\\\\|__.--~~\ =20 Fax: 254 2 313985-9 _--~ / =20 Fax: 254 2 313922 /~ ////// _-~~~~' =20 E-mail: wash@wananchi.com ('-//////-// =20 URL : http://www.wananchi.com //////(((-) =20 GSM: 254 72 743 223 / 254 733 744 121 /////" =20 _///" =20 +++ Monday, n.: In Christian countries, the day after the baseball game. -- Ambrose Bierce, "The Devil's Dictionary" --1UWUbFP1cBYEclgG Content-Type: application/x-perl Content-Disposition: attachment; filename="enteruser.pl" Content-Transfer-Encoding: quoted-printable #!/usr/bin/perl=0A#=0A# NOTE: Install Perl5 and reference #!/usr/local/bin/= perl if you have an older=0A# version of FreeBSD=0A#=0A# This software is i= ntended for distribution under the same terms and spirit=0A# as FreeBSD.=0A= #=0A# This script was originally authored by Dan Howard <dannyman@dannyland= .org>=0A# for EnterAct, LLC, 1998. (http://www.enteract.com/)=0A#=0Ause Fcn= tl ':flock';=0A#use Getopt::Std;=0A=0A# Global, user-customizeable configs= =0Amy $pw_path =3D '/usr/sbin/pw';=0Amy $pw_conf_path =3D '/etc/pw.conf';= =0Amy $sendmail_path =3D '/usr/sbin/sendmail';=0Amy $welcome_message_path = =3D '/etc/adduser.message';=0Amy $logfile =3D '/var/log/enteruser.log';=0Am= y $organization =3D 'Wananchi Online';=0Amy $domain =3D `/bin/hostname`;=0A= #my $lockfile =3D '/var/run/enteruser.LOCK';=0A=0A### Forward declarations = ###=0A# Main functions=0Asub enteruser;=0Asub queueuser;=0A# Queueuser help= ers=0Asub queueadd;=0Asub queuelist;=0Asub queuedel;=0Asub queuedo;=0A# Com= mon helpers=0Asub get_user_data;=0Asub print_user_data;=0Asub add_user;=0A#= UI=0Asub get_fullname;=0Asub get_password;=0Asub get_shell;=0Asub get_user= name;=0A#sub get_billing_id;=0A#sub get_group;=0A#sub get_referral;=0A# Gen= eric helpers=0Asub append_file;=0A=0A### START PROGRAM ###=0Aif( $< !=3D 0 = ) {=0A print "You must be root to run $0!\n";=0A exit -1;=0A}=0A=0A# Here's= an example of how you could use GetOpt to extend functionality, but I=0A# = never was too keen on this example. One possibility is to set various=0A# = defaults for a queueuser operation, or change the path for the welcome=0A# = message.=0A#=0A# One possibility that has excited me on occasion has been t= he idea of setting=0A# input through the command-line, which could ease the= lives of advanced users=0A# somewhat, but not enough that I've bothered to= try.=0A#=0A# getopts('c');=0A# # -c is for curt, meaning no welcome messag= e=0A# if( $opt_c ) {=0A# print "Will not send welcome message.\n";=0A# $w= elcome_message_path =3D '';=0A# }=0A=0Aif( $0 =3D~ /queueuser/ ) {=0A &queu= euser();=0A}=0Aelse {=0A &enteruser();=0A}=0A### END PROGRAM ###=0A=0Asub= enteruser {=0A my %newuser;=0A=0A my $y_or_n;=0A =0A %newuser =3D &get_use= r_data;=0A print "\nVerify User Information\n";=0A print "-----------------= ------\n";=0A &print_user_data(%newuser);=0A print "\nIs this okay? (Y/n) "= ;=0A $y_or_n =3D <>;=0A if( $y_or_n !~ /^n/i ) {=0A &add_user(%newuser);= =0A }=0A}=0A=0Asub queueuser {=0A my @userqueue;=0A my $choice;=0A=0Awhile(= 1) {=0A my $yn;=0A=0A print<<__MENU;=0A=0A Please Select Operation=0A -= ----------------------=0A [A]dd a user to the queue=0A [L]ist users in = the queue=0A [D]elete user from the queue=0A [P]rocess users in queue= =0A [Q]uit this program=0A__MENU=0A print "What would you like to do? ";= =0A $choice =3D <>;=0A if( $choice =3D~ /^a/i ) {=0A LAME: { # the LAME= kludge=0A push @userqueue, &queueadd;=0A }=0A print "Add another? (= Y/n) ";=0A $yn =3D <>;=0A goto LAME unless $yn =3D~ /^n/i;=0A }=0A el= sif( $choice =3D~ /^l/i ) {=0A &queuelist(@userqueue);=0A }=0A elsif( $= choice =3D~ /^d/i ) {=0A @userqueue =3D &queuedel(@userqueue);=0A }=0A = elsif( $choice =3D~ /^p/i ) {=0A @userqueue =3D &queuedo(@userqueue);=0A = }=0A elsif( $choice =3D~ /^q/i ) {=0A if( @userqueue ) {=0A print "T= here are unprocessed users in your queue.\n";=0A print "If you quit now,= they will be lost!\n";=0A print "Do you really want to quit? (y/N) ";= =0A $choice =3D <>;=0A if( $choice =3D~ /^y/i ) {=0A exit(0);=0A = }=0A }=0A else {=0A exit(0);=0A }=0A }=0A else {=0A print "= \nHuh?\n";=0A }=0A }=0A}=0A =0A# Pretty much just enteruser, only we stay = within queueuser=0Asub queueadd {=0A my %newuser;=0A=0A my $y_or_n;=0A =0A = %newuser =3D &get_user_data;=0A print "\nVerify User Information\n";=0A pri= nt "-----------------------\n";=0A &print_user_data(%newuser);=0A print "\n= Is this okay? (Y/n) ";=0A $y_or_n =3D <>;=0A if( $y_or_n !~ /^n/i ) {=0A r= eturn {%newuser};=0A }=0A}=0A=0Asub queuelist {=0A my @userlist =3D @_;=0A = my $user;=0A=0A for $user (@userlist) {=0A printf("%8s %16s %10s %4s\n", = =0A $user->{username}, $user->{password},=0A $user->{fullname}, $user->= {shell});=0A }=0A}=0A=0Asub queuedel {=0A my @userlist =3D @_;=0A my $goner= ;=0A my ($i, $confirm);=0A=0A &queuelist(@userlist);=0A print "Which user d= o you wish to remove? ";=0A $goner =3D <>;=0A chomp $goner;=0A for $i ( 0 .= . $#userlist ) {=0A if( $userlist[$i]->{username} eq $goner ) {=0A print= "\nConfirm User Deletion\n";=0A print "---------------------\n";=0A &p= rint_user_data(%{$userlist[$i]});=0A print "Remove this user from your qu= eue? (Y/n) ";=0A $confirm =3D <>;=0A if( $confirm !~ /^n/i ) {=0A sp= lice(@userlist,$i,1);=0A print "User $goner removed from queue.\n";=0A = }=0A else {=0A print "Okay then, we'll leave this one alone.\n";=0A = }=0A }=0A }=0A return @userlist;=0A}=0A=0Asub queuedo {=0A my @userlist = =3D @_;=0A my $i;=0A=0A for $user (@userlist) {=0A if( $user->{username} )= {=0A print "\n>>> ADDING USER ", $user->{username}, ":\n";=0A &add_use= r(%{$user});=0A }=0A }=0A return;=0A}=0A=0A# Self-explanatory ...=0Asub pr= int_user_data {=0A my %user =3D @_;=0Aprint<<__EOUD;=0A username: $user{u= sername}=0A fullname: $user{fullname}=0A password: $user{password}=0A = shell: $user{shell}=0A__EOUD=0A}=0A=0A# Get each piece of user data, ca= lling appropriate get_ function until it=0A# returns 1=0Asub get_user_data = {=0A my %user;=0A# while( $user{group} eq '' ) { $user{group} =3D &get_grou= p; }=0A while( $user{username} eq '' ) { $user{username} =3D &get_username;= }=0A while( $user{fullname} eq '' ) { $user{fullname} =3D &get_fullname; }= =0A while( $user{password} eq '' ) { $user{password} =3D &get_password; }= =0A while( $user{shell} eq '' ) { $user{shell} =3D &get_shell; }=0A return = %user;=0A}=0A=0A# Here's an example of a custom function used by EnterAct. = Here we ask=0A# additionally for a 'Billing ID' to be stored in the log=0A= # sub get_billing_id {=0A# print " Billing ID: ";=0A# m= y $billing_id =3D <>;=0A# chomp $billing_id;=0A# if( $billing_id =3D~ /^\= d+$/ ) {=0A# return $billing_id;=0A# }=0A# print "I'm sorry, but I was = hoping for a number.\n";=0A# return '';=0A# }=0A=0Asub get_fullname {=0A p= rint " Full Name: ";=0A my $fullname =3D <>;=0A chomp $f= ullname;=0A if( $fullname eq '' ) {=0A return "J. Doe";=0A }=0A if( $fulln= ame =3D~ /^[\w\s\.\&\']*$/ ) {=0A return $fullname;=0A }=0A print "Names s= hould be alphanumeric.\n";=0A return '';=0A}=0A=0A# Here's another example = of how you might want to specify going about setting=0A# group names. This= is an EnterAct-specific example which prompts for a few=0A# different acce= ptable groups.=0A# sub get_group {=0A# while(1) {=0A# print "Choose from= : dialin, mailbox, loyola, nologin\n";=0A# print " Which= group? ";=0A# my $group =3D <>;=0A# if( $group =3D~ /^d/i ) {=0A# r= eturn 'dialin';=0A# }=0A# elsif( $group =3D~ /^m/i ) {=0A# return 'm= ailbox';=0A# }=0A# elsif( $group =3D~ /^l/i ) {=0A# return 'loyola';= =0A# }=0A# elsif( $group =3D~ /^n/i ) {=0A# return 'nologin';=0A# = }=0A# }=0A# }=0A=0A# This one I like. It'll generate a random password if= none is entered, using=0A# an algorithm that results in something a little= easier to tell a customer=0A# over the phone than what pw generates but th= at should still be quite=0A# unpredictable.=0A#=0A# If a password is entere= d, it does a very basic sanity check on it to=0A# determine if it might be = easily crack-able.=0Asub get_password {=0A my ($file, $confirm);=0A my @che= ck_files =3D ('/etc/passwd', '/usr/share/dict/words');=0A my @ary =3D ( 0 .= . 9, 'A' .. 'Z', 'a' .. 'z', 'z', '!', '$', '%');=0A=0A print " = Password: [random] ";=0A my $password =3D <>;=0A chomp $password;=0A if( $p= assword ne '' ) {=0A foreach $file (@check_files) {=0A if( (system ("/us= r/bin/grep", "-qw", $password, $file))/256 =3D=3D 0 ) {=0A print "Ewww, = no. That password is found in $file.\n";=0A print "This password is ine= xcusably lame, do you really want it? (Y/n) ";=0A $confirm =3D <>;=0A = if( $confirm !~ /^n/i ) {=0A return $password;=0A }=0A else {=0A= return '';=0A }=0A }=0A }=0A }=0A else {=0A my $pw_len =3D rand= (5)+6;=0A for(1..$pw_len) {=0A $password .=3D $ary[rand(@ary)];=0A }=0A= }=0A return $password;=0A}=0A=0A# Another custom function used at EnterAct= . This one actually got much more=0A# sophisticated with time. Seen here = is an earlier version, that could still=0A# be interesting.=0A# =0A# sub ge= t_referral {=0A# my @ary =3D (=0A# 'Current customer',=0A# 'Word= of mouth',=0A# 'Additional account',=0A# 'Microcenter',=0A# = 'CNET',=0A# 'Newsgroups',=0A# 'Loyola',=0A# 'Byte By Byte',= =0A# 'Chicago Computer Guide',=0A# 'Digital Chicago',=0A# 'N= ational-Louis',=0A# 'Lake Forest College',=0A# 'Web',=0A# 'P= hone book',=0A# );=0A# =0A# foreach $n (0..@ary-1) {=0A# print " ", $n+= 1, "\) $ary[$n]\n";=0A# }=0A# =0A# print "Enter referral numer or other: = ";=0A# my $referral =3D <>;=0A# chomp $referral;=0A# if( $referral =3D~ = /^\d+$/ && $ary[$referral-1] ) {=0A# $referral =3D $ary[$referral-1];=0A#= }=0A# return $referral;=0A# }=0A=0A# This function will determine what s= hells are available in $pw_conf_path and=0A# offer these as choices=0Asub g= et_shell {=0A my($i, $shell, $shellstr, $default);=0A $shellstr =3D `/usr/b= in/grep ^shells $pw_conf_path`;=0A $shellstr =3D~ s/.*?=3D\W*(.*)/$1/;=0A c= homp $shellstr;=0A my @shells =3D split(/\W+/, $shellstr);=0A $default =3D = $shells[0]; # Default shell is first choice listed.=0A $default or die "Not= enough shells in $pw_conf_path!";=0A print " Shell: [$defa= ult] ";=0A $shell =3D <>;=0A chomp $shell;=0A $shell =3D $default unless $s= hell;=0A for $i ( 0 .. $#shells ) {=0A if( $shell eq $shells[$i] ) {=0A = return $shell;=0A }=0A }=0A print "\"$shell\" is not a valid shell.\n";=0A= print "Please select from among:\n @shells\n";=0A return '';=0A}=0A=0A# = If you are using a more modern version of FreeBSD and want to use usernames= =0A# greater than eight characters, you need to change this function. Add/= remove=0A# checks as desired.=0Asub get_username {=0A print " = Username: ";=0A my $username =3D <>;=0A chomp $username;=0A $usernam= e =3D~ tr/[A-Z]/[a-z]/;=0A if( length($username) > 8 ) {=0A print "No, tha= t username is too long.\n";=0A print "Usernames must be eight of fewer cha= racters.\n";=0A return '';=0A }=0A if( length($username) < 3 ) {=0A print= "No, that username is too short.\n";=0A print "Usernames must be three or= more characters in length.\n";=0A return '';=0A }=0A if( $username !~ /^[= a-z0-9]*$/ ) {=0A print "No, that username's not good.\n";=0A print "User= names should consist solely of alphanumeric characters.\n";=0A return '';= =0A }=0A if( $username !~ /^[a-z]/ ) {=0A print "I'm sorry, but usernames = shouldn't start with numbers.\n";=0A return '';=0A }=0A if( (system "/usr/= bin/id $username 2> /dev/null > /dev/null")/256 =3D=3D 0 ) {=0A print "Ouc= h - that one's taken already.\n";=0A return '';=0A }=0A if( (system "/usr/= bin/grep -q ^$username: /etc/aliases")/256 =3D=3D 0 ) {=0A print "Ouch - t= hat one's claimed as a mail alias.\n";=0A return '';=0A }=0A return $usern= ame;=0A}=0A=0A# Calls pw to enter a user into the system. Did you properly= configure=0A# /etc/pw.conf?=0Asub add_user {=0A my %user =3D @_;=0A my $lo= gline;=0A my $username =3D $user{username};=0A my $fullname =3D $user{fulln= ame};=0A my $password =3D $user{password};=0A my $shell =3D $user{shell};= =0A# my $group =3D $user{group};=0A=0A my $oldbuf =3D $|;=0A $| =3D 1;=0A= =0A # It's nice to finish what we start.=0A local $SIG{INT} =3D 'IGNORE';= =0A=0A print "Running pw ... ";=0A open( PW, =0A "| $pw_path useradd $user= name -c \"$fullname\" -m -s $shell -h 0" )=0A# "| $pw_path useradd $userna= me -c \"$fullname\" -g $group -m -s $shell -h 0" )=0A or die "$pw_path fai= lure: $!";=0A print PW $password, "\n";=0A close PW or warn "$pw_path exite= d on $?: $!";=0A print "DONE!\n";=0A=0A print "Creating public directories = ... ";=0A system("/bin/mkdir", "/home/$username/public_html");=0A system("/= usr/sbin/chown", "-R", "$username.$username", "/home/$username/public_html"= );=0A# system("/usr/sbin/chown", "-R", "$username.$group", "/home/$username= /public_html");=0A print "DONE!\n";=0A=0A if( -s $welcome_message_path ) {= =0A print "Queueing welcome message ... ";=0A open( WELCOME, $welcome_mes= sage_path ) =0A or die "Couldn't open $welcome_message_path: $!";= =0A open( MAIL, "| $sendmail_path -t " )=0A || die "Couldn't open pipe = to $sendmail: $0";=0A local $SIG{PIPE} =3D sub { die "Couldn't open pipe t= o $sendmail: $0" };=0A select MAIL;=0A print<<__MAIL;=0ATo: $username\@$d= omain ($fullname)=0ASubject: Welcome to $organization!=0A=0A__MAIL=0A whil= e( <WELCOME> ) {=0A # This is better than exec()'ing arbitrary code as ro= ot, agreed?=0A s/\$name/$username/g;=0A s/\$fullname/$fullname/g;=0A = s/\$password/$password/g;=0A print unless /^#/;=0A }=0A close MAIL || d= ie "Error completing mail operation: $0";=0A select STDOUT;=0A print "DON= E!\n";=0A }=0A=0A print "Logging ... ";=0A $logline =3D localtime() . " $0 = " . "$username (" . (getpwnam($username))[2] . "/" . (getpwnam($username))[= 3] . ") \"$fullname\"";=0A# $logline =3D localtime() . " $0 " . "$username/= $group (" . (getpwnam($username))[2] . "/" . (getpwnam($username))[3] . ") = \"$fullname\"";=0A &append_file($logfile, $logline);=0A print "DONE!\n";=0A= =0A $| =3D $oldbuf;=0A}=0A=0Asub append_file {=0A my($filename,$line) =3D @= _;=0A=0A open(FH, ">>$filename") or warn=0A "Can't open $logfile: $!";=0A = flock(FH,LOCK_EX);=0A seek(FH, 0, 2);=0A print FH $line, "\n";=0A close(FH)= ;=0A flock(FH, LOCK_UN);=0A}=0A --1UWUbFP1cBYEclgG Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pw.conf" defaultpasswd no reuseuids yes reusegids no #nispasswd no skeleton no newmail /etc/adduser.message logfile /var/log/newusers.log-`/bin/date +%Y-%m-%d` home /home shellpath /bin:/sbin:/usr/local/bin:/usr/compat/linux/bin shells sh, csh, bash, tcsh, ksh, zsh, no, date defaultshell no defaultgroup 1004 #extragroups wheel, staff #defaultclass no minuid 1000 maxuid 1000 - 65534 mingid 1000 maxgid 1000 - 65534 #expire_days no #password_days no --1UWUbFP1cBYEclgG-- --NU0Ex4SbNnrxsi6C Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (FreeBSD) Comment: For info see http://www.gnupg.org iD8DBQE76Ox9n7LIsuxjem8RAppoAJ9Z3vW9+fANOEDdQ4Y5Fp776z4e1QCePN/+ Ya0VAXgM4vTsW5IFP9kKgBw= =DokJ -----END PGP SIGNATURE----- --NU0Ex4SbNnrxsi6C-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011107111037.C37545>