AuthorizeRequest.pm 7.28 KB
Newer Older
1
2
3
4
5
6
7
8
9
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
# $Id$

# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
10
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
11
12
13
# Copyright 2017 The Sympa Community. See the AUTHORS.md file at the top-level
# directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

package Sympa::Spindle::AuthorizeRequest;

use strict;
use warnings;
use Time::HiRes qw();

use Sympa;
use Sympa::Log;
use Sympa::Request;
use Sympa::Scenario;

use base qw(Sympa::Spindle);

sikeda's avatar
sikeda committed
41
my $log = Sympa::Log->instance;
42
43
44
45
46
47

sub _twist {
    my $self    = shift;
    my $request = shift;

    # Skip authorization unless specific scenario is defined.
48
49
    if ($request->{error} or not $request->handler->action_scenario
        or ($self->{scenario_context} and $self->{scenario_context}{skip})) {
50
51
52
        return ['Sympa::Spindle::DispatchRequest'];
    }

53
54
    my $scenario      = $request->handler->action_scenario;
    my $action_regexp = $request->handler->action_regexp;
55

56
    my $sender = $request->{sender};
57

58
    # Check if required context (known list or robot) is given.
59
60
    if (defined $request->handler->context_class
        and $request->handler->context_class ne ref $request->{context}) {
61
62
63
64
65
        $request->{error} = 'unknown_list';
        return ['Sympa::Spindle::DispatchRequest'];
    }
    my $that = $request->{context};

66
67
    my $context = $self->{scenario_context}
        or die 'bug in logic. Ask developer';
IKEDA Soji's avatar
IKEDA Soji committed
68
    # Add target email kept only in request to context.
69
70
71
    # FIXME: $request and $context would be merged in some future
    $context = {email => $request->{email}, %$context}
        if exists $request->{email};
72

73
74
    # Call scenario: auth_method MD5 do not have any sense in
    # scenario because auth is performed by AUTH command.
sikeda's avatar
sikeda committed
75

76
77
78
    my $action;
    my $result;

79
    # The order of the following 3 lines is important! SMIME > DKIM > SMTP.
sikeda's avatar
sikeda committed
80
81
82
83
84
    my $auth_method =
          $request->{smime_signed} ? 'smime'
        : $request->{md5_check}    ? 'md5'
        : $request->{dkim_pass}    ? 'dkim'
        :                            'smtp';
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

    $result = Sympa::Scenario::request_action($that, $scenario, $auth_method,
        $context);
    $action = $result->{'action'} if ref $result eq 'HASH';

    unless (defined $action and $action =~ /\A(?:$action_regexp)\b/) {
        $log->syslog(
            'info',
            '%s for %s from %s aborted, unknown requested action "%s" in scenario "%s"',
            uc $request->{action},
            $that,
            $sender,
            $action,
            $scenario
        );
        my $error = sprintf 'Unknown requested action in scenario: %s',
            ($action || '');
102
103
104
105
106
107
108
109
110
        Sympa::send_notify_to_listmaster(
            $request->{context},
            'mail_intern_error',
            {   error  => $error,
                who    => $sender,
                action => 'Command process',
            }
        );
        $self->add_stash($request, 'intern');
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
        return undef;
    }

    # Special cases for subscribe & signoff: If membership is unsatisfactory,
    # force execute request and let it be rejected.
    unless ($action =~ /\Areject\b/i) {
        if ($request->{action} eq 'subscribe'
            and defined $that->get_list_member($request->{email})) {
            $action =~ s/\A\w+/do_it/;
        } elsif ($request->{action} eq 'signoff'
            and not defined $that->get_list_member($request->{email})) {
            $action =~ s/\A\w+/do_it/;
        }
    }

    if ($action =~ /\Ado_it\b/i) {
        $request->{quiet} ||= ($action =~ /,\s*quiet\b/i);    # Overwrite.
        $request->{notify} = ($action =~ /,\s*notify\b/i);
        return ['Sympa::Spindle::DispatchRequest'];
130
131
132
133
134
    } elsif ($action =~ /\Alistmaster\b/i) {
        # Special case for move_list and create_list.
        $request->{pending} = 'pending';
        $request->{notify} = ($action =~ /,\s*notify\b/i);
        return ['Sympa::Spindle::DispatchRequest'];
135
136
    } elsif (
        $action =~ /\Arequest_auth\b(?:\s*[(]\s*[[]\s*(\S+)\s*[]]\s*[)])?/i) {
137
138
        my $to = $1;
        if ($to and $to eq 'email') {
139
            $request->{sender_to_confirm} = $request->{email};
140
        }
141
        return ['Sympa::Spindle::ToAuth'];
142
    } elsif ($action =~ /\Aowner\b/i and ref $that eq 'Sympa::List') {
143
        # Special case for subscribe and signoff.
144
        $request->{quiet} ||= ($action =~ /,\s*quiet\b/i);
145
        return ['Sympa::Spindle::ToAuthOwner'];
146
    } elsif ($action =~ /\Areject\b/i) {
sikeda's avatar
sikeda committed
147
148
        $self->add_stash($request, 'auth', $result->{'reason'},
            {template => $result->{'tt2'}});
149
150
151
152
153
154
        $log->syslog(
            'info',
            '%s for %s from %s refused (not allowed)',
            uc $request->{action},
            $that, $sender
        );
155
        return undef;
156
    }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

    $log->syslog(
        'info',
        '%s for %s from %s aborted, unknown requested action "%s" in scenario "%s"',
        uc $request->{action},
        $that,
        $sender,
        $action,
        $scenario
    );
    my $error = sprintf 'Unknown requested action in scenario: %s',
        $request->{action};
    Sympa::send_notify_to_listmaster(
        $request->{context},
        'mail_intern_error',
        {   error  => $error,
            who    => $sender,
            action => 'Command process',
        }
    );
    $self->add_stash($request, 'intern');
    return undef;
179
180
181
182
183
184
}

# Checks the authentication and return method
# used if authentication not failed.
# Returns 'smime', 'md5', 'dkim' or 'smtp' if authentication OK, undef else.
# Old name: Sympa::Commands::get_auth_method().
185
186
# DEPRECATED.  Use Sympa::Request::Handler::auth module to authorize requests.
#sub _get_auth_method;
187
188

1;
sikeda's avatar
sikeda committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
__END__

=encoding utf-8

=head1 NAME

Sympa::Spindle::AuthorizeRequest -
Workflow to authorize requests in command messages

=head1 DESCRIPTION

L<Sympa::Spindle::AuthorizeRequest> authorizes requests and stores them
into request spool or dispatch them.

TBD

=head2 Public methods

See also L<Sympa::Spindle/"Public methods">.

=over

=item new ( key =E<gt> value, ... )

In most cases, L<Sympa::Spindle::ProcessMessage>
214
splices messages to this class.  This method is not used in ordinal case.
sikeda's avatar
sikeda committed
215
216
217
218
219
220
221
222
223
224
225

=item spin ( )

Not implemented.

=back

=head1 SEE ALSO

L<Sympa::Request>, L<Sympa::Scenario>, L<Sympa::Spindle::DispatchRequest>,
L<Sympa::Spindle::ProcessMessage>, L<Sympa::Spindle::ProcessRequest>,
226
L<Sympa::Spindle::ToAuth>, L<Sympa::Spindle::ToAuthOwner>.
sikeda's avatar
sikeda committed
227
228
229
230
231
232

=head1 HISTORY

L<Sympa::Spindle::AuthorizeRequest> appeared on Sympa 6.2.13.

=cut