File Coverage

blib/lib/Catalyst/Plugin/Authentication/Credential/PAM.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::Authentication::Credential::PAM;
2              
3 1     1   21619 use strict;
  1         2  
  1         57  
4 1     1   5 use warnings;
  1         1  
  1         32  
5 1     1   506 use Authen::PAM qw/:constants/;
  0            
  0            
6             use Scalar::Util qw/blessed/;
7              
8             our $VERSION = '0.01';
9              
10             sub login {
11             my ($c, $user, $password) = @_;
12             unless ($user && defined $password) {
13             $c->log->debug("Can't login a user without a username and a password") if $c->debug;
14             return 0;
15             }
16             unless (blessed($user) && $user->isa("Catalyst::Plugin::Authentication::User")) {
17             if (my $user_obj = $c->get_user($user, $password)) {
18             $user = $user_obj;
19             }
20             else {
21             $c->log->debug("User '$user' doesn't exist in the default store") if $c->debug;
22             return 0;
23             }
24             }
25             if ($c->_check_password($user->id, $password)) {
26             $c->set_authenticated($user);
27             return 1;
28             }
29             else {
30             return 0;
31             }
32             }
33              
34             sub _check_password {
35             my ($c, $username, $password) = @_;
36             my $service = $c->config->{authentication}{pam}{service} || 'login';
37             my $handler = sub {
38             my @response = ();
39             while (@_) {
40             my $code = shift;
41             my $message = shift;
42             my $answer;
43             if ($code == PAM_PROMPT_ECHO_ON) {
44             $answer = $username;
45             }
46             elsif ($code == PAM_PROMPT_ECHO_OFF) {
47             $answer = $password;
48             }
49             push(@response, PAM_SUCCESS, $answer);
50             }
51             return (@response, PAM_SUCCESS);
52             };
53             my $pam = Authen::PAM->new($service, $username, $handler);
54             $pam or do {
55             $c->_log_debug($username, $service, Authen::PAM->pam_strerror($pam));
56             return 0;
57             };
58             my $result = $pam->pam_authenticate;
59             unless ($result == PAM_SUCCESS) {
60             $c->_log_debug($username, $service, $pam->pam_strerror($result));
61             return 0;
62             }
63             $result = $pam->pam_acct_mgmt;
64             unless ($result == PAM_SUCCESS) {
65             $c->_log_debug($username, $service, $pam->pam_strerror($result));
66             return 0;
67             }
68             $c->log->debug(qq/Successfully authenticated user '$username' using service '$service'./) if $c->debug;
69             return 1;
70             }
71              
72             sub _log_debug {
73             my ($c, $username, $service, $error) = @_;
74             $c->log->debug(qq/Failed to authenticate user '$username' using service '$service'. Reason: '$error'/) if $c->debug;
75             }
76              
77             1;
78              
79             __END__
80              
81             =head1 NAME
82              
83             Catalyst::Plugin::Authentication::Credential::PAM - Authenticate a user against PAM
84              
85             =head1 SYNOPSIS
86              
87             use Catalyst qw(
88             Authentication
89             Authentication::Store::Foo
90             Authentication::Credential::PAM
91             );
92            
93             package MyApp::Controller::Auth;
94            
95             # default is 'login'
96             __PACKAGE__->config->{authentication}{pam}{service} = 'su';
97            
98             sub login : Local {
99             my ( $self, $c ) = @_;
100             $c->login( $c->req->param('username'), $c->req->param('password') );
101             }
102              
103             =head1 DESCRIPTION
104              
105             This is an authentication credential checker that verifies passwords using a
106             specified PAM service.
107              
108             =head1 METHODS
109              
110             =over 4
111              
112             =item login($username, $password)
113              
114             Try to log a user in.
115              
116             =back
117              
118             =head1 AUTHOR
119              
120             Rafael Garcia-Suarez C<< <rgarciasuarez@mandriva.com> >>
121              
122             =head1 LICENSE
123              
124             Copyright (c) 2006 Mandriva SA.
125              
126             This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.
127              
128             =cut