File Coverage

blib/lib/Net/Server/Mail/ESMTP/AUTH.pm
Criterion Covered Total %
statement 14 62 22.5
branch 0 14 0.0
condition 0 3 0.0
subroutine 5 13 38.4
pod 0 8 0.0
total 19 100 19.0


line stmt bran cond sub pod time code
1             package Net::Server::Mail::ESMTP::AUTH;
2              
3 1     1   3811 use 5.006;
  1         2  
4 1     1   3 use strict;
  1         1  
  1         21  
5 1     1   3 use base qw(Net::Server::Mail::ESMTP::Extension);
  1         5  
  1         503  
6 1     1   689 use MIME::Base64;
  1         514  
  1         48  
7              
8 1     1   5 use vars qw( $VERSION );
  1         1  
  1         452  
9             $VERSION = '0.2';
10              
11             =head1 NAME
12              
13             Net::Server::Mail::ESMTP::AUTH - SMTP Authentification extensions for Net::Server::Mail::ESMTP
14              
15             =head1 SYNOPSIS
16              
17             use Net::Server::Mail::ESMTP;
18             my @local_domains = qw(example.com example.org);
19             my $server = new IO::Socket::INET Listen => 1, LocalPort => 25;
20              
21             my $conn;
22             while($conn = $server->accept)
23             {
24             my $esmtp = new Net::Server::Mail::ESMTP socket => $conn;
25            
26             # activate AUTH extension
27             $esmtp->register('Net::Server::Mail::ESMTP::AUTH');
28              
29             # adding AUTH handler
30             $esmtp->set_callback(AUTH => \&validate_auth);
31             $esmtp->set_callback(DATA => \&queue_message);
32             $esmtp->process;
33             }
34              
35             sub validate_auth
36             {
37             my ($session, $username, $password) = @_;
38              
39             if ($username eq 'ROBERT' and $password eq 'TOTO04') {
40             # AUTH SUCCESFULL
41             $session->{AUTH}->{ok} = 1;
42             return 1;
43             } else {
44             # AUTH FAILED
45             return 0;
46             }
47             }
48              
49             sub queue_message {
50             my($session, $data) = @_;
51              
52             # providing AUTH doesn't make it mandatory.
53             # A client might not use AUTH at all!
54             # You must deal now with permissions:
55              
56             unless ($session->{AUTH}->{ok}) {
57             # warn "no AUTH supplied!";
58             return(0, 530, 'Error: Authentication required');
59             }
60             ... do stuff
61             }
62              
63             =head1 FEATURES
64              
65             * AUTH LOGIN method support
66             * AUTH PLAIN method support
67              
68             =head1 DESCRIPTION
69              
70             "Net::Server::Mail::ESMTP::AUTH" is an extension to provide
71             ESMTP Authentification support to Net::Server::Mail::ESMTP module.
72             Actually only AUTH LOGIN and AUTH PLAIN methods are supported.
73              
74             AUTH callback is called with login and password who was given
75             by user's mail client, AUTH callback should return 1 when authentification
76             mechanism was succesfull otherwise 0.
77              
78             =cut
79              
80             our $verb = 'AUTH';
81              
82             sub init
83             {
84 0     0 0   my ($self, $parent) = @_;
85 0           $self->{AUTH} = ();
86              
87 0           return $self;
88             }
89              
90             sub verb
91             {
92 0     0 0   return ( [ 'AUTH' => \&process, ],);
93             }
94              
95             sub keyword
96             {
97 0     0 0   return 'AUTH LOGIN PLAIN';
98             }
99              
100             sub reply
101             {
102 0     0 0   return ( [ 'AUTH', ]);
103             }
104              
105             sub process_authlogin_username
106             {
107 0     0 0   my ($self, $operation) = @_;
108 0           $self->{AUTH}->{username} = decode_base64($operation);
109 0           $self->{AUTH}->{password} = '';
110 0           $self->reply(334, "UGFzc3dvcmQ6");
111 0           $self->next_input_to(\&process_authlogin_password);
112 0           return ();
113             }
114              
115             sub process_authlogin_password
116             {
117 0     0 0   my ($self, $operation) = @_;
118 0           $self->{AUTH}->{password} = decode_base64($operation);
119              
120 0           return exec_auth_callback($self);
121             }
122              
123             sub exec_auth_callback
124             {
125 0     0 0   my ($self) = @_;
126              
127 0           my $authok=0;
128              
129 0           my $ref = $self->{callback}->{AUTH};
130 0 0 0       if (ref $ref eq 'ARRAY' && ref $ref->[0] eq 'CODE') {
131 0           my $code = $ref->[0];
132              
133 0           $authok = &$code($self, $self->{AUTH}->{username}, $self->{AUTH}->{password});
134             }
135              
136 0 0         if ($authok) {
137 0           $self->reply(235, "Authentification successful.");
138 0           return ();
139             } else {
140 0           $self->reply(535, "Authentification failed.");
141 0           return 1;
142             }
143             }
144              
145             sub process
146             {
147 0     0 0   my ($self, $data) = @_;
148 0 0         my ($operation, $param) = $data=~/^(.+?)\s(.*)$/ ? ($1, $2) : ($data, '');
149              
150 0           $self->{AUTH}->{type} = $operation;
151 0           map { $self->{AUTH}->{$_} = '' } ('username', 'password', 'challenge', 'ticket', );
  0            
152              
153 0 0         if ($operation eq '*') {
    0          
    0          
154 0           $self->reply(501, "Authentification aborted.");
155 0           return ();
156             } elsif ($operation eq 'PLAIN') {
157 0           $param=decode_base64($param);
158 0           my @plaindata = split /\0/, $param;
159 0 0         unless (@plaindata > 2) {
160 0           $self->reply(535, "Authentification failed.");
161 0           return ();
162             } else {
163 0           $self->{AUTH}->{username} = $plaindata[@plaindata-2];
164 0           $self->{AUTH}->{password} = $plaindata[@plaindata-1];
165 0           return exec_auth_callback($self);
166             }
167             } elsif ($operation eq 'LOGIN') {
168 0           $param=decode_base64($param);
169             # warn " ==> LOGIN ==> $param\n";
170 0           $self->reply(334, "VXNlcm5hbWU6");
171 0           $self->next_input_to(\&process_authlogin_username);
172 0           return ();
173             } else {
174 0           $self->reply(504, "Unrecognized authentification type.");
175             }
176              
177 0           return ();
178             }
179              
180             =pod
181              
182             =head1 SEE ALSO
183              
184             Please, see L and L for
185             more documentations.
186              
187             =head1 AUTHOR
188              
189             Sylvain Cresto Escresto@gmail.comE
190              
191             Thanks to Chris Echris at u- club.deE
192              
193             =head1 BUGS
194              
195             Please send bug-reports to scresto@gmail.com.
196              
197             =head1 LICENCE
198              
199             This library is free software; you can redistribute it and/or modify
200             it under the same terms as Perl itself.
201              
202             =head1 COPYRIGHT
203              
204             Copyright (C) 2004, 2016 - Sylvain Cresto
205              
206             =cut
207              
208             1;