Home
| pfodApps/pfodDevices
| WebStringTemplates
| Java/J2EE
| Unix
| Torches
| Superannuation
|
| About
Us
|
Freebees - Webpage from Tacacs+ user logs
|
This perl file is called from the webpage to allow users to check their
usage. It uses the user log file written by the modified tacacs+ program
and the user payment files which contain a date and number of hours purchased
tab seperated. One line for each purchase of online time. e.g.
30/09/97 200
The administrator can check anyone's usage by using his/her password instead of the user's password. The admin user gets extra info on the webpage about the user. The user just gets his/her name at the top. Set the variable $administration_user in the code below to the appropiate user id. This file is actually run from a small C file which suid's to root. The perl system I am running on Solaris would not let me suid to root directly from the the perl program. The C file is show at the bottom of the page as is the sendmail program.
There may be a security hole in the sendmail program if it is accessiable to the general users as it runs as root and lets you send mail as any user. If in doubt do not install it. If you find a hole and how to fix it let me know. The permissions specified below only allow root and users in the other group to use the program.
This program also looks up our database to translates the user Id into a real name. You will need to remove those lookup lines or replace them with the appropiate code to access your database.
Any errors email an error message to the apporpiate person and displays an error message on the resulting webpage.
This file assumes you have a shadow password file. If not you will need to pickup the password field from the normal password file.
This file is placed in the /usr/local/etc/system.perl directory with
the following permissions
-rwx--x--- 1 root other 20624 Nov 8 13:10 acc_details.pl
#!/usr/bin/perl -w # Copyright(c) 1997 Forward Computing and Control Pty. Ltd. # written by Matthew Ford # # Return user's account details given userid and password # # Need this info # UserID and password # administation password works for all users # # Return # Page of users account details # # Process: # Check password for user if fail check password agaist administration password # Dump /var/log/users-time-dir/userid file and # /var/log/users-pay-dir/userid file $ENV{'IFS'} = '' if $ENV{'IFS'} ; # $ENV{'SHELL'} = '/sbin/sh' if $ENV{'SHELL'} ne ''; $ENV{'SHELL'} = '/sbin/sh'; $ENV{'PATH'} = '/usr/sbin:/usr/bin:/usr/local/bin'; $userdb = " /export/home/root/etc/mail/userdb.db "; $mailto = "SomeAdminUser\@your.domain.name"; # all mail to accounts $dblookup = " /usr/local/bin/dblookup "; $mailprog = ' /cww/test/cgi-bin/sendmail '; $timedir = " /var/log/users-time-dir/"; $paydir = " /var/log/users-pay-dir/"; $webtime = 0; # start with no access time chargable $timepaid = 0; # and no time paid $administration_user = "put the administrator's user id here"; $< = $>; # make effective uid the real uid # Retrieve Date &get_date; if ($ENV{'REQUEST_METHOD'} eq "GET") { $FORM_DATA = $ENV{'QUERY_STRING'}; } else { $LENGTH = $ENV{'CONTENT_LENGTH'}; # $LENGTH = 14; # for testing only while ($LENGTH) { $FORM_DATA .= getc(STDIN); $LENGTH--; } } foreach (split(/&/, $FORM_DATA)) { ($NAME, $VALUE) = split(/=/, $_); $NAME =~ s/\+/ /g; $NAME =~ s/%([0-9|A-F]{2})/pack(C,hex($1))/eg; $VALUE =~ s/\+/ /g; $VALUE =~ s/%([0-9|A-F]{2})/pack(C,hex($1))/eg; $MYDATA{$NAME} = $VALUE; } print "Content-type: text/html\n\n"; print "<HTML>\n"; print "<HEAD>\n"; print "<TITLE>Central West Web - User Account Details</TITLE>\n"; print "</HEAD>\n"; print "<BODY>\n"; print "<H1><A HREF=\"../welcome.html\"><IMG SRC=\"/gifs/images/cwwsmall.gif\""; print " ALIGN=\"BOTTOM\" ALT=\"[Image] Central West Web\"></A>"; print "User Account Details</H1>"; # print " User's ID :\n "; # chop($userid = <STDIN>); $userid = $MYDATA{'USER.ID'}; $userid =~ s/(^\s+)|(\s+$)//g; # strip leading trailing blanks if (!$userid) { # just Enter pressed print " <P><H3>The User ID is missing<P>"; print " Click on the browser's <B>Back</B> button to return to the form<BR> and fill in the User ID.</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } #print $userid , "\n"; # print " User's Password:\n "; # chop($userpasswd = <STDIN>); $userpasswd = $MYDATA{'USER.PASSWD'}; $userpasswd =~ s/(^\s+)|(\s+$)//g; # strip leading trailing blanks if (!$userpasswd) { # just Enter pressed print " <P><H3>The Password is missing<P>"; print "Click on the browser's"; print " <B>Back</B> button to return to the form<BR> and fill"; print " in the Password.</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } # try to lookup this user in the database and find his info # look through existing userdb file # email_name:info constists of name;birthdate;address;ph_No.; # # check if last 4 characters are all digits $isuserid = 1; # assume userid to start with $digits = substr($userid,length($userid)-4); # print "\n$digits\n"; $onlydigits = $digits; $onlydigits =~ s/\D//g; # remove all no-ditigs if ($digits eq $onlydigits) { # is userid $mailname = $userid . ":mailname"; # do all lookups lower case $mailname =~ y/A-Z/a-z/; if (! defined( open(USERDB, $dblookup . $userdb . $mailname . " | ")) ) { &mailerr("could not lookup '" . $userid . "' in database $userdb\n"); print "<P><H3> Internal Error<BR> Please report this to the "; print "<A HREF=\"mailto:webmaster\@cww.octec.org.au\">"; print "webmaster\@cww.octec.org.au</A></H3><P>"; print "</BODY>\n</HTML>\n"; exit 1; } $_ = <USERDB>; # get return line from lookup close(USERDB); s/\n//g; # remove all /r /n s/\r//g; #chop(); @info = split(/\s+/,$_,2); s/^\s//; # strip leading blanks # do all lookups lower case $info[0] =~ y/A-Z/a-z/; if ($info[0] ne $mailname) { # not found info field sleep(3); # wait 2 to 3 seconds print "<P><H3> Invalid User Name or Password.<P>"; print " User Names and Passwords are case sensitive.<P>"; print "Click on the browser's"; print " <B>Back</B> button to return to the form"; print "</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } $username = $info[1]; } else { $isuserid = 0; # assume is emailname $username = $userid; # make lowercase $username =~ y/A-Z/a-z/; } $userinfo = $username . ":info"; # do all lookups lower case $userinfo =~ y/A-Z/a-z/; if (! defined( open(USERDB, $dblookup . $userdb . $userinfo . " | ")) ) { &mailerr("could not lookup '" . $username . "' in database $userdb\n"); print "<P><H3> Internal Error<BR> Please report this to the "; print "<A HREF=\"mailto:webmaster\@cww.octec.org.au\">"; print "webmaster\@cww.octec.org.au</A></H3><P>"; print "</BODY>\n</HTML>\n"; exit 1; } $_ = <USERDB>; # get return line from lookup close(USERDB); s/\n//g; # remove all /r /n s/\r//g; #chop(); @info = split(/\s+/,$_,2); s/^\s//; # strip leading blanks # do all lookups lower case $info[0] =~ y/A-Z/a-z/; if ($info[0] ne $userinfo) { # not found info field sleep(3); # wait 2 to 3 seconds print "<P><H3> Invalid User Name or Password.<P>"; print " User Names and Passwords are case sensitive.<P>"; print "Click on the browser's"; print " <B>Back</B> button to return to the form"; print "</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } @userinfo = split(/;/,$info[1]); $founduser = 0; $foundpassword = 0; # check the password for this user id # get password from shadow file if (! $isuserid) { goto CHECK_ADM; } if (! defined( open(SHADOW,"/etc/shadow")) ) { &mailerr("could not open file /etc/shadow\n"); print "<P><H3> Internal Error<BR> Please report this to the "; print "<A HREF=\"mailto:webmaster\@cww.octec.org.au\">"; print "webmaster\@cww.octec.org.au</A></H3><P>"; print "</BODY>\n</HTML>\n"; exit 1; } while(<SHADOW>) { /^([^:]+)/; if ($1 eq $userid) { $founduser = 1; # found this userid ($login,$pwd) = split(/:/); $login = $login; # to shut up perl warnings $salt = substr($pwd,0,2); # print "pass " . $pwd . "\n"; if (crypt($userpasswd,$salt) eq $pwd) { $foundpassword = 1; } last; # break from this loop } } close(SHADOW); if ($founduser == 0) { # did not find user at all sleep(3); # wait 2 to 3 seconds print "<P><H3> Invalid User Name or Password.<P>"; print " User Names and Passwords are case sensitive.<P>"; print "Click on the browser's"; print " <B>Back</B> button to return to the form"; print "</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } # else try administration password CHECK_ADM: # jump here if email name $foundadm = 0; $isadm = 0; if ($foundpassword == 0) { # look for adm password if (! defined( open(SHADOW,"/etc/shadow")) ) { &mailerr("could not open file /etc/shadow\n"); print "<P><H3> Internal Error<BR> Please report this to the "; print "<A HREF=\"mailto:webmaster\@cww.octec.org.au\">"; print "webmaster\@cww.octec.org.au</A></H3><P>"; print "</BODY>\n</HTML>\n"; exit 1; } while(<SHADOW>) { /^([^:]+)/; if ($1 eq $administration_user) { # collect the adm password $foundadm = 1; # found admin user ($login,$pwd) = split(/:/); $login = $login; # to shut up perl warnings $salt = substr($pwd,0,2); if (crypt($userpasswd,$salt) ne $pwd) { sleep(3); # wait 2 to 3 seconds print "<P><H3> Invalid User Name or Password.<P>"; print " User Names and Passwords are case sensitive.<P>"; print "Click on the browser's"; print " <B>Back</B> button to return to the form"; print "</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } $isadm = 1; # access under adm password } } close(SHADOW); } if (($founduser == 0) && ($foundadm == 0)) { # did not find user at all sleep(3); # wait 2 to 3 seconds print "<P><H3> Invalid User Name or Password.<P>"; print " User Names and Passwords are case sensitive.<P>"; print "Click on the browser's"; print " <B>Back</B> button to return to the form"; print "</H3>\n"; print "</BODY>\n</HTML>\n"; exit 1; } # mailname:info name(responsable name);birthdate;address;ph; # Email_name;login;extern;internet # print "<H2> $userinfo[0]</H2>\n"; if ($isadm) { # adm using this print "\n<PRE>"; # print " ", $userinfo[0], "\n" if $userinfo[0]; print " born ", $userinfo[1], "\n" if $userinfo[1]; print " ", $userinfo[2], "\n" if $userinfo[2]; print " ", "ph. ",$userinfo[3], "\n" if $userinfo[3]; print " Email Name ",$userinfo[4], "\n" if $userinfo[4]; print " User ID ",$userinfo[5], "\n" if $userinfo[5]; print " Internet Access ",$userinfo[7], "\n" if $userinfo[7]; print " External Email ",$userinfo[6], "\n" if $userinfo[6]; print "</PRE>"; } # set up userid from info $userid = $userinfo[5]; print " your current access is"; if ($userinfo[7] eq "CWW") { print " Central West Web access and local email only."; } elsif ($userinfo[7] eq "CWE") { print " Central West Web access and World Wide Email."; } elsif ($userinfo[7] eq "INT") { print " World Wide Web access and World Wide Email." } else { &mailerr("invalid access for '" . $userid . "' in database $userdb\n"); print "</H3><P>"; print "<P><H3> Internal Error<BR> Please report this to the "; print "<A HREF=\"mailto:webmaster\@cww.octec.org.au\">"; print "webmaster\@cww.octec.org.au</A></H3><P>"; print "</BODY>\n</HTML>\n"; exit 1; } print "</H3><HR>\n"; $firsttimewrite = 0; # nothing written yet # ======================= # First time through Accumulate the hours paid for # ================================= # open user-pay-dir file for this user id $userpayfile = $paydir . $userid; # print $userpayfile; if ( defined( open(ACC, $userpayfile)) ) { # print "<HR>"; # print "<H3>Hours Purchased</H3>"; # print "<PRE>"; # print "Date of Payment Hours Purchased\n"; # print "---------------------------------\n"; # print "<BR>"; # $~ = PAYMENTS; # set up write format while ($accrec = <ACC>) { $accrec =~ s/\n//g; # remove all /r /n $accrec =~ s/\r//g; #chop($accrec); #chop($accrec); # to remove ^M from Dos @accrec = split(/\t/,$accrec); # split on tabs $datetime = $accrec[0]; $hrs = $accrec[1]; $timepaid = $timepaid + $hrs; # in hrs # write; # print $accrec[0] . " " . $accrec[1] . "\n"; } close(ACC); $hrs = $timepaid; if ($timepaid) { $firsttimewrite = 1; # wrote something here # print "------------------------------------------------------------\n"; # print "</PRE>"; print " Total World Wide Web access time purchased to date:"; print " <B>$hrs hrs </B>\n"; } else { # print "</PRE>"; } } # ======================= # First time through accumulate time used # ===================== # open user-time-dir file for this user id $usertimefile = $timedir . $userid; # print $usertimefile; if ( defined( open(ACC, $usertimefile)) ) { # print "<HR>"; # print "<H3>Access Times</H3>"; # print "<PRE>"; # print "End Date/Time of Session Duration Access Type\n" # print "------------------------------------------------------------\n"; # print "<BR>"; # $~ = ACCESSTIMES; # set up write format while ($accrec = <ACC>) { $accrec =~ s/\n//g; # remove all /r /n $accrec =~ s/\r//g; #chop($accrec); @accrec = split(/\t/,$accrec); # split on tabs $datetime = $accrec[0]; # find elapsedtime= the second last item ($elapsedtime,$duration) = split(/=/,$accrec[$#accrec-1]); if ($elapsedtime !~ /^elapsed_time/) { $duration = 0; # could not find elapsed time entry } @timearray = &calc_time($duration); $duration = $timearray[0]; if ($accrec[$#accrec] eq "acc_type=INT") { $accesstype = "World Wide Web"; $webtime = $webtime + $timearray[1]; # add these minutes } else { $accesstype = "Central West Web"; } # write; # print $accrec[0] . " " . $accrec[10] . " " .$accrec[11] . "\n"; } close(ACC); } else { # print "<HR>"; # print "<H3> No access to date.</H3>"; } $hrs = ($webtime / 60) - (($webtime % 60)/60); $mins = $webtime - ($hrs * 60); $mins =sprintf("%0.0d",$mins); if (length($mins) < 1) { $mins = "0"; } if (length($mins) < 2) { $mins = " " . $mins; } $hrs = sprintf("%0.0d",$hrs); if (length($hrs) < 1) { $hrs = "0"; } if (length($hrs) < 2) { $hrs = " " . $hrs; } if ($webtime) { $firsttimewrite = 1; # wrote something here # print "------------------------------------------------------------\n"; # print "</PRE>"; if ($timepaid) { print "<BR>"; } print " Total World Wide Web access time to date:"; print " <B>$hrs hrs $mins mins</B>\n"; } else { # print "</PRE>"; } # ============================== # First time through show summary # =============================== if ($webtime || $timepaid) { # show summary $firsttimewrite = 1; # wrote something here print "<H2>"; print " World Wide Web access left: "; $timeleft = $timepaid*60 - $webtime; if ($timeleft < 0) { $sign = "-"; $timeleft = -$timeleft; } else { $sign = ""; } $hrs = ($timeleft / 60) - (($timeleft % 60)/60); $mins = $timeleft - ($hrs * 60); $mins =sprintf("%0.0d",$mins); if (length($mins) < 1) { $mins = "0"; } if (length($mins) < 2) { $mins = " " . $mins; } $hrs = sprintf("%0.0d",$hrs); if (length($hrs) < 1) { $hrs = "0"; } if (length($hrs) < 2) { $hrs = " " . $hrs; } print "<B>$sign$hrs hrs $mins mins</B>"; print "</H2>"; } # =============================== # Second time through print out purchased hours # ================================ # open user-pay-dir file for this user id $userpayfile = $paydir . $userid; $timepaid = 0; # print $userpayfile; if ( defined( open(ACC, $userpayfile)) ) { if ($firsttimewrite) { print "<HR>"; } print "<H3>Hours Purchased</H3>"; print "<PRE>"; print "Date of Payment Hours Purchased\n"; print "---------------------------------\n"; # print "<BR>"; $~ = PAYMENTS; # set up write format while ($accrec = <ACC>) { $accrec =~ s/\n//g; # remove all /r /n $accrec =~ s/\r//g; #chop($accrec); #chop($accrec); # to remove ^M from Dos @accrec = split(/\t/,$accrec); # split on tabs $datetime = $accrec[0]; $hrs = $accrec[1]; $timepaid = $timepaid + $hrs; # in hrs write; # print $accrec[0] . " " . $accrec[1] . "\n"; } close(ACC); $hrs = $timepaid; if ($timepaid) { # print "------------------------------------------------------------\n"; print "</PRE> Total World Wide Web access time purchased to date:"; print " <B>$hrs hrs </B>"; } else { print "</PRE>"; } } # ================================ # Second time through print out usage # ================================ # open user-time-dir file for this user id $usertimefile = $timedir . $userid; $webtime = 0; # print $usertimefile; if ( defined( open(ACC, $usertimefile)) ) { if ($firsttimewrite) { print "<HR>"; } print "<H3>Access Times</H3>"; print "<PRE>"; print "End Date/Time of Session Duration Access Type\n"; print "------------------------------------------------------------\n"; # print "<BR>"; $~ = ACCESSTIMES; # set up write format while ($accrec = <ACC>) { $accrec =~ s/\n//g; # remove all /r /n $accrec =~ s/\r//g; #chop($accrec); @accrec = split(/\t/,$accrec); # split on tabs $datetime = $accrec[0]; ($elapsedtime,$duration) = split(/=/,$accrec[$#accrec - 1]); if ($elapsedtime !~ /^elapsed_time/) { $duration = 0; # could not find elapsed time entry } @timearray = &calc_time($duration); $duration = $timearray[0]; if ($accrec[$#accrec] eq "acc_type=INT") { $accesstype = "World Wide Web"; $webtime = $webtime + $timearray[1]; # add these minutes } else { $accesstype = "Central West Web"; } write; # print $accrec[0] . " " . $accrec[10] . " " .$accrec[11] . "\n"; } close(ACC); } else { if ($firsttimewrite) { print "<HR>"; } print "<H3> No access to date.</H3>"; } $hrs = ($webtime / 60) - (($webtime % 60)/60); $mins = $webtime - ($hrs * 60); $mins =sprintf("%0.0d",$mins); if (length($mins) < 1) { $mins = "0"; } if (length($mins) < 2) { $mins = " " . $mins; } $hrs = sprintf("%0.0d",$hrs); if (length($hrs) < 1) { $hrs = "0"; } if (length($hrs) < 2) { $hrs = " " . $hrs; } if ($webtime) { # print "------------------------------------------------------------\n"; print "</PRE> Total World Wide Web access time to date:"; print " <B>$hrs hrs $mins mins</B>\n"; } else { print "</PRE>"; } print "<HR>"; print "<P><A HREF=\"../welcome.html\"><IMG SRC=\"/gifs/images/cwwsmall.gif\"\n"; print " ALIGN=\"BOTTOM\" ALT=\"[Image] Central West Web\"></A>\n"; print "<A HREF=\"../welcome.html\">Central West Web, NSW, Australia</A>\n"; print "<HR><P>Copyright© 1997 Forward Computing and Control Pty. Ltd.\n"; print "<BR>ACN 003 669 994, All rights reserved. (Email forward.com.au)\n"; # print $username, "\n"; print "</BODY>\n</HTML>\n"; exit; #============================================================ sub calc_time { local($sec) = pop(@_); local($hrs,$mins,$minutes,$timestr,$timearray); # calc hours $mins = ($sec / 60) - (($sec % 60) / 60); if ($sec % 60) { # add one $mins = $mins + 1; } if ($mins < 1) { $mins = $mins + 1; } $minutes = $mins; $hrs = ($mins / 60) - (($mins % 60)/60); $mins = $mins - ($hrs * 60); $mins =sprintf("%0.0d",$mins); if (length($mins) < 2) { $mins = " " . $mins; } $hrs = sprintf("%0.0d",$hrs); if (length($hrs) < 1) { $hrs = "0"; } if (length($hrs) < 2) { $hrs = " " . $hrs; } $timestr = $hrs . " hrs " . $mins . " mins"; @timearray = ($timestr, $minutes); @timearray; } sub get_date { @days = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday', 'Saturday'); @months = ('January','February','March','April','May','June','July', 'August','September','October','November','December'); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $date = "$days[$wday], $months[$mon] $mday, 19$year at $hour\:$min\:$sec"; $shortdate = "$months[$mon] $mday, 19$year"; $shortdate = $shortdate; $date = $date; $isdst = $isdst; $yday = $yday; } sub mailerr { local($errmsg) = pop(@_); open(MAIL,"|".$mailprog) || die "Can't open mail program :$!\n"; print MAIL "To: ". $mailto . "\n"; print MAIL "From: webmaster\@cww.octec.org.au\n"; print MAIL "Subject: Error Process User's Account Details Web Request"; print MAIL " for $userid\n"; print MAIL "\n"; print MAIL " While processing user's account details request at\n "; print MAIL " " . $date . "\n"; print MAIL $errmsg . "\n\n"; close(MAIL); } #End Date/Time of Session Duration Access Type format ACCESSTIMES = @<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< $datetime, $duration, $accesstype . #Date of Payment Hours Purchased format PAYMENTS = @<<<<<<<<<<<<< @###### $datetime, $hrs .
This file is compiled with
cc acc_details.c -o acc_details
and is placed in the cgi-bin directory with the following permissions
---s--s--x 1 root other 5340 Sep 22 22:36 acc_details
/* user-acc.c */ main(argc,argv) int argc; char **argv; { setuid(0); /* user root */ setgid(1); /* group other */ execv("/usr/local/etc/system.perl/acc_details.pl",argv); }
This file is placed in the /usr/local/etc/system.perl directory with the following permissions -rwx--x--- 1 root other 20624 Nov 8 13:10 sendmail.pl This is called from the sendmail executiable shown further down
#!/usr/local/bin/perl -w # Copyright (c)1997 Forward Computing and Control Pty. Ltd. # All rights reserved ACN 003 669 994 NSW Australia. # written by Matthew Ford # # sendmail.pl # this programs sends mail after su to root # $mailprog = '/usr/local/lib/sendmail -t'; # take to from from input # $ENV{'IFS'} = '' if $ENV{'IFS'} ; # $ENV{'SHELL'} = '/sbin/sh' if $ENV{'SHELL'} ne ''; $ENV{'SHELL'} = '/sbin/sh'; $ENV{'PATH'} = '/usr/sbin:/usr/bin:/usr/local/bin'; $< = $>; # make effective uid the real uid open(MAIL,"| $mailprog"); while(<STDIN>) { print MAIL ; } close(MAIL);
This file is compiled with cc sendmail.c -o sendmail and is placed in a suitable directory with the following permissions ---s--s--- 1 root other 5340 Sep 22 22:36 sendmail
/* sendmail.c */ main(argc,argv) int argc; char **argv; { setuid(0); /* user root */ setgid(1); /* group other */ execv("/usr/local/bin/sendmail.pl", argv); }
Refer to Conditions of Use
Contact Forward Computing and Control by
©Copyright 1996-2020 Forward Computing and Control Pty. Ltd.
ACN 003 669 994