Summary Re: 3-Hour Account

From: Armand O. Lagunilla <armand_at_g-net.globe.com.ph>
Date: Mon, 16 Oct 1995 17:53:28 +0800 (SST)

Thanks to Sean Watson who sent me a script to place the ff. constraints
on the users:

 Only one login per user at a time is allowed.
 Only 2 hours of connect time is allowed in 24 hours.
 Users must have an account on the campus VMS machine (on which students get
   accounts automatically when they enroll and faculty get accounts on request).
 Users get a dynamiclly allocated IP address from a restricted list of
   hostnames (ppp0, ppp1, ppp2, etc).

I'm attaching the script for others to refer to:

> ------------public_ppp-begin--------------------------
> #!/bin/bash
> PATH=/bin:/usr/bin:/usr/lib/ppp:.:${HOME}/bin
>
> # get stty settings
> STTY=$(stty -g)
>
> # save the TTY for when we send all IO to ERRLOG
> TTY=$(tty)
>
> # set up ERRLOG to say where we want IO we don't want the user to see
> ERRLOG=.ppp_errs
>
> # set up a file for the PPPLOG variable
> PPPLOG=ppp_log
>
> # count number of time this user has logged in since the 6815 and 6820
> # lines go to the same user (ppp) there is no way to tell how many lines
> # in the rotary are in use. Someday, we may want seperate usernames for
> # separate phone lines.
> NUM_USERS=$(w -h $(whoami) | # do a w (-h = no headers) for users with my username
> wc -l | # count the lines therein
> tr -cd "1234567890") # strip everything not a digit (space/tab/etc)
>
> # set PPPDEVS here so they are easier to find/modify.
> # also this will allow us to set prefered hostnames for some users
> PPPDEVS="ppp0 ppp1 ppp2 ppp3 ppp4 ppp5 ppp6 ppp7 ppp8 ppp9"
> PPPDEVS="${PPPDEVS} ppp10 ppp11 ppp12 ppp13 ppp14 ppp15"
>
> # set PPPFLAGS here so they are easier to find/modify.
> # also this will allow us to set prefered values for some users
> #
> # note, should we try silent rather than passive? Should we put a MTU in?
> PPPFLAGS="passive"
>
> # time limits (in seconds) depends on the number of users
> case ${NUM_USERS} in
> 1) # one user: four 6820 are free / five are free and 6815 is in use
> TIMEON=$((60*60*2)) # 2 hours
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> 2) # two users: three 6820 are free / four are free and 6815 is in use
> TIMEON=$((60*60*2)) # 2 hours
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> 3) # three users: two 6820 is free / three are free and 6815 is in use
> TIMEON=$((60*60*2)) # 2 housr
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> 4) # four users: one 6820 is free / two are free and 6815 is in use
> TIMEON=$((60*60*2)) # 2 housr
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> 5) # five users: no 6820 is free / one is free and 6815 is in use
> TIMEON=$((60*60*2)) # 2 housr
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> 6) # five users: no 6820 is free and 6815 is in use
> TIMEON=$((60*60*2)) # 2 housr
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> *) # something weird happened, act like 6 users
> TIMEON=$((60*60*2)) # 2 housr
> TIMEOFF=$((60*60*24)) # 24 hours
> ;;
> esac
>
> #define a function to show a time (in h:m:s)
> timefmt ()
> {
> for S
> do
> H=$(($S / 3600))
> S=$(($S % 3600))
> M=$(($S / 60))
> S=$(($S % 60))
>
> if [ $H -eq 0 ]
> then H=""
> elif [ $H -eq 1 ]
> then H="$H hour"
> else H="$H hours"
> fi
>
> if [ $M -eq 0 ]
> then M=""
> elif [ $M -eq 1 ]
> then M="$M minute"
> else M="$M minutes"
> fi
>
> if [ $S -eq 0 ]
> then S=""
> elif [ $S -eq 1 ]
> then S="$S second"
> else S="$S seconds"
> fi
>
> # this should look like counting from 000 to 111 in binary
> [ -z "$H" -a -z "$M" -a -z "$S" ] && echo "as long as you want"
> [ -z "$H" -a -z "$M" -a ! -z "$S" ] && echo "$S"
> [ -z "$H" -a ! -z "$M" -a -z "$S" ] && echo "$M"
> [ -z "$H" -a ! -z "$M" -a ! -z "$S" ] && echo "$M and $S"
> [ ! -z "$H" -a -z "$M" -a -z "$S" ] && echo "$H"
> [ ! -z "$H" -a -z "$M" -a ! -z "$S" ] && echo "$H and $S"
> [ ! -z "$H" -a ! -z "$M" -a -z "$S" ] && echo "$H and $M"
> [ ! -z "$H" -a ! -z "$M" -a ! -z "$S" ] && echo "$H, $M, and $S"
> done
> }
>
> #define a function to log to PPPLOG
> # this was changed to put out date in seconds since midnight
> # since it is much easier to go from this to ctime format
> # than vice versa and doing math on this fromat is difficult. ASW
> ppplog ()
> {
> for state
> do
> echo "$(date +%s):${USERNAME}:${TTY##*tty}:${name}:${state}"
> done >> $PPPLOG
> }
>
> #define a function to echo to /dev/tty
> ttyecho ()
> {
> echo "$*" > ${TTY=$(tty)}
> }
>
> #explain what the time limits are
> explainlimits ()
> {
> ttyecho "You may stay connected for $(timefmt ${TIMEON})"
> ttyecho "in any period of $(timefmt ${TIMEOFF})."
> ttyecho
> }
>
> # define a function to do a normal cleanup/exit
> normal_exit()
> {
> SIG=$1
> # reset the default error handler
> trap ${SIG}
>
> # if we need a ppplog out, give one (if we don't know, then we don't need one)
> if [ "${need_ppplog_out=NO}" != "NO" ]
> then
> # also log an unexpected_close
> ppplog out unexpected_close
> # we really don't need one now
> need_ppplog_out=
> fi
> # some cleanup is uneeded unless we got a USERNAME
> if [ ! -z "${USERNAME}" ]
> then
> [ -f ${USERNAME}.lock ] && rm -f ${USERNAME}.lock
> fi
> # try to clean up ${name}.lock, but only if the lock exists and is this pid's
> if [ ! -z "${name}" ] && [ -f ${name}.lock ]
> then
> read TESTPID junk < ${name}.lock
> [ ${TESTPID} = $$ ] && rm -f ${name}.lock
> fi
> # if we know pppd's pid, send it whatever signal we just got (for good measure)
> if [ ! -z "${PPPD_PID}" ]
> then
> [ ${SIG} = EXIT] && kill ${PPPD_PID}
> [ ${SIG} != EXIT] && kill -${SIG} ${PPPD_PID}
> # no need to send it a second signal
> PPPD_PID=
> fi
> exit 0
> }
>
> trap "normal_exit EXIT" EXIT
> trap "normal_exit HUP" HUP
> trap "normal_exit INT" INT
> trap "normal_exit TERM" TERM
>
> #tell the user what the time limits are
> ttyecho "You have made connection number ${NUM_USERS}:"
> explainlimits
>
> echo -n "Academic VAX Username: "
> read -r USERNAME junk
>
> # No username? Just exit gracefully (in case they don't have one, etc).
> [ -z "${USERNAME}" ] && exit
> # VMS treats usernames insenstively, but filenames (which we user) are case
> # senstive. In order to prevent swatson from having 2^7=128 different logins,
> # we map things to lowercase only (this prevents us from having to rename
> # things in scripts/, etc.
> USERNAME=$(echo "${USERNAME}" | tr "A-Z" "a-z")
>
> stty -echo
> echo -n "Password: "
> read -r PASSWORD junk
> echo
> stty echo
>
> # No password? We don't need to log this as a failure, just exit.
> [ -z "${PASSWORD}" ] && exit
>
> # Unless otherwise specified, send all output to an errorlog
> exec 2>>${ERRLOG} >>${ERRLOG}
>
> if [ -x scripts/${USERNAME}.check ]
> then
> scripts/${USERNAME}.check "${USERNAME}" "${PASSWORD}"
> else
> # Check is improved. Check will now read its data from stdin (and avoid
> # a plaintext password on the command line). Also, you can
> # use -n -p -H -P to specify which of name, password, host or port
> # repsectively is given. Arguments without - are take to be the first
> # variable (in that order) that has not yet been specified. An argument
> # of - means read that (on a separate line) from stdin. Defaults for -n
> # and -p are read from stdin (ie "-"). The default value for -H is
> # academic.csubak.edu and for -P is pop3.
> # Return values have been extended:
> # 0 -- authentication worked
> # 1 -- couldn't connect
> # 2 -- couldn't send username
> # 3 -- bad password
> # Lastly, check has been extended to authenticate with either the POP3
> # or FTP protocol. This will work on either port and supports wuftpd
> # style extended responses.
> check <<END_OF_CHECK
> ${USERNAME}
> ${PASSWORD}
> END_OF_CHECK
> fi
> if [ $? != 0 ]; then
> ttyecho "Bad Username or Password."
> ppplog bad_password
> # no need to let this hang around core ....
> PASSWORD=
> # We don't want to password failures to lock the user out for a day....
> USERNAME=
> exit
> fi
>
> # if we want debugging, the next lines may be uncommented (if it is done
> # before, the user may get lots of garbage or the password will be stored)
> #set -x
> #set -v
>
> # no need to let this hang around core ....
> PASSWORD=
>
> if [ -f ${USERNAME}.lock ]; then
> # a little white lie.... They shouldn't be trying this anyway!
> ttyecho "Bad Username or Password."
> # log this little incident
> ppplog double_login
> # no need to clear any locks; we would let the user login again (execpt for
> # the time constraint)
> USERNAME=
> exit
> else
> # as soon as we know the lock dosn't exist, lock other logins by this user out
> # NOTE, this needs to be before any tty I/O since they could hang it there
> # indefinitely.
> touch ${USERNAME}.lock
> chmod 444 ${USERNAME}.lock
> fi
>
> # Now that we have all the info on the user, we give a script an oppourtunity
> # to change things. Note that we need to use . rather than run the script
> # directly (otherwise, it couldn't change variables in this context, use
> # functions defined here, cause exits, etc).
> [ -f scripts/${USERNAME}.reconf ] && . scripts/${USERNAME}.reconf
>
> # Let the user know any new or interesting information. cat is better than
> # more/less because it will never require user (ie script) input
> if [ -f Welcome.msg ]; then
> cat Welcome.msg >${TTY}
> fi
>
> if [ ${TIMEOFF} -le 0 ]
> then
> TIMEOFF=0
> TIMEON=0
> fi
> if [ ${TIMEOFF} -gt ${TIMEON} ]
> then
> TOWAIT=$(pppusertime "${USERNAME}" ${TIMEOFF} ${TIMEON} ${PPPLOG})
> else
> TOWAIT=-${TIMEON}
> fi
>
> if [ ${TOWAIT} -gt 0 ]; then
> explainlimits
> ttyecho "Access Denied. You have to wait $(timefmt ${TOWAIT})"
> ttyecho " until you can use the system again."
> ppplog user_impatient
> sleep 4
> exit
> fi
>
> TOWAIT=$((-${TOWAIT}))
>
> ttyecho "You may now stay connected for $(timefmt ${TOWAIT})."
>
> for name in $PPPDEVS .
> do
> if [ ${name} = . ]; then
> ttyecho "All available ports are in use. Try again later."
> exit
> fi
> if [ ! -e ${name}.lock ]; then
> # if the file dosn't exist, try to write our PID and username to it
> echo $$ ${USERNAME} >> ${name}.lock
> # now, check to see if our PID is the first on in the file.
> read TESTPID junk < ${name}.lock
> # if so, we have the lock
> if [ ${TESTPID} = $$ ]; then
> # for safety sake, make it unwritable.
> chmod 444 ${name}.lock
> # Give last few lines of nslookup on their address
> # in order to make dip (and other programs) happy.
> nslookup ${name}.lib.csubak.edu | tail -4 >${TTY}
> # enter the user in the log
> ppplog in
> # and remember that we have to catch a logout
> need_ppplog_out=YES
> # give the user a constant string so that a connect script will
> # know that everything is fine and that it should really get to
> # starting its PPP
> ttyecho "PPP starting. Start it on your end too."
> # This was happening: We'd get a HUP and exit (killing the pppd too) but
> # we wouldn't run the rest of our program. If we ignore HUP, then pppd
> # ignores it too. The way we solve this to run pppd with an & (and tell it
> # not to detach). This sets $! to pppd's pid so we can kill it when we get
> # our HUP/whatever.
> /usr/lib/ppp/pppd -detach remotename ${name} name linux1 ${PPPFLAGS} \
> proxyarp linux1:${name} ${TTY}&
> PPPD_PID=$!
> # We want to kill people who stay on forever, but we don't want
> # to throw library staff off who need the system or people who don't
> # have to wait to log back in (what would be the point?)
> if [ ${TIMEOFF} -ne 0 ]
> then
> # this subshell will handle things for us without us having to
> # bother with at(1) (no mail messages, more control, etc)
> # we could do things like wake up, see if all ports are in use
> # if not, sleep a while longer, otherwise kill PPPD and exit
> (sleep ${TOWAIT}; kill ${PPPD_PID} && ppplog forced_logout) &
> fi
> # just wait for pppd to exit (either because our subshell killed it or
> # because it exited on its own
> wait ${PPPD_PID}
> # no need for a HUP/TERM/etc to a process that exited on its own
> PPPD_PID=
> # Ok, we should take note that the user logged out
> ppplog out
> # and that we don't need to do it again.
> need_ppplog_out=NO
> exit
> fi
> fi
> done
> ------------public_ppp-end----------------------------
> ------------pppusertime-begin-------------------------
> #!/usr/bin/perl
>
> # This program was written to allow 2 hours in a 24 hour period, but the
> # only place there numbers are refered to are in coments. Any other
> # time limits would work as well.
> #
> # This program is to do accounting for PPP usage. If given just a
> # username and time to start the accounting, it will compute the number
> # of seconds that user has been logged in the time since the given time.
> # Of more use, if an maximum amount of time (in seconds) is given, it will
> # either return how much time that user must wait to reconnect or it will
> # return how long that user may be connected. (In order to tell the difference
> # a non-positve result means that the user may not connect and a
> # postive result means that the user may connect.)
> #
> # Determining how long the user has connected is accomplished by reading
> # through the log file and for each logout the user has after the
> # start of accounting time we add the number of seconds (durring the accounting
> # period) the user was connected to a total. We do this by keeping track
> # of the last login time the user logged in at and subtracting this from
> # the logout time.
> #
> # Finding out if the user is allowed to log in is easy then. We can just
> # compare the amount of seconds the user has with the number of
> # seconds the user is allowed. If the former is less, the user can log in
> # otherwise, the user must wait. What is tricky is determining how long
> # the user may stay in (or later, how long the user must wait).
> #
> # This is computed by finding out how much time they have been connected in the
> # previous 22 hours (24-2=22) and subtracting that from 2.
> #
> # Finding out how long a user must wait before they can reconnect is determined
> # by how when the first time in the past 24 hours the user connected. If
> # the user connected 24 hours or more ago, the user may re-connect
> # immedeately. If the user connected 23 hours ago the use may reconnect
> # in 1 hour, etc.
> #
> # This means that in our scan through the log, we must determine:
> # (a) how long the user was logged in durring the last 22 hours,
> # (b) how long the user was logged in durring the last 24 hours, and
> # (c) the earliest time in the last 24 hours when the user was logged in.
> #
>
> $now = time; # get the time ASAP
>
> # a usage message can really help
> $usage = "Usage:\n" .
> " $0 <username> <timesince> [<timealloted> [<logfile1> ...]]\n".
> " \n".
> " Where username is the name of the user in question,\n".
> " timesince is the first time we care about (if negative the\n".
> " number of seconds we care about),\n".
> " timealloted is the amount of time allowed for the user".
> " since timesince,\n".
> " and logfile(s) are (hopefully sequentially ordered) file(s)\n".
> " where public_ppp information is to be found.\n";
>
> # get info from command line:
> ($#ARGV >= 1) || die $usage;
> $user = shift(_at_ARGV);
> $period = shift(_at_ARGV);
> $maxtime = shift(_at_ARGV) if _at_ARGV;
>
> # this pretends the user put in ppp_log if we had no logfile arguments
> unshift(_at_ARGV, 'ppp_log') unless _at_ARGV;
>
> # as promised above, we need to compute since from the current time
> # if it was given to be a negative value
> if ($period > 0)
> {
> $start1 = $now - $period;
> $start2 = $start1;
> $start2 += $maxtime if (defined($maxtime));
> }
> else
> {
> $start1 = $period;
> $start2 = $period;
> }
>
> # initialize some variables
> $p1time = 0; # we know of no time used yet in period 1
> $p2time = 0; # we know of no time used yet in period 2
>
> while (<>) # get each line in the files left on the command line
> { # even if it was faked with a unshift.
> chop; # we don't care about the \n at the end
> ($date, $loguser, $device, $addr, $status) = split(/:/);
> # split each colon delimited field as a variable
> next unless ($user eq $loguser); # same if the user is not our current
> # concern
> next unless ($date > $start1); # if the date is before we care about, just
> # get the next line
> if ($status eq 'in')
> {
> push(_at_in1times, $date);
> $firstgap = $date - $start1 if (!defined($firstgap));
> $firstgap = $date - $start1 if ($firstgap > $date + $start1);
> }
> elsif ($status eq 'out')
> {
> if (_at_in1times)
> {
> $p1time += $date - pop(_at_in1times);
> }
> else
> {
> $firstgap = 0 if (!defined($firstgap));
> $p1time += $date - $start1;
> }
> }
> next unless ($date > $start2); # if the date is before we care about, just
> # get the next line
> if ($status eq 'in')
> {
> push(_at_in2times, $date);
> }
> elsif ($status eq 'out')
> {
> if (_at_in2times)
> {
> $p2time += $date - pop(_at_in2times);
> }
> else
> {
> $p2time += $date - $start2;
> }
> }
> }
>
> $firstgap = 0 if (!defined($firstgap));
>
> while(_at_in1times)
> {
> $p1time += pop(_at_in1times) - $now;
> }
>
> while(_at_in2times)
> {
> $p2time += pop(_at_in2times) - $now;
> }
>
> if (defined($maxtime))
> {
> if ($maxtime <= $p1time)
> {
> print $firstgap, "\n";
> exit(1);
> }
> print $p2time-$maxtime, "\n";
> exit(1);
> }
>
> print $p1time, "\n";
> exit(0);
> ------------pppusertime-end---------------------------
>
Received on Mon Oct 16 1995 - 11:36:14 NZDT

This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:46 NZDT