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>
