1
--- amavisd.conf.ori Tue Jun 29 18:14:44 2004
2
+++ amavisd.conf Tue Jun 29 18:20:12 2004
5
# SMTP SERVER (INPUT) PROTOCOL SETTINGS (e.g. with Postfix, Exim v4, ...)
6
-# (used when MTA is configured to pass mail to amavisd via SMTP or LMTP)
7
-$inet_socket_port = 10024; # accept SMTP on this local TCP port
8
+# (used when MTA passing mail to amavisd via SMTP, LMTP or QMQPqq)
9
+$inet_socket_port = 10024; # accept on this local TCP port
10
# (default is undef, i.e. disabled)
11
-# multiple ports may be provided: $inet_socket_port = [10024, 10026, 10028];
12
+# multiple ports may be provided:
13
+# $inet_socket_port = [10024, 10026, 10028, 10628];
14
+# multiple protocols may be provided with multiple ports
15
+# (according to the protocol port settings below)
18
+$inet_smtp_port = 10024; # accept on this local TCP port
19
+ # (default is undef, i.e. disabled)
20
+# multiple ports may be provided: $inet_smtp_port = [10024, 10025];
22
+# QMQPqq port (can be used only with qmail)
23
+$inet_qmqpqq_port = 10628; # accept on this local TCP port
24
+ # (default is undef, i.e. disabled)
25
+# multiple ports may be provided: $inet_qmqpqq_port = [10628, 10629];
28
# SMTP SERVER (INPUT) access control
29
--- amavisd.ori Tue Jun 29 18:14:54 2004
30
+++ amavisd Tue Jun 29 18:20:12 2004
1
--- amavisd.ori Tue Jun 27 13:22:56 2006
2
+++ amavisd Tue Jun 27 13:30:29 2006
5
#( Amavis::In::Courier )
34
6
+# Amavis::In::QMQPqq
39
$unix_socketname $inet_socket_port $inet_socket_bind @inet_acl
40
+ $inet_smtp_port $inet_qmqpqq_port
41
$myhostname $localhost_name
44
&retcode &prolong_timer &sanitize_str &min &max
45
&strip_tempdir &rmdir_recursively &rmdir_flat
46
- &read_text &read_l10n_templates &read_hash &run_command);
47
+ &read_text &read_l10n_templates &read_hash &run_command
48
+ &if_exists_in_array);
51
@@ -1147,4 +1150,17 @@
54
+# returns undef if value does not exist in array or position of the first occurence in the array
55
+sub if_exists_in_array($$) {
56
+my($value,$ref) = @_;
57
+(ref $ref eq 'ARRAY') || return(undef);
59
+for(my $i=0;$i<@{$ref};$i++) {
60
+ if($value eq $ref->[$i]) {
69
@@ -1226,11 +1242,23 @@
70
sub received_line($$$$) {
71
my($conn, $msginfo, $id, $folded) = @_;
72
- my($smtp_proto,$recips) = ($conn->smtp_proto, $msginfo->recips);
75
+ if(defined $conn->smtp_proto) {
76
+ $proto = $conn->smtp_proto;
77
+ $helo = $conn->smtp_helo;
79
+ elsif(defined $conn->qmqp_proto) {
80
+ $proto = $conn->qmqp_proto;
81
+ $helo = $conn->qmqp_helo;
84
my($client_ip) = $conn->client_ip;
85
if ($client_ip =~ /:/ && $client_ip !~ /^IPv6:/i) {
86
$client_ip = 'IPv6:' . $client_ip;
89
+ my($recips) = $msginfo->recips;
90
my($s) = sprintf("from %s%s\n by %s%s (amavisd-new, %s)",
91
- ($conn->smtp_helo eq '' ? 'unknown' : $conn->smtp_helo),
92
+ ($helo eq '' ? 'unknown' : $helo),
93
($client_ip eq '' ? '' : " ([$client_ip])"),
96
: sprintf(" (%s [%s])", $myhostname, $conn->socket_ip)),
97
($conn->socket_port eq '' ? 'unix socket' : "port ".$conn->socket_port));
98
- $s .= "\n with $smtp_proto" if $smtp_proto =~ /^(ES|S|L)MTP$/i;
99
+ $s .= "\n with $proto" if defined($proto);
100
$s .= "\n id $id" if $id ne '';
101
# do not disclose if many
102
@@ -2180,4 +2208,8 @@
103
sub smtp_helo # (E)SMTP HELO/EHLO parameter
104
{ my($self)=shift; !@_ ? $self->{smtp_helo} : ($self->{smtp_helo}=shift) }
105
+sub qmqp_proto # QMQP/QMQPqq
106
+ { my($self)=shift; !@_ ? $self->{qmqp_proto}: ($self->{qmqp_proto}=shift) }
107
+sub qmqp_helo # for future use maybe
108
+ { my($self)=shift; !@_ ? $self->{qmqp_helo} : ($self->{qmqp_helo}=shift) }
111
@@ -4922,5 +4954,5 @@
112
import Amavis::Conf qw(:platform :confvars :notifyconf :sa);
113
import Amavis::Util qw(do_log debug_oneshot am_id prolong_timer
115
+ min max if_exists_in_array);
116
import Amavis::Timing qw(section_time);
118
@@ -4950,4 +4982,5 @@
119
use vars qw($extra_code_sql $extra_code_ldap
120
$extra_code_in_amcl $extra_code_in_smtp
121
+ $extra_code_in_qmqpqq
122
$extra_code_antivirus $extra_code_antispam);
124
@@ -4986,5 +5019,9 @@
125
@banned_filename @bad_headers);
127
-use vars qw($amcl_in_obj $smtp_in_obj); # Amavis::In::AMCL and In::SMTP objects
128
+use vars qw($amcl_in_obj); # Amavis::In::AMCL object
129
+use vars qw($smtp_in_obj); # Amavis::In::SMTP object
130
+use vars qw($qmqpqq_in_obj); # Amavis::In::QMQPqq object
131
+use vars qw($inet_smtp_port $inet_qmqpqq_port);
133
use vars qw($sql_policy $sql_wblist); # Amavis::Lookup::SQL objects
135
@@ -5175,15 +5212,22 @@
136
$conn->socket_port($prop->{sockport});
137
$conn->client_ip($prop->{peeraddr});
138
- if (!$extra_code_in_smtp) {
140
+ if (!$extra_code_in_smtp && !$extra_code_in_qmqpqq) {
141
die ("incomming TCP connection, but dynamic code ".
142
- "to handle SMTP or LMTP not loaded");
144
+ "to handle SMTP, LMTP or QMQPqq not loaded");
145
+ } elsif(defined if_exists_in_array($prop->{sockport},$inet_smtp_port)) {
146
my($lmtp); # false by default, start as a SMTP server
147
# $lmtp = $prop->{sockport} != 25 &&
148
# $prop->{sockport} != $inet_socket_port;
149
$smtp_in_obj = Amavis::In::SMTP->new if !$smtp_in_obj;
150
- $smtp_in_obj->process_smtp_request(
151
- $sock, $lmtp, $conn, \&check_mail);
152
+ $smtp_in_obj->process_smtp_request($sock, $lmtp, $conn, \&check_mail);
153
+ } elsif(defined if_exists_in_array($prop->{sockport},$inet_qmqpqq_port)) {
154
+ $qmqpqq_in_obj = Amavis::In::QMQPqq->new if !$qmqpqq_in_obj;
155
+ $qmqpqq_in_obj->process_qmqpqq_request($sock,$conn,\&check_mail);
156
+ } else { # better to be safe than sorry
157
+ die ("dynamic code to handle incomming TCP connection on port '" .
158
+ "$prop->{sockport}' is not loaded or does not exist (yet)");
162
die ("unsupported protocol: " . $sock->NS_proto);
163
@@ -5235,6 +5279,7 @@
164
local $SIG{CHLD} = 'DEFAULT';
165
# do_log(0, "Amavis::In::SMTP::DESTROY will be called from 'child_finish_hook'");
166
- $smtp_in_obj = undef; # calls Amavis::In::SMTP::DESTROY
167
- $amcl_in_obj = undef; # (currently does nothing for Amavis::In::AMCL)
168
+ $smtp_in_obj = undef; # calls Amavis::In::SMTP::DESTROY
169
+ $qmqpqq_in_obj = undef; # calls Amavis::In::QMQPqq::DESTROY
170
+ $amcl_in_obj = undef; # (currently does nothing for Amavis::In::AMCL)
173
@@ -6483,5 +6528,5 @@
174
map { chomp($_ = <Amavis::DATA>) }
175
($extra_code_sql, $extra_code_ldap,
176
- $extra_code_in_amcl, $extra_code_in_smtp,
177
+ $extra_code_in_amcl, $extra_code_in_smtp, $extra_code_in_qmqpqq,
178
$extra_code_antivirus, $extra_code_antispam,
180
@@ -6510,5 +6555,5 @@
181
$amavisd_path = $1 if $amavisd_path=~m{^([A-Za-z0-9/._=+-]+)$(?!\n)}; # untaint
183
-my($config_file) = '/etc/amavisd.conf'; # default location of config file
184
+my($config_file) = '/usr/local/etc/amavisd.conf'; # default location of config file
185
if (@ARGV >= 2 && $ARGV[0] eq '-c') { # override by command line option -c
186
shift @ARGV; $config_file = shift @ARGV;
187
@@ -6537,10 +6582,88 @@
188
$extra_code_in_amcl = 1; # release memory occupied by the source code
190
-if ($inet_socket_port eq '' || ref $inet_socket_port && !@$inet_socket_port) {
191
- $extra_code_in_smtp = undef;
193
- eval $extra_code_in_smtp or die "Problem in the In::SMTP code: $@";
194
- $extra_code_in_smtp = 1; # release memory occupied by the source code
197
+# make it a reference
198
+$inet_socket_port = ($inet_socket_port eq ''?
199
+ undef : (ref $inet_socket_port?
200
+ (@$inet_socket_port ?
201
+ $inet_socket_port : undef) : [$inet_socket_port]));
203
+if(!ref $inet_socket_port) {
204
+ $extra_code_in_smtp = undef;
205
+ $extra_code_in_qmqpqq = undef;
208
+ # make it a reference
209
+ $inet_smtp_port = ($inet_smtp_port eq ''?
210
+ undef : (ref $inet_smtp_port?
211
+ (@$inet_smtp_port ?
212
+ [@$inet_smtp_port] : undef) : [$inet_smtp_port]));
213
+ # make it a reference
214
+ $inet_qmqpqq_port = ($inet_qmqpqq_port eq ''?
215
+ undef : (ref $inet_qmqpqq_port ?
216
+ (@$inet_qmqpqq_port ?
217
+ [@$inet_qmqpqq_port] : undef) : [$inet_qmqpqq_port]));
219
+ # check whether these two does not overlay
220
+ if(ref $inet_smtp_port && ref $inet_qmqpqq_port) {
221
+ foreach my $port (@$inet_smtp_port) {
222
+ (!defined if_exists_in_array($port,$inet_qmqpqq_port)) ||
223
+ die("QMQPqq port '$port' is already assigned to SMTP/LMTP");
227
+ # check whether every $inet_socket_port is assigned some service
228
+ foreach my $port (@$inet_socket_port) {
229
+ if(ref $inet_smtp_port && defined if_exists_in_array($port,$inet_smtp_port)) {
232
+ if(ref $inet_qmqpqq_port && defined if_exists_in_array($port,$inet_qmqpqq_port)) {
235
+ die("Port '$port' is not assigned any service");
238
+ if(ref $inet_smtp_port) {
239
+ # check whether $inet_smtp_port is in $inet_socket_port
240
+ my $if_any = undef;
241
+ foreach my $port (@$inet_smtp_port) {
242
+ if(defined if_exists_in_array($port,$inet_socket_port)) {
248
+ $extra_code_in_smtp = undef; # feature not a bug
251
+ eval $extra_code_in_smtp || die("Problem in the In::SMTP code: $@");
252
+ $extra_code_in_smtp = 1; # release memory occupied by the source code
256
+ $extra_code_in_smtp = undef;
259
+ if(ref $inet_qmqpqq_port) {
260
+ # check whether $inet_qmqpqq_port is in $inet_socket_port
261
+ my $if_any = undef;
262
+ foreach my $port (@$inet_qmqpqq_port) {
263
+ if(defined if_exists_in_array($port,$inet_socket_port)) {
269
+ $extra_code_in_qmqpqq = undef; # feature not a bug
272
+ eval $extra_code_in_qmqpqq || die("Problem in the In::QMQPqq code: $@");
273
+ $extra_code_in_qmqpqq = 1; # release memory occupied by the source code
277
+ $extra_code_in_qmqpqq = undef;
281
if (!@av_scanners && !@av_scanners_backup) {
282
@@ -6633,4 +6756,5 @@
283
do_log(1, "AMCL-in protocol code ".($extra_code_in_amcl?'':" NOT")." loaded");
284
do_log(1, "SMTP-in protocol code ".($extra_code_in_smtp?'':" NOT")." loaded");
285
+do_log(1, "QMQPqq-in protocol code ".($extra_code_in_qmqpqq?'':" NOT")." loaded");
286
do_log(1, "ANTI-VIRUS code ".($extra_code_antivirus?'':" NOT")." loaded");
287
do_log(1, "ANTI-SPAM code ".($extra_code_antispam?'':" NOT")." loaded");
288
@@ -7942,4 +8066,329 @@
289
@{$self->{smtp_outbuf}} = ();
10
: sprintf(" (%s [%s])", c('myhostname'), $conn->socket_ip) ),
11
($conn->socket_port eq '' ? 'unix socket' : "port ".$conn->socket_port) );
12
+ # must not use proto name QMQPqq in 'with'
13
$s .= "\n with $smtp_proto" if $smtp_proto=~/^(ES|S|L)MTPS?A?\z/i; # rfc3848
14
$s .= "\n id $id" if $id ne '';
16
$extra_code_sql_lookup $extra_code_ldap
17
$extra_code_in_amcl $extra_code_in_smtp $extra_code_in_courier
18
+ $extra_code_in_qmqpqq
19
$extra_code_out_smtp $extra_code_out_pipe
20
$extra_code_out_bsmtp $extra_code_out_local $extra_code_p0f
22
# Amavis::In::AMCL, Amavis::In::SMTP and In::Courier objects
23
use vars qw($amcl_in_obj $smtp_in_obj $courier_in_obj);
24
+use vars qw($qmqpqq_in_obj); # Amavis::In::QMQPqq object
25
use vars qw($sql_dataset_conn_lookups); # Amavis::Out::SQL::Connection object
26
use vars qw($sql_dataset_conn_storage); # Amavis::Out::SQL::Connection object
28
do_log(0,"SMTP-in proto code %s loaded", $extra_code_in_smtp ?'':" NOT");
29
do_log(0,"Courier proto code %s loaded", $extra_code_in_courier ?'':" NOT");
30
+ do_log(0,"QMQPqq-in proto code %s loaded", $extra_code_in_qmqpqq ?'':" NOT");
31
do_log(0,"SMTP-out proto code %s loaded", $extra_code_out_smtp ?'':" NOT");
32
do_log(0,"Pipe-out proto code %s loaded", $extra_code_out_pipe ?'':" NOT");
33
@@ -7214,4 +7219,10 @@
34
$amcl_in_obj = Amavis::In::AMCL->new if !$amcl_in_obj;
35
$amcl_in_obj->process_policy_request($sock, $conn, \&check_mail, 0);
36
+ } elsif ($suggested_protocol eq 'QMQPqq') {
37
+ if (!$extra_code_in_qmqpqq) {
38
+ die "incoming TCP connection, but dynamic QMQPqq code not loaded";
40
+ $qmqpqq_in_obj = Amavis::In::QMQPqq->new if !$qmqpqq_in_obj;
41
+ $qmqpqq_in_obj->process_qmqpqq_request($sock,$conn,\&check_mail);
42
} else { # defaults to SMTP or LMTP
43
if (!$extra_code_in_smtp) {
45
do_log(5,"child_finish_hook: invoking DESTROY methods");
46
undef $smtp_in_obj; undef $amcl_in_obj; undef $courier_in_obj;
47
+ undef $qmqpqq_in_obj;
48
undef $sql_storage; undef $sql_wblist; undef $sql_policy; undef $ldap_policy;
49
undef $sql_dataset_conn_lookups; undef $sql_dataset_conn_storage;
51
# do_log(5,"at the END handler: invoking DESTROY methods");
52
undef $smtp_in_obj; undef $amcl_in_obj; undef $courier_in_obj;
53
+ undef $qmqpqq_in_obj;
54
undef $sql_storage; undef $sql_wblist; undef $sql_policy; undef $ldap_policy;
55
undef $sql_dataset_conn_lookups; undef $sql_dataset_conn_storage;
57
$extra_code_sql_lookup, $extra_code_ldap,
58
$extra_code_in_amcl, $extra_code_in_smtp, $extra_code_in_courier,
59
+ $extra_code_in_qmqpqq,
60
$extra_code_out_smtp, $extra_code_out_pipe,
61
$extra_code_out_bsmtp, $extra_code_out_local, $extra_code_p0f,
62
@@ -9455,5 +9469,10 @@
63
$extra_code_in_courier = undef;
65
- if ($needed_protocols_in{'QMQPqq'}) { die "In::QMQPqq code not available" }
66
+ if ($needed_protocols_in{'QMQPqq'}) {
67
+ eval $extra_code_in_qmqpqq or die "Problem in the In::QMQPqq code: $@";
68
+ $extra_code_in_qmqpqq = 1; # release memory occupied by the source code
70
+ $extra_code_in_qmqpqq = undef;
74
@@ -12152,4 +12171,270 @@
76
BEGIN { die "Code not available for module Amavis::In::Courier" }
322
108
+ my($class) = @_;
323
109
+ my($self) = bless {}, $class;
324
+ $self->{fh_pers} = undef; # persistent file handle for email.txt
325
+ $self->{tempdir_pers} = undef; # temporary directory for check_mail
326
+ $self->{preserve} = undef; # don't delete tempdir on exit
327
+ $self->{tempdir_empty} = 1; # anything of interest in tempdir?
328
110
+ $self->{bytesleft} = undef; # bytes left for whole package
329
111
+ $self->{len} = undef; # set by getlen() method
330
112
+ $self->{sock} = undef; # connected socket
331
113
+ $self->{proto} = undef; # protocol
114
+ $self->{tempdir} = Amavis::TempDir->new; # TempDir object
332
115
+ $self->{session_closed_normally} = undef; # closed properly? (waited for K/Z/D)
336
+sub preserve_evidence # try to preserve temporary files etc in case of trouble
337
+ { my($self)=shift; !@_ ? $self->{preserve} : ($self->{preserve}=shift) }
341
+# do_log(0, "Amavis::In::QMQPqq::DESTROY called");
342
+ $self->{fh_pers}->close
343
+ or die "Can't close temp file: $!" if $self->{fh_pers};
344
+ my($errn) = $self->{tempdir_pers} eq '' ? ENOENT
345
+ : (stat($self->{tempdir_pers}) ? 0 : 0+$!);
346
+ if (defined $self->{tempdir_pers} && $errn != ENOENT) {
347
+ # this will not be included in the TIMING report,
348
+ # but it only occurs infrequently and doesn't take that long
349
+ if ($self->preserve_evidence && !$self->{tempdir_empty}) {
350
+ do_log(0, "tempdir is to be PRESERVED: ".$self->{tempdir_pers});
352
+ do_log(2, "tempdir being removed: ".$self->{tempdir_pers});
353
+ rmdir_recursively($self->{tempdir_pers});
356
+ if (! $self->{session_closed_normally}) {
357
+ $self->qmqpqq_resp("Z","Service shutting down, closing channel");
361
+sub prepare_tempdir($) {
363
+ if (! defined $self->{tempdir_pers} ) {
364
+ # invent a name for a temporary directory for this child, and create it
365
+ my($now_iso8601) = strftime("%Y%m%dT%H%M%S", localtime);
366
+ $self->{tempdir_pers} = sprintf("%s/amavis-%s-%05d",
367
+ $TEMPBASE, $now_iso8601, $$);
369
+ my($errn) = stat($self->{tempdir_pers}) ? 0 : 0+$!;
370
+ if ($errn == ENOENT || ! -d _) {
371
+ mkdir($self->{tempdir_pers}, 0750)
372
+ or die "Can't create directory $self->{tempdir_pers}: $!";
373
+ $self->{tempdir_empty} = 1;
374
+ section_time('mkdir tempdir');
376
+ # prepare temporary file for writing (and reading later)
377
+ my($fname) = $self->{tempdir_pers} . "/email.txt";
378
+ my($errn) = stat($fname) ? 0 : 0+$!;
379
+ if ($self->{fh_pers} && !$errn && -f _) {
380
+ $self->{fh_pers}->seek(0,0) or die "Can't rewind mail file: $!";
381
+ $self->{fh_pers}->truncate(0) or die "Can't truncate mail file: $!";
383
+ $self->{fh_pers} = IO::File->new($fname, 'w+', 0640)
384
+ or die "Can't create file $fname: $!";
385
+ section_time('create email.txt');
121
+ eval { do_log(5,"Amavis::In::QMQPqq DESTROY called, sock=%s, normal=%s",
122
+ $self->{sock}, $self->{session_closed_normally}) };
124
+ if (ref($self->{sock}) && ! $self->{session_closed_normally}) {
125
+ $self->qmqpqq_resp("Z","Service shutting down, closing channel");
129
+ { my($eval_stat) = $@; eval { do_log(1,"QMQPqq shutdown: %s",$eval_stat) } }
390
132
+# get byte, die if no bytes left
391
133
+sub getbyte($) {