File Coverage

blib/lib/Apache/AuthenProgram.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             # Apache::AuthenProgram allows you to call an external program
2             # that performs username/password authentication in Apache.
3             #
4             # Copyright (c) October 7, 2002 Mark Leighton Fisher, Thomson Inc.
5             #
6             # This module is free software; you can redistribute it and/or
7             # modify it under the same terms as Perl itself.
8              
9              
10             package Apache::AuthenProgram;
11              
12 1     1   7523 use strict;
  1         2  
  1         38  
13 1     1   1758 use Apache::Constants ':common';
  0            
  0            
14             use File::Temp q(tempfile);
15              
16             $Apache::AuthenProgram::VERSION = '0.90';
17              
18              
19             sub handler {
20             my $request = shift; # Apache request object
21             my @args = (); # authentication program arguments
22             my $cmd = ""; # program command string
23             my $i = 0; # counter for @args
24             my $ofh = ""; # output file handle for password temp file
25             my $password = ""; # password from Basic Authentication
26             my $passfile = ""; # temporary file containing password
27             my $passtype = ""; # "File" if communicating password by temp file
28             my $program = ""; # authentication program filename
29             my $response = ""; # Apache response object
30             my $success = ""; # success string from authentication program
31             my $username = ""; # username from Basic Authentication
32              
33             # get password, decline if not Basic Authentication
34             ($response, $password) = $request->get_basic_auth_pw;
35             return $response if $response;
36              
37             # get username
38             $username = $request->connection->user;
39             if ($username eq "") {
40             $request->note_basic_auth_failure;
41             $request->log_reason("Apache::AuthenProgram - No Username Given", $request->uri);
42             return AUTH_REQUIRED;
43             }
44              
45             # get authentication program, args, and success string
46             $program = $request->dir_config("AuthenProgram");
47             for ($i = 1; $i < 10; $i++) {
48             $args[$i] = $request->dir_config("AuthenProgramArg$i");
49             }
50             $success = $request->dir_config("AuthenProgramSuccess");
51              
52             # write temp. password file on request
53             $passtype = $request->dir_config("AuthenProgramPassword");
54             if ($passtype eq "File") {
55             ($ofh, $passfile) = tempfile();
56             if (!defined($ofh) || $ofh eq "") {
57             $request->log_reason("Apache::AuthenProgram can't create password file",
58             $request->uri);
59             return SERVER_ERROR;
60             }
61             chmod(0600, $passfile)
62             || $request->log_reason(
63             "Apache::AuthenProgram can't chmod 0600 password file '$passfile' because: $!",
64             $request->uri);
65             if (!print $ofh $password,"\n") {
66             $request->log_reason("Apache::AuthenProgram can't write password file '$ofh'",
67             $request->uri);
68             return SERVER_ERROR;
69             }
70             if (!close($ofh)) {
71             $request->log_reason("Apache::AuthenProgram can't close password file '$ofh'",
72             $request->uri);
73             return SERVER_ERROR;
74             }
75             $password = $passfile;
76             }
77              
78             # execute command, then examine output for success or failure
79             $cmd = "$program '$username' '$password' ";
80             $cmd .= join(' ', @args);
81             my @output = `$cmd`;
82             if ($passtype eq "File") {
83             if (!unlink($passfile)) {
84             $request->log_reason("Apache::AuthenProgram can't delete password file '$ofh'",
85             $request->uri);
86             }
87             }
88             if (!grep(/$success/, @output)) {
89             $request->note_basic_auth_failure;
90             $request->log_reason("login failure: " . join(' ', @output), $request->uri);
91             return AUTH_REQUIRED;
92             }
93              
94             unless (@{ $request->get_handlers("PerlAuthzHandler") || []}) {
95             $request->push_handlers(PerlAuthzHandler => \&authz);
96             }
97              
98             return OK;
99             }
100              
101             sub authz {
102             my $request = shift; # Apache request
103             my $requires = $request->requires; # Apache Requires arrayref
104             my $username # username
105             = $request->connection->user;
106             my $require = ""; # one Requires statement
107             my $type = ""; # type of Requires
108             my @users = (); # list of valid users
109              
110             # decline unless we have a requires
111             return OK unless $requires;
112              
113             # process each Requires statement
114             for my $require (@$requires) {
115             my($type, @users) = split /\s+/, $require->{requirement};
116              
117             # user is one of these users
118             if ($type eq "user") {
119             return OK if grep($username eq $_, @users);
120              
121             # user is simply authenticated
122             } elsif ($type eq "valid-user") {
123             return OK;
124             }
125             }
126            
127             $request->note_basic_auth_failure;
128             $request->log_reason("user $username: not authorized", $request->uri);
129             return AUTH_REQUIRED;
130              
131             }
132              
133             1;
134              
135             __END__