diff -Nur qpsmtpd-plugins-openfusion-20050429.old/plugins/whitelist_soft qpsmtpd-plugins-openfusion-20050429/plugins/whitelist_soft --- qpsmtpd-plugins-openfusion-20050429.old/plugins/whitelist_soft 2005-03-29 00:02:37.000000000 -0500 +++ qpsmtpd-plugins-openfusion-20050429/plugins/whitelist_soft 1969-12-31 19:00:00.000000000 -0500 @@ -1,223 +0,0 @@ -=head1 NAME - -whitelist_soft - whitelist override for other qpsmtpd plugins - - -=head1 DESCRIPTION - -The whitelist_soft plugin allows selected hosts or senders or recipients -to be whitelisted as exceptions to later plugin processing. It is a more -conservative variant of Devin Carraway's 'whitelist' plugin. - - -=head1 CONFIGURATION - -To enable the plugin, add it to the qpsmtpd/config/plugins file as usual. -It should precede any plugins you might wish to whitelist for. - -Several configuration files are supported, corresponding to different -parts of the SMTP conversation: - -=over 4 - -=item whitelisthosts - -Any IP address (or start-anchored fragment thereof) listed in the -whitelisthosts file is exempted from any further validation during -'connect', and can be selectively exempted at other stages by -plugins testing for a 'whitelisthost' connection note. - -Similarly, if the environment variable $WHITELISTCLIENT is set -(which can be done by tcpserver), the connection will be exempt from -further 'connect' validation, and the host can be selectively -exempted by other plugins testing for a 'whitelistclient' connection -note. - -=item whitelisthelo - -Any host that issues a HELO matching an entry in whitelisthelo will -be exempted from further validation at the 'helo' stage. Subsequent -plugins can test for a 'whitelisthelo' connection note. Note that -this does not actually amount to an authentication in any meaningful -sense. - -=item whitelistsenders - -If the envelope sender of a mail (that which is sent as the MAIL FROM) -matches an entry in whitelistsenders, or if the hostname component -matches, the mail will be exempted from any further validation within -the 'mail' stage. Subsequent plugins can test for this exemption as a -'whitelistsender' transaction note. - -=item whitelistrcpt - -If any recipient of a mail (that sent as the RCPT TO) matches an -entry from whitelistrcpt, or if the hostname component matches, no -further validation will be required for this recipient. Subsequent -plugins can test for this exemption using a 'whitelistrcpt' -transaction note, which holds the count of whitelisted recipients. - -=back - -whitelist_soft also supports per-recipient whitelisting when using -the per_user_config plugin. To enable the per-recipient behaviour -(delaying all whitelisting until the rcpt part of the smtp -conversation, and using per-recipient whitelist configs, if -available), pass a true 'per_recipient' argument in the -config/plugins invocation i.e. - - whitelist_soft per_recipient 1 - -By default global and per-recipient whitelists are merged; to turn off -the merge behaviour pass a false 'merge' argument in the config/plugins -invocation i.e. - - whitelist_soft per_recipient 1 merge 0 - - -=head1 BUGS - -Whitelist lookups are all O(n) linear scans of configuration files, even -though they're all associative lookups. Something should be done about -this when CDB/DB/GDBM configs are supported. - - -=head1 AUTHOR - -Based on the 'whitelist' plugin by Devin Carraway . - -Modified by Gavin Carr to not inherit -whitelisting across hooks, but use per-hook whitelist notes instead. -This is a more conservative approach e.g. whitelisting an IP will not -automatically allow relaying from that IP. - -=cut - -my $VERSION = 0.02; - -# Default is to merge whitelists in per_recipient mode -my %MERGE = ( merge => 1 ); - -sub register { - my ($self, $qp, %arg) = @_; - - $self->{_per_recipient} = 1 if $arg{per_recipient}; - $MERGE{merge} = $arg{merge} if defined $arg{merge}; - - # Normal mode - whitelist per hook - unless ($arg{per_recipient}) { - $self->register_hook("connect", "check_host"); - $self->register_hook("helo", "check_helo"); - $self->register_hook("ehlo", "check_helo"); - $self->register_hook("mail", "check_sender"); - $self->register_hook("rcpt", "check_rcpt"); - } - # Per recipient mode - defer all whitelisting to rcpt hook - else { - $self->register_hook("rcpt", "check_host"); - $self->register_hook("helo", "helo_helper"); - $self->register_hook("ehlo", "helo_helper"); - $self->register_hook("rcpt", "check_helo"); - $self->register_hook("rcpt", "check_sender"); - $self->register_hook("rcpt", "check_rcpt"); - } -} - -sub check_host { - my ($self, $transaction, $rcpt) = @_; - my $ip = $self->qp->connection->remote_ip || return (DECLINED); - - # From tcpserver - if (exists $ENV{WHITELISTCLIENT}) { - $self->qp->connection->notes('whitelistclient', 1); - $self->log(2,"host $ip is a whitelisted client"); - return OK; - } - - my $config_arg = $self->{_per_recipient} ? { rcpt => $rcpt, %MERGE } : {}; - for my $h ($self->qp->config('whitelisthosts', $config_arg)) { - if ($h eq $ip or $ip =~ /^\Q$h\E/) { - $self->qp->connection->notes('whitelisthost', 1); - $self->log(2,"host $ip is a whitelisted host"); - return OK; - } - } - return DECLINED; -} - -sub helo_helper { - my ($self, $transaction, $helo) = @_; - $self->{_whitelist_soft_helo} = $helo; - return DECLINED; -} - -sub check_helo { - my ($self, $transaction, $helo) = @_; - - # If per_recipient will be rcpt hook, and helo actually rcpt - my $config_arg = {}; - if ($self->{_per_recipient}) { - $config_arg = { rcpt => $helo, %MERGE }; - $helo = $self->{_whitelist_soft_helo}; - } - - for my $h ($self->qp->config('whitelisthelo', $config_arg)) { - if ($helo and lc $h eq lc $helo) { - $self->qp->connection->notes('whitelisthelo', 1); - $self->log(2,"helo host $helo in whitelisthelo"); - return OK; - } - } - return DECLINED; -} - -sub check_sender { - my ($self, $transaction, $sender) = @_; - - # If per_recipient will be rcpt hook, and sender actually rcpt - my $config_arg = {}; - if ($self->{_per_recipient}) { - $config_arg = { rcpt => $sender, %MERGE }; - $sender = $transaction->sender; - } - - return DECLINED if $sender->format eq '<>'; - my $addr = lc $sender->address or return DECLINED; - my $host = lc $sender->host or return DECLINED; - - for my $h ($self->qp->config('whitelistsenders', $config_arg)) { - next unless $h; - $h = lc $h; - - if ($addr eq $h or $host eq $h) { - $transaction->notes('whitelistsender', 1); - $self->log(2,"envelope sender $addr in whitelistsenders"); - return OK; - } - } - return DECLINED; -} - -sub check_rcpt { - my ($self, $transaction, $rcpt) = @_; - - my $addr = lc $rcpt->address or return DECLINED; - my $host = lc $rcpt->host or return DECLINED; - - my $config_arg = $self->{_per_recipient} ? { rcpt => $rcpt, %MERGE } : {}; - for my $h ($self->qp->config('whitelistrcpt', $config_arg)) { - next unless $h; - $h = lc $h; - - if ($addr eq $h or $host eq $h) { - my $note = $transaction->notes('whitelistrcpt'); - $transaction->notes('whitelistrcpt', ++$note); - $self->log(2,"recipient $addr in whitelistrcpt"); - return OK; - } - } - return DECLINED; -} - -# arch-tag: 15a093f1-2960-4dbe-be72-584d7ff1d92a -