File Coverage

blib/lib/POE/Component/SASLAuthd.pm
Criterion Covered Total %
statement 18 38 47.3
branch 0 2 0.0
condition 0 3 0.0
subroutine 6 11 54.5
pod 1 1 100.0
total 25 55 45.4


line stmt bran cond sub pod time code
1             package POE::Component::SASLAuthd;
2              
3 1     1   20948 use warnings;
  1         2  
  1         30  
4 1     1   5 use strict;
  1         2  
  1         25  
5              
6 1     1   4 use Carp qw(carp croak);
  1         6  
  1         61  
7              
8 1     1   977 use POE::Session;
  1         6408  
  1         6  
9 1     1   1037 use POE::Wheel::ReadWrite;
  1         144563  
  1         31  
10 1     1   8 use POE::Filter::Line;
  1         2  
  1         372  
11              
12             =head1 NAME
13              
14             POE::Component::SASLAuthd - Implement the Cyrus SASL authdaemond daemon.
15              
16             =head1 VERSION
17              
18             Version 0.04
19              
20             =cut
21              
22             our $VERSION = '0.04';
23              
24              
25             =head1 SYNOPSIS
26              
27             The authdaemond provides authenticaiton services for various network services.
28             Cyrus IMAP server, Exim, Postfix and probably several other products support
29             authentication via the authdaemon interface.
30              
31             A simple authentication daemon is provided below as an example:
32              
33             use strict;
34              
35             use POE::Session;
36             use POE::Wheel::SocketFactory;
37             use Socket;
38              
39             use POE::Component::SASLAuthd;
40              
41             POE::Session->create(
42             inline_states => {
43             _start => sub {
44             my ($kernel, $heap) = @_[KERNEL, HEAP];
45              
46             my $sock = '/var/state/saslauthd/mux';
47              
48             unlink $sock if -e $sock;
49             $heap->{'server'} = POE::Wheel::SocketFactory->new(
50             BindAddress => $sock,
51             SocketDomain => AF_UNIX,
52             SocketType => SOCK_STREAM,
53             SuccessEvent => 'handle_accept',
54             FailureEvent => 'handle_error',
55             );
56             chmod 0777, $sock;
57             },
58             _stop => sub { my ($kernel, $heap) = @_[KERNEL, HEAP];
59             warn "stop! ($heap->{'server'})\n" },
60             handle_accept => sub {
61             my ($kernel, $heap, $handle) = @_[KERNEL, HEAP, ARG0];
62              
63             POE::Component::SASLAuthd->spawn($handle, sub {
64             my $username = shift;
65             my $password = shift;
66             my $service = shift;
67             my $realm = shift;
68              
69             return 0 if $password eq 'snakk';
70             return 1 if $username eq 'snik';
71             return 0;
72             });
73             },
74             handle_error => sub {
75             ### do something
76             }
77             }
78             );
79              
80             POE::Kernel->run();
81              
82             =head1 METHODS
83              
84             =head2 spawn($socket, sub { ... })
85              
86             This is a class method, invoked as
87              
88             POE::Component::SASLAuthd->spawn($handle, $code)
89              
90             This method accepts two arguments - the first one is the socket handle that
91             cares the connection to the client, the second one is a code reference that
92             performs the authentication itself. The code is called with following arguments
93              
94             $username, $password, $service, $realm
95              
96             The authentication will be allowed if the code returns true and denied
97             otherwise.
98              
99             =cut
100              
101             sub spawn {
102 0     0 1   my $proto = shift;
103 0   0       my $class = ref($proto) || $proto;
104              
105 0           POE::Session->create(package_states => [$class, ['_start']], args => [@_]);
106             }
107              
108              
109             =head1 AUTHOR
110              
111             Kirill Miazine, C<< >>
112              
113              
114             =head1 SUPPORT
115              
116             You can find documentation for this module with the perldoc command.
117              
118             perldoc POE::Component::SASLAuthd
119              
120              
121             You can also look for information at:
122              
123              
124             =head1 COPYRIGHT & LICENSE
125              
126             Copyright 2008 Kirill Miazine, all rights reserved.
127              
128             This program is free software; you can redistribute it and/or modify it
129             under the same terms as Perl itself.
130              
131              
132             =cut
133              
134             sub _start {
135 0     0     my ($kernel, $heap) = @_[KERNEL, HEAP];
136 0           my ($handle, $auth_hook) = @_[ARG0, ARG1];
137              
138 0           $handle->blocking(1); # XXX Shall be made non-blocking at a later stage
139 0           my $username = _sasl_string($handle);
140 0           my $password = _sasl_string($handle);
141 0           my $service = _sasl_string($handle);
142 0           my $realm = _sasl_string($handle);
143              
144 0 0         return $auth_hook->($username, $password, $service, $realm) ?
145             _sasl_allow($handle) :
146             _sasl_deny($handle);
147             }
148              
149             sub _sasl_string {
150 0     0     my $buf;
151 0           $_[0]->read($buf, 2);
152 0           my $size = unpack('n', $buf);
153 0           $_[0]->read($buf, $size);
154 0           return unpack("A$size", $buf);
155             }
156              
157             sub _sasl_allow {
158 0     0     $_[0]->print(pack('nA3', 2, "OK\0"));
159 0           $_[0]->close();
160             }
161              
162             sub _sasl_deny {
163 0     0     $_[0]->print(pack('nA3', 2, "NO\0"));
164 0           $_[0]->close();
165             }
166              
167             1; # End of POE::Component::SASLAuthd