Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Apache Timeout module

by jjhorner (Hermit)
on Jun 09, 2000 at 06:00 UTC ( [id://17253]=sourcecode: print w/replies, xml ) Need Help??
Category: Web stuff/Apache
Author/Contact Info J. J. Horner jjhorner@bellsouth.net
Description:

I wrote this mod_perl handler to give easy timeouts to restricted web pages. It is very elementary, but useful. Please give me some comments at my email address above if you wish.

It requires a directory "times" under your /usr/local/apache/conf/ directory, owned by the user:group running the Apache child processes, for your timestamp files.

Usage: See in-code docs.

Update v0.21

  • I added better docs and fixed a bug or two.
  • I also moved most of the config info into the httpd.conf file and only moved configurable stuff to .htaccess.
  • Added concept of Minimum Time Out and Mode.

Update v0.20

  • I sped up the routine that checks time since last visit. It now stats a file, grabs the number of seconds since last modification, and uses that for $last_time. Then opens the time file rw to update the modification time.
  • I added option to put the DEBUG mode into the .htaccess file.

TO DO:

  • Write documentation
  • Make into format usable on CPAN
package Apache::TimeOut;
#file Apache/TimeOut.pm
#
#    Author: J. J. Horner
#    Version: 0.21 (06/14/2000)
#    Usage:  see documentation
#    Description:
#        Small mod_perl handler to provide Athentication phase time ou
+ts for 
#        sensitive areas, per realm.  Still has a few issues, but noth
+ing too 
#        serious.

use strict;
use warnings;
use Carp;
use Apache::Constants qw(:common);

our $VERSION = '0.01';

sub handler {

        my $current_time = time();

        my $r = shift;
        my $DEBUG = $r->dir_config('TIMEOUT_DEBUG') || carp "DEBUG val
+ue not set: $!"; # pulls debug flag from config file 
           carp "current time = $current_time" if $DEBUG;
        my ($res, $sent_pw) = $r->get_basic_auth_pw;
        carp "Response set - $res: $!" if $DEBUG;
        return $res if $res != OK;  # return not OK status if not OK

    my $time_to_die;
    if ($r->dir_config('TimeLimit') && ($r->dir_config('TimeLimit') < 
+$r->dir_config('DefaultLimit'))) {
            $time_to_die = $r->dir_config('TimeLimit');
    } else {
        $time_to_die = $r->dir_config('DefaultLimit');
    }
        carp "time limit set to $time_to_die" if $DEBUG;
        return DECLINED if ($r->dir_config('MODE'));  #do nothing if P
+erlSetVar TimeLimit not set.

        my $user = $r->connection->user;
        my $realm = $r->auth_name();
        $realm =~ s/\s+/_/g;
        my $host = $r->get_remote_host();
        my $time_file = "/usr/local/apache/conf/times/$realm-$host.$us
+er";
        carp "Time file set to $time_file" if $DEBUG;

        if (-e $time_file) {   # if timestamp file exists, check time 
+difference
                my $last_time = (stat($time_file))[9] || carp "Unable 
+to get last modtime from file: $!";
                carp "Last time = $last_time" if $DEBUG;

                if ($time_to_die >=  ($current_time - $last_time)) {
                        open (TIME, ">$time_file");
                        close TIME;
                        return OK;

                } else {  # if time delta greater than TimeLimit
                        $r->note_basic_auth_failure;
                        unlink($time_file) or carp "Can't unlink file:
+ $!";
                        return AUTH_REQUIRED;
                }

        } else {  # previous time delta greater than TimeLimit so file
+ was unlinked
                open (TIME, ">$time_file");
                close TIME;
                return OK;
        }
}

1;
__END__

=head1 NAME

Apache::TimeOut - mod_perl handler to provide time outs on .htaccess p
+rotected pages.

=head1 SYNOPSIS

  In httpd.conf file:
    PerlAuthenHandler Apache::TimeOut
    PerlSetVar DefaultLimit \<timeout in seconds\>

  Optional httpd.conf file entry:
    PerlSetVar TIMEOUT_DEBUG 1
       Turns debugging on to print messages to server error_log

  Optional .htaccess entries: 
    PerlSetVar TimeLimit \<timeout\>
        or
    PerlSetVar MODE off      #to turn off timeouts

=head1 DESCRIPTION

  Simple mod_perl handler for the AUTHENTICATION phase to set a limit 
+on user inactivity.
  Will provide timeouts to any file under the protection of an .htacce
+ss file, unless the 
  'MODE' option set to anything other than 0 in the .htaccess file.  T
+he 'DefaultLimit' is
  set via the httpd.conf file, and unless the user specified 'TimeLimi
+t' is set and less 
  than the 'DefaultLimit', determines the length of time a user can be
+ inactive.  This 
  handler can be set anywhere an AUTHENTICATION handler can be specifi
+ed.

=head2 EXPORT

None by default.


=head1 AUTHOR

J. J. Horner jjhorner@bellsouth.net

=head1 SEE ALSO

perl(1).

=cut
Replies are listed 'Best First'.
RE: Apache Timeout module
by plaid (Chaplain) on Jun 09, 2000 at 23:49 UTC
    First thing, the way you have it set up to check timestamps, the line if ($time_to_die >= ($current_time - $last_time)) { seems to suggest that $time_to_die is in seconds, as both $current_time and $last_time are in seconds, but I believe you were expecting $time_to_die in minutes, so you may want to throw a *= 60 in there or something.

    One thing I was considering about this is that there isn't really a need to throw the timestamp into a file, since basically you're just storing the exact same number as is already contained in the file's modification time. Since you're already effectively performing a stat via the -e test, you can then just use the cached filehandle _ to obtain the modification time and cut out an additional file opening/reading/writing.

    use Benchmark; use strict; my $time_to_die = 15; my $time_file_1 = "time1.txt"; my $time_file_2 = "time2.txt"; my $current_time = time(); # kept this outside the benchmark timethese(100000, { 'Time In File' => \&timeinfile, 'File Mod Time' => \&filemodtime }); sub timeinfile { if (-e $time_file_1) { open (TIME, "$time_file_1") || warn "Can't open Time file: $!"; my $last_time = <TIME> || warn "Unable to get timestamp from fil +e: $!"; close TIME; if ($time_to_die >= ($current_time - $last_time)) { open (TIME, ">$time_file_1"); print TIME $current_time || warn "Unable to write timestamp t +o file: $!"; close TIME; } else { unlink($time_file_1) or warn "Can't unlink file: $!"; } } else { open (TIME, ">$time_file_1"); print TIME $current_time; close TIME; } } sub filemodtime { if(-e $time_file_2) { my $last_time = (stat(_))[9]; if($time_to_die >= ($current_time - $last_time)) { open (TIME, ">$time_file_2"); close TIME; } else { unlink($time_file_2) or warn "Can't unlink file: $!"; } } else { open (TIME, ">$time_file_2"); close TIME; } } Benchmark: timing 100000 iterations of File Mod Time, Time In File... File Mod Time: 11 wallclock secs ( 6.97 usr + 3.21 sys = 10.18 CPU) Time In File: 48 wallclock secs (21.26 usr + 25.77 sys = 47.03 CPU)

      I'm glad someone is checking my code! I like your mod time idea, and it seems to work.

      As for the TimeLimit, it will be in seconds, and I was using 15 just so debugging would go faster. Normally, it would be something like 900.

      Again, thanks for checking on my work. I really appreciate the feedback. If it is ever released to CPAN, look for your name in the README.

      J. J. Horner
      Linux, Perl, Apache, Stronghold, Unix
      jhorner@knoxlug.org http://www.knoxlug.org/
      

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://17253]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (4)
As of 2024-04-16 18:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found