"Fossies" - the Fresh Open Source Software Archive

Member "amavisd-new-2.11.1/amavisd-new-qmqpqq.patch" (9 Oct 2018, 11264 Bytes) of package /linux/misc/amavisd-new-2.11.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Diff source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "amavisd-new-qmqpqq.patch": 2.11.0_vs_2.11.1.

    1 --- amavisd.ori 2017-12-27 16:33:03.000000000 +0100
    2 +++ amavisd 2018-10-09 14:36:42.767443000 +0200
    3 @@ -109,4 +109,5 @@
    4  #  Amavis::In::SMTP
    5  #( Amavis::In::Courier )
    6 +#  Amavis::In::QMQPqq
    7  #  Amavis::Out::SMTP::Protocol
    8  #  Amavis::Out::SMTP::Session
    9 @@ -5351,4 +5352,5 @@
   10    # RFC 3848, RFC 6531
   11    # http://www.iana.org/assignments/mail-parameters/mail-parameters.xhtml
   12 +  # must not use proto name QMQPqq in 'with'
   13    $s .= "\n with $smtp_proto"
   14      if $smtp_proto =~ /^ (?: SMTP | (?: ES|L|UTF8S|UTF8L) MTP S? A? ) \z/xsi;
   15 @@ -12113,4 +12115,5 @@
   16    $extra_code_sql_lookup $extra_code_ldap
   17    $extra_code_in_ampdp $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
   21 @@ -12140,4 +12143,5 @@
   22  # Amavis::In::AMPDP, Amavis::In::SMTP and In::Courier objects
   23  use vars qw($ampdp_in_obj $smtp_in_obj $courier_in_obj);
   24 +use vars qw($qmqpqq_in_obj);            # Amavis::In::QMQPqq object
   25  
   26  use vars qw($sql_dataset_conn_lookups); # Amavis::Out::SQL::Connection object
   27 @@ -12876,4 +12880,5 @@
   28    my(@msg);
   29    my $euid = $>;  # effective UID
   30 +  do_log(0,"QMQPqq-in proto code %s loaded", $extra_code_in_qmqpqq ?'':" NOT");
   31    $> = 0;         # try to become root
   32    POSIX::setuid(0)  if $> != 0;  # and try some more
   33 @@ -13691,5 +13696,9 @@
   34        die "unavailable support for protocol: $suggested_protocol";
   35      } elsif ($suggested_protocol eq 'QMQPqq') {
   36 -      die "unavailable support for protocol: $suggested_protocol";
   37 +      if (!$extra_code_in_qmqpqq) {
   38 +        die "incoming TCP connection, but dynamic QMQPqq code not loaded";
   39 +      }
   40 +      $qmqpqq_in_obj = Amavis::In::QMQPqq->new if !$qmqpqq_in_obj;
   41 +      $qmqpqq_in_obj->process_qmqpqq_request($sock,$conn,\&check_mail);
   42      } elsif ($suggested_protocol eq 'TCP-LOOKUP') { #postfix maps, experimental
   43        process_tcp_lookup_request($sock, $conn);
   44 @@ -13815,4 +13824,5 @@
   45    do_log_safe(5,"child_finish_hook: invoking DESTROY methods");
   46    undef $smtp_in_obj; undef $ampdp_in_obj; undef $courier_in_obj;
   47 +  undef $qmqpqq_in_obj;
   48    undef $sql_storage; undef $sql_wblist; undef $sql_lookups;
   49    undef $sql_dataset_conn_lookups; undef $sql_dataset_conn_storage;
   50 @@ -18906,4 +18916,5 @@
   51      $extra_code_sql_lookup, $extra_code_ldap,
   52      $extra_code_in_ampdp, $extra_code_in_smtp, $extra_code_in_courier,
   53 +    $extra_code_in_qmqpqq,
   54      $extra_code_out_smtp, $extra_code_out_pipe,
   55      $extra_code_out_bsmtp, $extra_code_out_local,
   56 @@ -19257,5 +19268,11 @@
   57      undef $extra_code_in_courier;
   58    }
   59 -  if ($needed_protocols_in{'QMQPqq'})  { die "In::QMQPqq code not available" }
   60 +  if ($needed_protocols_in{'QMQPqq'}) {
   61 +    eval $extra_code_in_qmqpqq or die "Problem in the In::QMQPqq code: $@";
   62 +    # release memory occupied by the source code
   63 +    undef $extra_code_in_qmqpqq; $extra_code_in_qmqpqq = 1;
   64 +  } else {
   65 +    undef $extra_code_in_qmqpqq;
   66 +  }
   67  }
   68  
   69 @@ -23508,4 +23525,276 @@
   70  __DATA__
   71  #
   72 +package Amavis::In::QMQPqq;
   73 +use strict;
   74 +# use re 'taint';   # (is this module ready for this yet?)
   75 +
   76 +BEGIN {
   77 +    use Exporter ();
   78 +    use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
   79 +    $VERSION = '1.18';
   80 +    @ISA = qw(Exporter);
   81 +}
   82 +use POSIX qw(strftime);
   83 +use Errno qw(ENOENT);
   84 +
   85 +BEGIN {
   86 +    import Amavis::Conf qw(:platform :confvars :dynamic_confvars c cr ca);
   87 +    import Amavis::Util qw(ll do_log am_id new_am_id prolong_timer
   88 +                           debug_oneshot sanitize_str rmdir_recursively);
   89 +    import Amavis::Lookup qw(lookup);
   90 +    import Amavis::Timing qw(section_time);
   91 +    import Amavis::rfc2821_2822_Tools;
   92 +    import Amavis::TempDir;
   93 +    import Amavis::In::Message;
   94 +    import Amavis::In::Connection;
   95 +}
   96 +
   97 +sub new($) {
   98 +    my($class) = @_;
   99 +    my($self) = bless {}, $class;
  100 +    $self->{bytesleft} = undef;        # bytes left for whole package
  101 +    $self->{len} = undef;      # set by getlen() method
  102 +    $self->{sock} = undef;     # connected socket
  103 +    $self->{proto} = undef;        # protocol
  104 +    $self->{tempdir} = Amavis::TempDir->new;   # TempDir object
  105 +    $self->{session_closed_normally} = undef; # closed properly? (waited for K/Z/D)
  106 +    $self;
  107 +}
  108 +
  109 +sub DESTROY {
  110 +  my($self) = shift;
  111 +  eval { do_log(5,"Amavis::In::QMQPqq DESTROY called, sock=%s, normal=%s",
  112 +                  $self->{sock}, $self->{session_closed_normally}) };
  113 +  eval {
  114 +    if (ref($self->{sock}) && ! $self->{session_closed_normally}) {
  115 +      $self->qmqpqq_resp("Z","Service shutting down, closing channel");
  116 +    }
  117 +  };
  118 +  if ($@ ne '')
  119 +    { my($eval_stat) = $@; eval { do_log(1,"QMQPqq shutdown: %s",$eval_stat) } }
  120 +}
  121 +
  122 +# get byte, die if no bytes left
  123 +sub getbyte($) {
  124 +my($self) = shift;
  125 +if(!$self->{bytesleft}--) {
  126 +   die("No bytes left");
  127 +   }
  128 +if(defined($_ = $self->{sock}->getc)) {
  129 +   return($_);
  130 +   }
  131 +die("EOF on socket");
  132 +}
  133 +
  134 +sub getlen($) {
  135 +my($self) = shift;
  136 +my($ch,$len);
  137 +
  138 +for(;;) {
  139 +   $ch = $self->getbyte;
  140 +   if($ch eq ':') {
  141 +       return($self->{len} = $len);
  142 +       }
  143 +   if($ch !~ /^\d$/) {
  144 +       die("Char '$ch' is not a number while determining length");
  145 +       }
  146 +   $len .= $ch;
  147 +   }
  148 +}
  149 +
  150 +sub getcomma($) {
  151 +my($self) = shift;
  152 +if($self->getbyte ne ',') {
  153 +   die("Comma expected, found '$_'");
  154 +   }
  155 +}
  156 +
  157 +sub getnetstring($$) {
  158 +my($self) = shift;
  159 +($self->{sock}->read($_[0],$self->getlen) == $self->{len}) ||
  160 +   die("EOF on socket");
  161 +$self->{bytesleft} -= $self->{len};
  162 +$self->getcomma;
  163 +}
  164 +
  165 +# Accept a QMQPqq connect
  166 +# and call content checking for the message received
  167 +#
  168 +sub process_qmqpqq_request($$$$) {
  169 +my($self,$sock,$conn,$check_mail) = @_;
  170 +# $sock:       connected socket from Net::Server
  171 +# $conn:       information about client connection
  172 +# $check_mail: subroutine ref to be called with file handle
  173 +
  174 +$self->{proto} = "QMQPqq";
  175 +$self->{session_closed_normally} = 0;  # closed properly?
  176 +$self->{sock} = $sock;     # store $sock info for getbyte() method
  177 +$self->{bytesleft} = 20;   # initial bytesleft value, there should
  178 +               # NEVER EVER be longer email than 10^20 (approximately)
  179 +               # bytes but increase if needed ;)
  180 +$self->{len} = undef;
  181 +
  182 +my($msginfo);
  183 +my($sender,@recips);
  184 +my($len);
  185 +
  186 +new_am_id(undef, $Amavis::child_invocation_count, undef);
  187 +Amavis::Timing::init();
  188 +
  189 +$conn->smtp_proto("QMQPqq");  # the name of the method is too specific
  190 +my($eval_stat);
  191 +eval {
  192 +   # get length of whole package
  193 +   $self->{bytesleft} = $self->getlen;
  194 +
  195 +   # get length of 'email'
  196 +   $len = $self->getlen;
  197 +   section_time('initial length determination');
  198 +
  199 +   # prepare tempdir
  200 +   Amavis::check_mail_begin_task();
  201 +   $self->{tempdir}->prepare;
  202 +   $self->{tempdir}->prepare_file;
  203 +
  204 +   $msginfo = Amavis::In::Message->new;
  205 +   $msginfo->rx_time(time);
  206 +   $msginfo->delivery_method(c('forward_method'));
  207 +
  208 +   # get 'email'
  209 +   $self->{tempdir}->empty(0);
  210 +   my $size = 16384;
  211 +   while(($len > 0) && ($sock->read($_,($len >= $size ? $size : $size = $len)) == $size)) {
  212 +       (print {$self->{tempdir}->fh} $_) ||
  213 +           die("Can't write to mail file: $!");
  214 +       $len -= $size;
  215 +       }
  216 +   if($len > 0) {
  217 +       die("EOF on socket");
  218 +       }
  219 +   $self->{tempdir}->fh->flush || die("Can't flush mail file: $!");
  220 +   $self->{tempdir}->fh->seek(0,1) || die("Can't seek on file: $!");
  221 +   $self->{bytesleft} -= $self->{len};
  222 +   section_time('email receiving');
  223 +   # comma has to follow
  224 +   $self->getcomma;
  225 +
  226 +   # get sender (presumably in unquoted form, really???)
  227 +   $self->getnetstring($sender);
  228 +   section_time('sender receiving');
  229 +
  230 +   # get recips (presumably in unquoted form, really???)
  231 +   my $i = 0;
  232 +   while($self->{bytesleft}) {
  233 +       $self->getnetstring($recips[$i++]);
  234 +       }
  235 +   section_time('recips receiving');
  236 +
  237 +   # final comma has to follow
  238 +   $self->{bytesleft} = 1;
  239 +   $self->getcomma;
  240 +       
  241 +   $msginfo->sender($sender);
  242 +   $msginfo->sender_smtp(qquote_rfc2821_local($sender));
  243 +   $msginfo->recips(\@recips);
  244 +       
  245 +   do_log(1, sprintf("%s:%s:%s %s: %s -> %s Received: %s",
  246 +       $self->{proto},$conn->socket_ip eq $inet_socket_bind ?
  247 +           '' : '['.$conn->socket_ip.']',
  248 +       $conn->socket_port, $self->{tempdir_pers},
  249 +       $msginfo->sender_smtp,
  250 +                join(',', map { $_->recip_addr_smtp }
  251 +                              @{$msginfo->per_recip_data}),
  252 +       join(' ',
  253 +           ($msginfo->msg_size  eq '' ? ()
  254 +           : 'SIZE='.$msginfo->msg_size),
  255 +           ($msginfo->body_type eq '' ? ()
  256 +           : 'BODY='.$msginfo->body_type),
  257 +           received_line($conn,$msginfo,am_id(),0) )
  258 +       ));
  259 +
  260 +   $msginfo->mail_tempdir($self->{tempdir}->path);
  261 +   $msginfo->mail_text_fn($self->{tempdir}->path . '/email.txt');
  262 +   $msginfo->mail_text($self->{tempdir}->fh);
  263 +
  264 +   my($smtp_resp,$exit_code,$preserve_evidence) =
  265 +       &$check_mail($conn,$msginfo,0);
  266 +
  267 +   if ($preserve_evidence) { $self->{tempdir}->preserve(1) }
  268 +
  269 +   if ($smtp_resp !~ /^4/ &&
  270 +       grep { !$_->recip_done } @{$msginfo->per_recip_data}) {
  271 +       die("TROUBLE/MISCONFIG: not all recipients done, ".
  272 +           "\$forward_method is \"$forward_method\"");
  273 +       }
  274 +
  275 +   if ($smtp_resp !~ /^4/ &&
  276 +       grep { !$_->recip_done } @{$msginfo->per_recip_data}) {
  277 +       if ($msginfo->delivery_method eq '') {
  278 +           do_log(2,"not all recipients done, forward_method is empty");
  279 +           }
  280 +       else {
  281 +           die "TROUBLE: (MISCONFIG) not all recipients done, " .
  282 +           "forward_method is: " . $msginfo->delivery_method;
  283 +           }
  284 +       }
  285 +
  286 +   # all ok
  287 +   if($smtp_resp =~ /^2/) {
  288 +       $self->qmqpqq_resp("K",$smtp_resp);
  289 +       }
  290 +   # permanent reject
  291 +   elsif($smtp_resp =~ /^5/) {
  292 +       $self->qmqpqq_resp("D",$smtp_resp);
  293 +       }
  294 +   # temporary reject (or other error if !~ /^4/)
  295 +   else {
  296 +       $self->qmqpqq_resp("Z",$smtp_resp);
  297 +       }
  298 +   1;
  299 +} or do {
  300 +   $eval_stat = $@ ne '' ? $@ : "errno=$!";
  301 +};
  302 +
  303 +$self->{tempdir}->clean;
  304 +alarm(0); do_log(4,"timer stopped after QMQPqq eval");
  305 +
  306 +if($eval_stat ne '') {
  307 +   chomp $eval_stat;
  308 +   do_log(0,"QMQPqq: NOTICE: $eval_stat");
  309 +   $self->qmqpqq_resp("Z","Service shutting down, $eval_stat");
  310 +   }
  311 +# report elapsed times by section for each transaction
  312 +do_log(2, "%s", Amavis::Timing::report());
  313 +
  314 +$self->{session_closed_normally} = 1;
  315 +# closes connection after child_finish_hook
  316 +}
  317 +
  318 +# sends a QMQPqq response consisting of K/D/Z code and an optional message;
  319 +# slow down evil clients by delaying response on permanent errors
  320 +sub qmqpqq_resp($$$;$$) {
  321 +my($self,$code,$resp,$penalize,$line) = @_;
  322 +if($code !~ /^(K|Z|D)$/) {
  323 +   die("Internal error(2): bad QMQPqq response code: '$code'");
  324 +   }
  325 +if($penalize) {
  326 +   do_log(0,"QMQPqq: $resp; PENALIZE: $line");
  327 +   sleep 5;
  328 +   section_time('QMQPqq penalty wait');
  329 +   }
  330 +$resp = sanitize_str($resp,1);
  331 +do_log(4,"QMQPqq> $resp");
  332 +$self->{sock}->print($self->netstring($code . $resp));
  333 +}
  334 +
  335 +sub netstring($$) {
  336 +my($self,$string) = @_;
  337 +return(sprintf("%d:%s,",length($string),$string));
  338 +}
  339 +
  340 +1;
  341 +
  342 +__DATA__
  343 +#
  344  package Amavis::Out::SMTP::Protocol;
  345  use strict;
  346 --- amavisd.conf.ori    2017-12-27 19:25:28.006677000 +0100
  347 +++ amavisd.conf    2018-10-09 14:36:42.768450000 +0200
  348 @@ -56,6 +56,6 @@
  349                 # option(s) -p overrides $inet_socket_port and $unix_socketname
  350  
  351 -$inet_socket_port = 10024;   # listen on this local TCP port(s)
  352 -# $inet_socket_port = [10024,10026];  # listen on multiple TCP ports
  353 +$protocol = 'QMQPqq';        # suggested protocol to use on all input sockets
  354 +$inet_socket_port = 10628;   # accept connections on this local TCP port(s)
  355  
  356  $policy_bank{'MYNETS'} = {   # mail originating from @mynetworks