File Coverage

blib/lib/Apache2/AuthPAM.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Apache2::AuthPAM;
2              
3             =head1 NAME
4              
5             Apache2::AuthPAM - Authenticate apache request using PAM services
6              
7             =cut
8              
9 1     1   372561 use 5.006;
  1         3  
  1         32  
10 1     1   5 use strict;
  1         1  
  1         27  
11 1     1   5 use warnings;
  1         4  
  1         45  
12              
13 1     1   1342 use Apache2::Const qw/:common/;
  0            
  0            
14             use Apache2::Log;
15              
16             use Authen::PAM qw/pam_start pam_end pam_authenticate pam_acct_mgmt PAM_SUCCESS/;
17              
18             our $VERSION = '0.01';
19              
20             our $MODNAME = __PACKAGE__;
21              
22              
23             sub handler {
24             # get object request
25             my $r = shift;
26              
27             # check first request
28             return OK unless $r->is_initial_req;
29              
30             # get user password
31             my ($rc, $pw) = $r->get_basic_auth_pw;
32              
33             # decline if not basic
34             return $rc if $rc;
35              
36             # get log object
37             my $log = $r->log;
38              
39             # get user name
40             my $username = $r->user;
41              
42             # avoid blank username
43             unless($username) {
44             $r->note_basic_auth_failure;
45             $log->info("$MODNAME: no user name supplied", $r->uri);
46             return AUTH_REQUIRED;
47             }
48              
49             # load apache config vars
50             my $service = $r->dir_config('PAMservice');
51             unless($service) {
52             $log->alert("$MODNAME: no PAM service name supplied", $r->uri);
53             return SERVER_ERROR;
54             }
55              
56             my $pam_conversation = sub { # closure with access to $pw
57             my @res;
58             while (@_) {
59             my $msg_type = shift;
60             my $msg = shift;
61             push @res, (0, $pw);
62             }
63             push @res, 0;
64             return @res;
65             };
66              
67             # start PAM dialog
68             my $pamh;
69             my $result = pam_start($service, $username, $pam_conversation, $pamh);
70              
71             unless ($result == PAM_SUCCESS) {
72             $r->note_basic_auth_failure;
73             $log->crit("$MODNAME: <$service> not started ($result) ", $r->uri);
74             pam_end($pamh, 0);
75             return SERVER_ERROR;
76             }
77              
78             $result = pam_authenticate($pamh, 0);
79             unless ($result == PAM_SUCCESS) {
80             $r->note_basic_auth_failure;
81             $log->info("$MODNAME: <$username> not authenticated by $service ($result) ", $r->uri);
82             pam_end($pamh, 0);
83             return AUTH_REQUIRED;
84             }
85              
86             $result = pam_acct_mgmt($pamh, 0);
87             unless ($result == PAM_SUCCESS) {
88             $r->note_basic_auth_failure;
89             $log->info("$MODNAME: <$username> no acct mgmt by $service ($result) ", $r->uri);
90             pam_end($pamh, 0);
91             return AUTH_REQUIRED;
92             }
93              
94             # Authenticated
95             pam_end($pamh, 0);
96             $log->info("$MODNAME: <$username> authenticated by $service ", $r->uri);
97              
98             return OK;
99             }
100              
101              
102             1;
103             __END__