Policy attributes to PERL script

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Policy attributes to PERL script

MickTW8
Hello all,

I am having trouble accessing postfix attributes from within a PERL script sent using smtpd_data_restrictions. I ought to say I am a novice to both postfix and PERL. The Postfix config files look like this ;

Master.cf ;
policy-pl unix -       n       n       -       -       spawn    user=nobody argv=/etc/postfix/quota.pl -v

main.cf  ;
smtpd_data_restrictions = check_policy_service unix:private/policy-pl

The PERL script is being definately being called as if I get it to print "action=REJECT Go away!"; All SMTP mail is sucessfully blocked with that message displayed, "action=DUNNO" allows mail to pass.

This issue I have is knowing how to read any of the attributes listed here www.postfix.org/SMTPD_POLICY_README.html#protocol

I have tried using $attr = @_; and local(*attr) =@ _;  to retreive the variables but $attr always remains empty. I have also set up the script to write the contents and element count of $attr which shows me "" and 0.

Does anyone know if postfix need any more configuration to send the attributes or am I missing something at the PERL end?

I apologise if this has been asked before.

Thanks in advance,
Mick.
Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

Jan P. Kessler-2

> This issue I have is knowing how to read any of the attributes listed here
> www.postfix.org/SMTPD_POLICY_README.html#protocol
>
> I have tried using $attr = @_; and local(*attr) =@ _;  to retreive the
> variables but $attr always remains empty. I have also set up the script to
> write the contents and element count of $attr which shows me "" and 0.

You have to read them from STDIN, as shown on the same page (greylisting
example)

http://www.postfix.org/SMTPD_POLICY_README.html#greylist_code

Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

Scott Kitterman-4
In reply to this post by MickTW8
On Friday, February 27, 2015 06:45:07 AM MickTW8 wrote:

> Hello all,
>
> I am having trouble accessing postfix attributes from within a PERL script
> sent using smtpd_data_restrictions. I ought to say I am a novice to both
> postfix and PERL. The Postfix config files look like this ;
>
> Master.cf ;
> policy-pl unix -       n       n       -       -       spawn    user=nobody
> argv=/etc/postfix/quota.pl -v
>
> main.cf  ;
> smtpd_data_restrictions = check_policy_service unix:private/policy-pl
>
> The PERL script is being definately being called as if I get it to print
> "action=REJECT Go away!"; All SMTP mail is sucessfully blocked with that
> message displayed, "action=DUNNO" allows mail to pass.
>
> This issue I have is knowing how to read any of the attributes listed here
> www.postfix.org/SMTPD_POLICY_README.html#protocol
>
> I have tried using $attr = @_; and local(*attr) =@ _;  to retreive the
> variables but $attr always remains empty. I have also set up the script to
> write the contents and element count of $attr which shows me "" and 0.
>
> Does anyone know if postfix need any more configuration to send the
> attributes or am I missing something at the PERL end?
>
> I apologise if this has been asked before.

Here's a link to a working Perl exampl:

http://bazaar.launchpad.net/~kitterman/postfix-policyd-spf-perl/trunk/view/head:/postfix-policyd-spf-perl

Scott K
Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

MickTW8
Thanks for pointing out STDIN Jan. It really helps to know what I am looking for. Thanks Scott for the working example. I've got something to go on now.  Both your replies are very much appreciated.

Mick.
Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

Markus Benning
In reply to this post by MickTW8
Am 2015-02-27 14:45, schrieb MickTW8:
> This issue I have is knowing how to read any of the attributes listed
> here
> www.postfix.org/SMTPD_POLICY_README.html#protocol

Hello Mick,

it may be an option for your to implement your code as a plugin for
mtpolicyd.
There's documentation for wrinting a simple plugin at:

https://www.mtpolicyd.org/getting-started.html#Mail::MtPolicyd::Cookbook::BasicModule

Then you wont have to care about accepting connections, parsing, logging
and so on.

Another option may be to just copy over the Request class to your
project and remove
dependencies on Net::Server, etc. from it:

https://github.com/benningm/mtpolicyd/blob/master/lib/Mail/MtPolicyd/Request.pm

  Markus


--
Markus Benning, https://markusbenning.de/
Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

MickTW8
Hello Markus,

Thanks very much for your reply.  I didn't come across Cookbook in my
searches but I don't think I will need it now as I'm very pleased to
report I got my first test policy implemented yesterday evening. Don't
laugh, all it does so far is block senders where 'sender' doesn't match
'sasl-user'. Everyone has to start somewhere right? It does put me in a
place where I can write customised policies now.  I was thinking of
using mysql but everyone seems to use Berkeley DB? Maybe worth
considering as it has a locking arrangement.

One of my user email accounts was compromised a couple of months ago and
over a period of 5 hours thousands of SPAM messages were sent. Grrrr!
Since then I have become rather paranoid checking the mail log whenever
I can looking for "Relay=' and auth failures manually barring IPs that
repeatedly fail to log in.  I need to relax a bit so decided to try and
write a SPAM limitation policy, as in ;

 if (X number of messages sent in Y  time), {
  external relay access blocked until user resets password
}.

To do this I needed to read  the SASL_USERNAME field into PERL in order
to log and count SMTP requests to their account, now I can, thanks to
help given here. I think by Thursday I will have a test version of  it
up and running.

So far with just sasl != user;
................
$client_address="";
$client_name="";
$reverse_client_name="";
$helo_name="";
$sender="";
$recipient="";
$recipient_count="";
$sasl_username="\n";

$c=0;
while  ($c==0) {
$b=(<STDIN>);
  $a.=$b;
  if ($b =~ /=/) {
        my ($key, $value) =split (/=/, $b, 2);
        if ($key eq "client_address") { $client_address=$value;}
        if ($key eq "client_name") { $client_name=$value;}
        if ($key eq "reverse_client_name") { $reverse_client_name=$value;}
        if ($key eq "helo_name") { $helo_name=$value;}
        if ($key eq "sender") { $sender=$value;}
        if ($key eq "recipient") { $recipient=$value;}
        if ($key eq "recipient_count") { $recipient_count=$value;}
        if ($key eq "sasl_username") { $sasl_username=$value;}  
    }

  if($b eq "\n") { $c=1;}
}
$action="action=DUNNO\n\n";
if($sasl_username ne "\n") {
   if ($sasl_username ne $sender) {
   $action= "action=REJECT Wrong sender\n\n";
   }
}
print $action;
.......



Thanks for your suggestion,


Mick.

Benning, Markus wrote:

> Am 2015-02-27 14:45, schrieb MickTW8:
>> This issue I have is knowing how to read any of the attributes listed
>> here
>> www.postfix.org/SMTPD_POLICY_README.html#protocol
>
> Hello Mick,
>
> it may be an option for your to implement your code as a plugin for
> mtpolicyd.
> There's documentation for wrinting a simple plugin at:
>
> https://www.mtpolicyd.org/getting-started.html#Mail::MtPolicyd::Cookbook::BasicModule 
>
>
> Then you wont have to care about accepting connections, parsing,
> logging and so on.
>
> Another option may be to just copy over the Request class to your
> project and remove
> dependencies on Net::Server, etc. from it:
>
> https://github.com/benningm/mtpolicyd/blob/master/lib/Mail/MtPolicyd/Request.pm 
>
>
>  Markus
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

Markus Benning
Am 2015-03-01 12:38, schrieb Mick:

> Hello Markus,
>
> Thanks very much for your reply.  I didn't come across Cookbook in my
> searches but I don't think I will need it now as I'm very pleased to
> report I got my first test policy implemented yesterday evening. Don't
> laugh, all it does so far is block senders where 'sender' doesn't
> match 'sasl-user'. Everyone has to start somewhere right? It does put
> me in a place where I can write customised policies now.  I was
> thinking of using mysql but everyone seems to use Berkeley DB? Maybe
> worth considering as it has a locking arrangement.
>
> One of my user email accounts was compromised a couple of months ago
> and over a period of 5 hours thousands of SPAM messages were sent.
> Grrrr! Since then I have become rather paranoid checking the mail log
> whenever I can looking for "Relay=' and auth failures manually barring
> IPs that repeatedly fail to log in.  I need to relax a bit so decided
> to try and write a SPAM limitation policy, as in ;
>
> if (X number of messages sent in Y  time), {
>  external relay access blocked until user resets password
> }.
>
> To do this I needed to read  the SASL_USERNAME field into PERL in
> order to log and count SMTP requests to their account, now I can,
> thanks to help given here. I think by Thursday I will have a test
> version of  it up and running.

The reject_sender_login_mismatch in smtpd_sender_restriction already
does that
as a native postfix check:

http://www.postfix.org/postconf.5.html#smtpd_sender_restrictions

The Accounting/Quota module in mtpolicyd can be used to count/limit
mails
per sasl user in a SQL database supported by perl-DBI (SQLite, MySQL,
etc.):

https://www.mtpolicyd.org/getting-started.html#Mail::MtPolicyd::Cookbook::HowtoAccountingQuota


Markus

--
Markus Benning, https://markusbenning.de/
Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

MickTW8
Hi Markus,

I am pleased to say my 'moonshine' perl based policy is now up and running.


Benning, Markus wrote:
> The reject_sender_login_mismatch in smtpd_sender_restriction already
> does that
> as a native postfix check:
I didn't know that. There is a lot I don't know or understand, which is
why I decided to try to come up with something myself. Regarding
blocking sender login mismatch, I will keep that in the policy. I added
an extra field to the policy mysql DB table enabling mailboxes to be
group linked by an administrator. This means that an SMTP login within a
specific group, can send messages on behalf of anyone else provided that
has the same group code.  A very simple addition where both the sender
and sasl-username are cross checked with the group name (if any).

$action= "action=DUNNO\n\n";
if ($sasl_username ne $sender)
  {
     if(length($sasllink)>0 && length($senderlink)>0 && $sasllink eq
$senderlink) {}
     else { $action= "action=REJECT Not authorised\n\n";}
  }
}
I guess I can skip one of the two lengths being greater than 0 as if one
is and one isn't, they wouldn't be equal anyway. Only just noticed that.
Ho humm.


>
> http://www.postfix.org/postconf.5.html#smtpd_sender_restrictions
>
> The Accounting/Quota module in mtpolicyd can be used to count/limit mails
> per sasl user in a SQL database supported by perl-DBI (SQLite, MySQL,
> etc.):
>
> https://www.mtpolicyd.org/getting-started.html#Mail::MtPolicyd::Cookbook::HowtoAccountingQuota 
>
I had a look at your site. Cookbook looks highly customisable. Had you
sold that to me two weeks ago, I'd have bitten you right arm off to try
it out. Right now, I have everything I need ... I think?, and really
want to go down my own avenue.  I have bookmarked your website for
future investigation though, thanks for the link. I did try to download
polidyd from the Debian resource, but all I got was upgrade text file so
gave up.


My idea of a quota policy differs in that it is not intended to restrict
traffic from genuine users, I want it solely to mitigate against
compromised accounts. On a average user account, say if 20 messages are
sent within a minute, relay access will be blocked. The  
'recipient_count' adds to the total so that could catch people out if
sending to multiple to/cc/bcc., that is why it is all end users can
change values via a php web portal. The option to block or unblock is
there too.

In the pipeline: I will add to the php script to ensure the mail
password can't be the same as the portal password, and the maximum quota
reduces or increases depending on mail and portal password strength.
There are currently 3 sets of message (counter) per (seconds) variables,
each resetting their count after the timeout.

Why would I want to manually block my own account? Well, I for one have
various email accounts. Mailing lists, mates & friends, trusted
business, untrusted business. With the group link, all I need is one
account that is SMTP active to be able to send mail from any of these.
If other accounts are blocked by default, it cuts down the risk of a
compromised pop3 becoming open SMTP. Yeah, I know it won't catch on ;-)



Thanks again,

Mick.




Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

Paul Hoffman
On Fri, Mar 06, 2015 at 01:54:54AM +0000, Mick wrote:

> Hi Markus,
>
> I am pleased to say my 'moonshine' perl based policy is now up and running.
>
>
> Benning, Markus wrote:
> >The reject_sender_login_mismatch in smtpd_sender_restriction
> >already does that
> >as a native postfix check:
> I didn't know that. There is a lot I don't know or understand, which
> is why I decided to try to come up with something myself. Regarding
> blocking sender login mismatch, I will keep that in the policy. I
> added an extra field to the policy mysql DB table enabling mailboxes
> to be group linked by an administrator. This means that an SMTP
> login within a specific group, can send messages on behalf of anyone
> else provided that has the same group code.  A very simple addition
> where both the sender and sasl-username are cross checked with the
> group name (if any).
>
> $action= "action=DUNNO\n\n";
> if ($sasl_username ne $sender)
>  {
>     if(length($sasllink)>0 && length($senderlink)>0 && $sasllink eq
> $senderlink) {}
>     else { $action= "action=REJECT Not authorised\n\n";}
>  }
> }

Suggestion:

    $action =
        $sasl_username eq $sender || (length($sasllink) && $sasllink eq $senderlink)
            ? "action=DUNNO\n\n";
            : "action=REJECT Not authorised\n\n"

Paul.

--
Paul Hoffman <[hidden email]>
Systems Librarian
Fenway Libraries Online
c/o Wentworth Institute of Technology
550 Huntington Ave.
Boston, MA 02115
(617) 442-2384 (FLO main number)
Reply | Threaded
Open this post in threaded view
|

Re: Policy attributes to PERL script

MickTW8
Paul Hoffman wrote:

>> $action= "action=DUNNO\n\n";
>> if ($sasl_username ne $sender)
>>  {
>>     if(length($sasllink)>0 && length($senderlink)>0 && $sasllink eq
>> $senderlink) {}
>>     else { $action= "action=REJECT Not authorised\n\n";}
>>  }
>> }
>>    
>
> Suggestion:
>
>     $action =
>         $sasl_username eq $sender || (length($sasllink) && $sasllink eq $senderlink)
>             ? "action=DUNNO\n\n";
>             : "action=REJECT Not authorised\n\n"
>
> Paul.
>
>  
Hi Paul,

I like your suggestion. I didn't realise you could format a TRUE / FALSE
statement like that so I have replaced that particular part of the
script with yours so I have something to refer to later. It was a bit a
bit misleading of me stating $action is declared where it is shown to
be, as it goes through the quota and already blocked sections first
where it can be changed to reject. I have adjusted your suggested script
to keep original $action value if TRUE is returned.
I guess this is sloppy programming on my part. As soon as a rejection is
spotted, I suppose I could just add;

print"action=REJECT reason being..";
exit(0);

.. and end the program.

Here is how that part of the script looks now ;

if($sasl_username ne "\n")
{
  $action = $sasl_username eq $sender || (length($sasllink) && $sasllink
eq $senderlink)
            ? "$action"
            : "action=REJECT Not authorised\n\n";
}

Much neater than my burn offerings. Thanks again. The' if($sasl_username
ne "\n") ' is still needed as non SASL authenticated incoming mail would
be rejected otherwise.

Cheers,

Mick.