Merge tag 'upstream/1.35'
Upstream version 1.35
This commit is contained in:
		
						commit
						cf9402a5ac
					
				
					 11 changed files with 1565 additions and 1684 deletions
				
			
		| 
						 | 
					@ -1,3 +1,41 @@
 | 
				
			||||||
 | 
					1.35
 | 
				
			||||||
 | 
					====
 | 
				
			||||||
 | 
					- code:    rate(), size() and rcpt() function index is now case insensitive by default
 | 
				
			||||||
 | 
						   (same limit counters for from@example.org and fRom@eXample.org)
 | 
				
			||||||
 | 
					           if you need to treat the localpart case-sensitive according to rfc5321
 | 
				
			||||||
 | 
						   you may use rate5321(), size5321() and rcpt5321()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1.34
 | 
				
			||||||
 | 
					====
 | 
				
			||||||
 | 
					- bugfix:  fixed taint mode logging error for verbose --showconfig and --stdoutlog
 | 
				
			||||||
 | 
						   options and newer perl versions.
 | 
				
			||||||
 | 
					- bugfix:  check_* functions use print/getline instead of send/recv for large 
 | 
				
			||||||
 | 
						   --dumpcache output (thanks to Alexandre Simon)
 | 
				
			||||||
 | 
					- code:    log_* routines added to allow the same plugins for postfwd1 and postfwd2
 | 
				
			||||||
 | 
					- code:    added more information when using --debug=cleanup
 | 
				
			||||||
 | 
					- docs:    documentation updates
 | 
				
			||||||
 | 
					- feature: new sendmail(sendmail-path::from::to::subject::body) action.
 | 
				
			||||||
 | 
					           Please take a look at the manual, especially about
 | 
				
			||||||
 | 
					           it's limitations, before using it!
 | 
				
			||||||
 | 
					    ------------------------------------------------------------
 | 
				
			||||||
 | 
					     # alert
 | 
				
			||||||
 | 
					     action=sendmail(/usr/sbin/sendmail::from@example.org::to@example.org::Subject::Text)
 | 
				
			||||||
 | 
					    ------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1.33
 | 
				
			||||||
 | 
					====
 | 
				
			||||||
 | 
					- feature: new compare operators *
 | 
				
			||||||
 | 
					        ====================================================================
 | 
				
			||||||
 | 
					         *ITEM > VALUE                true if ITEM > VALUE
 | 
				
			||||||
 | 
					         *ITEM < VALUE                true if ITEM < VALUE
 | 
				
			||||||
 | 
					        ====================================================================
 | 
				
			||||||
 | 
					- bugfix:  fixed bug when computing scores with more than 1 digit after the "." (n.nn)
 | 
				
			||||||
 | 
					- bugfix:  fixed bug when computing negative values with the set action
 | 
				
			||||||
 | 
					- bugfix:  ITEMS plugins returning zero values were handled incorrectly
 | 
				
			||||||
 | 
					- bugfix:  max command recursion was not reset for each rule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.32
 | 
					1.32
 | 
				
			||||||
====
 | 
					====
 | 
				
			||||||
- feature: new option --save_rates=<file> allows to load and save
 | 
					- feature: new option --save_rates=<file> allows to load and save
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,18 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" ?>
 | 
				
			||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
					<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
				
			||||||
<html xmlns="http://www.w3.org/1999/xhtml">
 | 
					<html xmlns="http://www.w3.org/1999/xhtml">
 | 
				
			||||||
<head>
 | 
					<head>
 | 
				
			||||||
<title>postfwd - postfix firewall daemon</title>
 | 
					<title>postfwd - postfix firewall daemon</title>
 | 
				
			||||||
 | 
					<meta http-equiv="content-type" content="text/html; charset=utf-8" />
 | 
				
			||||||
<link rev="made" href="mailto:root@localhost" />
 | 
					<link rev="made" href="mailto:root@localhost" />
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<body style="background-color: white">
 | 
					<body style="background-color: white">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<p><a name="__index__"></a></p>
 | 
					
 | 
				
			||||||
<!-- INDEX BEGIN -->
 | 
					<!-- INDEX BEGIN -->
 | 
				
			||||||
 | 
					<div name="index">
 | 
				
			||||||
 | 
					<p><a name="__index__"></a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<ul>
 | 
					<ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,9 +41,11 @@
 | 
				
			||||||
	<li><a href="#license">LICENSE</a></li>
 | 
						<li><a href="#license">LICENSE</a></li>
 | 
				
			||||||
	<li><a href="#author">AUTHOR</a></li>
 | 
						<li><a href="#author">AUTHOR</a></li>
 | 
				
			||||||
</ul>
 | 
					</ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<hr name="index" />
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
<!-- INDEX END -->
 | 
					<!-- INDEX END -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<hr />
 | 
					 | 
				
			||||||
<p>
 | 
					<p>
 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
<h1><a name="name">NAME</a></h1>
 | 
					<h1><a name="name">NAME</a></h1>
 | 
				
			||||||
| 
						 | 
					@ -111,7 +117,8 @@
 | 
				
			||||||
            --config_timeout <i>     parser timeout in seconds
 | 
					            --config_timeout <i>     parser timeout in seconds
 | 
				
			||||||
            --keep_rates             do not clear rate limit counters on reload
 | 
					            --keep_rates             do not clear rate limit counters on reload
 | 
				
			||||||
            --save_rates <file>      save and load rate limits on disk
 | 
					            --save_rates <file>      save and load rate limits on disk
 | 
				
			||||||
            --fast_limit_evaluation  evaluate rate limits before ruleset is parsed</pre>
 | 
					            --fast_limit_evaluation  evaluate rate limits before ruleset is parsed
 | 
				
			||||||
 | 
					                                     (please note the limitations)</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        Plugins:
 | 
					        Plugins:
 | 
				
			||||||
            --plugins <file>        loads postfwd plugins from file</pre>
 | 
					            --plugins <file>        loads postfwd plugins from file</pre>
 | 
				
			||||||
| 
						 | 
					@ -165,6 +172,8 @@ is not important. So the following would lead to the same result as the previous
 | 
				
			||||||
         ITEM == VALUE                true if ITEM equals VALUE
 | 
					         ITEM == VALUE                true if ITEM equals VALUE
 | 
				
			||||||
         ITEM => VALUE                true if ITEM >= VALUE
 | 
					         ITEM => VALUE                true if ITEM >= VALUE
 | 
				
			||||||
         ITEM =< VALUE                true if ITEM <= VALUE
 | 
					         ITEM =< VALUE                true if ITEM <= VALUE
 | 
				
			||||||
 | 
					         ITEM >  VALUE                true if ITEM >  VALUE
 | 
				
			||||||
 | 
					         ITEM <  VALUE                true if ITEM <  VALUE
 | 
				
			||||||
         ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
					         ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
				
			||||||
         ITEM != VALUE                false if ITEM equals VALUE
 | 
					         ITEM != VALUE                false if ITEM equals VALUE
 | 
				
			||||||
         ITEM !> VALUE                false if ITEM >= VALUE
 | 
					         ITEM !> VALUE                false if ITEM >= VALUE
 | 
				
			||||||
| 
						 | 
					@ -442,7 +451,7 @@ necessary. Of course this might increase the system load, so please use it with
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        -- FILE /etc/postfwd/clients_west.cf --
 | 
					        -- FILE /etc/postfwd/clients_west.cf --
 | 
				
			||||||
        192.168.3.0/24</pre>
 | 
					        192.168.3.0/24</pre>
 | 
				
			||||||
<p>Remind that there is currently no loop detection (/a/file calls /a/file) and that this feature is only available
 | 
					<p>Note that there is currently no loop detection (/a/file calls /a/file) and that this feature is only available
 | 
				
			||||||
with postfwd1 v1.15 and postfwd2 v0.18 and higher.</p>
 | 
					with postfwd1 v1.15 and postfwd2 v0.18 and higher.</p>
 | 
				
			||||||
<p>
 | 
					<p>
 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
| 
						 | 
					@ -456,7 +465,7 @@ request attributes by preceeding $$ characters, like:</p>
 | 
				
			||||||
        id=R-003; client_name = !!$$helo_name; action=WARN helo '$$(helo_name)' does not match DNS '$$(client_name)'</pre>
 | 
					        id=R-003; client_name = !!$$helo_name; action=WARN helo '$$(helo_name)' does not match DNS '$$(client_name)'</pre>
 | 
				
			||||||
<p><em>postfix actions</em></p>
 | 
					<p><em>postfix actions</em></p>
 | 
				
			||||||
<p>Actions will be replied to postfix as result to policy delegation requests. Any action that postfix understands is allowed - see
 | 
					<p>Actions will be replied to postfix as result to policy delegation requests. Any action that postfix understands is allowed - see
 | 
				
			||||||
``man 5 access'' or <a href="http://www.postfix.org/access.5.html">http://www.postfix.org/access.5.html</a> for a description. If no action is specified, the postfix WARN action
 | 
					"man 5 access" or <a href="http://www.postfix.org/access.5.html">http://www.postfix.org/access.5.html</a> for a description. If no action is specified, the postfix WARN action
 | 
				
			||||||
which simply logs the event will be used for the corresponding rule.</p>
 | 
					which simply logs the event will be used for the corresponding rule.</p>
 | 
				
			||||||
<p>postfwd will return dunno if it has reached the end of the ruleset and no rule has matched. This can be changed by placing a last
 | 
					<p>postfwd will return dunno if it has reached the end of the ruleset and no rule has matched. This can be changed by placing a last
 | 
				
			||||||
rule containing only an action statement:</p>
 | 
					rule containing only an action statement:</p>
 | 
				
			||||||
| 
						 | 
					@ -494,7 +503,7 @@ rule containing only an action statement:</p>
 | 
				
			||||||
        this command creates a counter for the given <item>, which will be increased any time a request
 | 
					        this command creates a counter for the given <item>, which will be increased any time a request
 | 
				
			||||||
        containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
					        containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
				
			||||||
        rate counters are very fast as they are executed before the ruleset is parsed.
 | 
					        rate counters are very fast as they are executed before the ruleset is parsed.
 | 
				
			||||||
        please note that <action> is currently limited to postfix actions (no postfwd actions)!
 | 
					        please note that <action> was limited to postfix actions (no postfwd actions) for postfwd versions <1.33!
 | 
				
			||||||
            # no more than 3 requests per 5 minutes
 | 
					            # no more than 3 requests per 5 minutes
 | 
				
			||||||
            # from the same "unknown" client
 | 
					            # from the same "unknown" client
 | 
				
			||||||
            id=RATE01 ;  client_name==unknown
 | 
					            id=RATE01 ;  client_name==unknown
 | 
				
			||||||
| 
						 | 
					@ -525,6 +534,11 @@ rule containing only an action statement:</p>
 | 
				
			||||||
           # recipient count limit 3 per hour per client
 | 
					           # recipient count limit 3 per hour per client
 | 
				
			||||||
           id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address!=10.1.1.1
 | 
					           id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address!=10.1.1.1
 | 
				
			||||||
              action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)</pre>
 | 
					              action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)</pre>
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					        rate5321,size5321,rcpt5321 (<item>/<max>/<time>/<action>)
 | 
				
			||||||
 | 
					        same as the corresponding non-5321 functions, with the difference that the localpart of
 | 
				
			||||||
 | 
					        sender oder recipient addresses are evaluated case-sensitive according to rfc5321. That
 | 
				
			||||||
 | 
					        means that requests from bob@example.local and BoB@example.local will be treated differently</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        ask (<addr>:<port>[:<ignore>])
 | 
					        ask (<addr>:<port>[:<ignore>])
 | 
				
			||||||
        allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
					        allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
				
			||||||
| 
						 | 
					@ -537,9 +551,15 @@ rule containing only an action statement:</p>
 | 
				
			||||||
           id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)</pre>
 | 
					           id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        mail(server/helo/from/to/subject/body)
 | 
					        mail(server/helo/from/to/subject/body)
 | 
				
			||||||
 | 
					        This command is deprecated. You should try to use the sendmail() action instead.
 | 
				
			||||||
        Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
					        Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
				
			||||||
        This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
					        This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
				
			||||||
        not track notification state and will notify you any time, the corresponding rule hits.</pre>
 | 
					        not track notification state and will notify you any time, the corresponding rule hits.</pre>
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					        sendmail(sendmail-path::from::to::subject::body)
 | 
				
			||||||
 | 
					        Mail command, that uses an existing sendmail binary and sends a message with the given arguments.
 | 
				
			||||||
 | 
					        LIMITATIONS: The command does not track notification state and will notify you any time, the
 | 
				
			||||||
 | 
					        corresponding rule hits (which could mean 100 mails for a mail with 100 recipients at RCPT stage).</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        wait (<delay>)
 | 
					        wait (<delay>)
 | 
				
			||||||
        pauses the program execution for <delay> seconds. use this for
 | 
					        pauses the program execution for <delay> seconds. use this for
 | 
				
			||||||
| 
						 | 
					@ -680,6 +700,10 @@ will be used.</p>
 | 
				
			||||||
                                        $myresult = ($myitem <= $val);
 | 
					                                        $myresult = ($myitem <= $val);
 | 
				
			||||||
                                } elsif ($cmp eq '=>') {
 | 
					                                } elsif ($cmp eq '=>') {
 | 
				
			||||||
                                        $myresult = ($myitem >= $val);
 | 
					                                        $myresult = ($myitem >= $val);
 | 
				
			||||||
 | 
					                                } elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
					                                        $myresult = ($myitem < $val);
 | 
				
			||||||
 | 
					                                } elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
					                                        $myresult = ($myitem > $val);
 | 
				
			||||||
                                } elsif ($cmp eq '!=') {
 | 
					                                } elsif ($cmp eq '!=') {
 | 
				
			||||||
                                        $myresult = not($myitem == $val);
 | 
					                                        $myresult = not($myitem == $val);
 | 
				
			||||||
                                } elsif ($cmp eq '!<') {
 | 
					                                } elsif ($cmp eq '!<') {
 | 
				
			||||||
| 
						 | 
					@ -709,15 +733,15 @@ continue or to stop parsing the ruleset.</p>
 | 
				
			||||||
                        # note(<logstring>) command
 | 
					                        # note(<logstring>) command
 | 
				
			||||||
                        "note"  => sub {
 | 
					                        "note"  => sub {
 | 
				
			||||||
                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                my($myaction) = $default_action; my($stop) = 0;
 | 
					                                my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
					                                log_info "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
				
			||||||
                                return ($stop,$index,$myaction,$myline,%request);
 | 
					                                return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                        # skips next <myarg> rules
 | 
					                        # skips next <myarg> rules
 | 
				
			||||||
                        "skip" => sub {
 | 
					                        "skip" => sub {
 | 
				
			||||||
                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                my($myaction) = $default_action; my($stop) = 0;
 | 
					                                my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
					                                $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
				
			||||||
                                return ($stop,$index,$myaction,$myline,%request);
 | 
					                                return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
| 
						 | 
					@ -725,8 +749,8 @@ continue or to stop parsing the ruleset.</p>
 | 
				
			||||||
                        # dumps current request contents to syslog
 | 
					                        # dumps current request contents to syslog
 | 
				
			||||||
                        "dumprequest" => sub {
 | 
					                        "dumprequest" => sub {
 | 
				
			||||||
                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                my($myaction) = $default_action; my($stop) = 0;
 | 
					                                my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
					                                map { log_info "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
				
			||||||
                                return ($stop,$index,$myaction,$myline,%request);
 | 
					                                return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                        },</pre>
 | 
					                        },</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
| 
						 | 
					@ -979,7 +1003,10 @@ The following arguments will control it's behaviour in this case.</p>
 | 
				
			||||||
        Once a ratelimit was set by the ruleset, future requests will be evaluated against it
 | 
					        Once a ratelimit was set by the ruleset, future requests will be evaluated against it
 | 
				
			||||||
        before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
					        before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
				
			||||||
        With this mode rate limits will be faster, but also eventually set up
 | 
					        With this mode rate limits will be faster, but also eventually set up
 | 
				
			||||||
        whitelisting-rules within the ruleset might not work as expected.</pre>
 | 
					        whitelisting-rules within the ruleset might not work as expected.
 | 
				
			||||||
 | 
					        LIMITATIONS: This option does not allow nested postfwd commands like
 | 
				
			||||||
 | 
					                action=rate(sender/3/60/wait(3))
 | 
				
			||||||
 | 
					        This option doe not work with the strict-rfc5321 rate() functions.</pre>
 | 
				
			||||||
<p><em>Informational arguments</em></p>
 | 
					<p><em>Informational arguments</em></p>
 | 
				
			||||||
<p>These arguments are for command line usage only. Never ever use them with postfix spawn!</p>
 | 
					<p>These arguments are for command line usage only. Never ever use them with postfix spawn!</p>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
| 
						 | 
					@ -1193,7 +1220,7 @@ check the parser with the -C | --showconfig switch at the command line before ap
 | 
				
			||||||
        Rule   0: id->"RBL001"; action->"REJECT listed on spamcop and bad rdns"; rbl->"bl.spamcop.net"; client_name->"^unknown$"</pre>
 | 
					        Rule   0: id->"RBL001"; action->"REJECT listed on spamcop and bad rdns"; rbl->"bl.spamcop.net"; client_name->"^unknown$"</pre>
 | 
				
			||||||
<p><em>Request processing</em></p>
 | 
					<p><em>Request processing</em></p>
 | 
				
			||||||
<p>When a policy delegation request arrives it will be compared against postfwd`s ruleset. To inspect the processing in detail you should increase
 | 
					<p>When a policy delegation request arrives it will be compared against postfwd`s ruleset. To inspect the processing in detail you should increase
 | 
				
			||||||
verbority using use the ``-v'' or ``-vv'' switch. ``-L'' redirects log messages to stdout.</p>
 | 
					verbority using use the "-v" or "-vv" switch. "-L" redirects log messages to stdout.</p>
 | 
				
			||||||
<p>Keeping the order of the ruleset in general, items will be compared in random order, which basically means that</p>
 | 
					<p>Keeping the order of the ruleset in general, items will be compared in random order, which basically means that</p>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        id=R001; action=dunno; client_address=192.168.1.1; sender=bob@alice.local</pre>
 | 
					        id=R001; action=dunno; client_address=192.168.1.1; sender=bob@alice.local</pre>
 | 
				
			||||||
| 
						 | 
					@ -1232,7 +1259,7 @@ to compare against the request attribute the parser will jump to the next rule i
 | 
				
			||||||
<p>If a rule matches, there are two options:</p>
 | 
					<p>If a rule matches, there are two options:</p>
 | 
				
			||||||
<p>* Rule returns postfix action (dunno, reject, ...)
 | 
					<p>* Rule returns postfix action (dunno, reject, ...)
 | 
				
			||||||
The parser stops rule processing and returns the action to postfix. Other rules will not be evaluated.</p>
 | 
					The parser stops rule processing and returns the action to postfix. Other rules will not be evaluated.</p>
 | 
				
			||||||
<p>* Rule returns postfwd action (jump(), note(), ...)
 | 
					<p>* Rule returns postfwd action (jump(), <code>note()</code>, ...)
 | 
				
			||||||
The parser evaluates the given action and continues with the next rule (except for the <code>jump()</code> or <code>quit()</code> actions - please see the <a href="#actions">ACTIONS</a> section
 | 
					The parser evaluates the given action and continues with the next rule (except for the <code>jump()</code> or <code>quit()</code> actions - please see the <a href="#actions">ACTIONS</a> section
 | 
				
			||||||
for more information). Nothing will be sent to postfix.</p>
 | 
					for more information). Nothing will be sent to postfix.</p>
 | 
				
			||||||
<p>If no rule has matched and the end of the ruleset is reached postfwd will return dunno without logging anything unless in verbose mode. You may
 | 
					<p>If no rule has matched and the end of the ruleset is reached postfwd will return dunno without logging anything unless in verbose mode. You may
 | 
				
			||||||
| 
						 | 
					@ -1252,7 +1279,7 @@ it`s internal caching in that case. Start postfwd with the following parameters:
 | 
				
			||||||
        postfwd -d -f /etc/postfwd.cf -i 127.0.0.1 -p 10040 -u nobody -g nobody -S</pre>
 | 
					        postfwd -d -f /etc/postfwd.cf -i 127.0.0.1 -p 10040 -u nobody -g nobody -S</pre>
 | 
				
			||||||
<p>For efficient caching you should check if you can use the options --cache-rdomain-only, --cache-no-sender
 | 
					<p>For efficient caching you should check if you can use the options --cache-rdomain-only, --cache-no-sender
 | 
				
			||||||
and --cache-no-size.</p>
 | 
					and --cache-no-size.</p>
 | 
				
			||||||
<p>Now check your syslogs (default facility ``mail'') for a line like:</p>
 | 
					<p>Now check your syslogs (default facility "mail") for a line like:</p>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        Aug  9 23:00:24 mail postfwd[5158]: postfwd n.nn ready for input</pre>
 | 
					        Aug  9 23:00:24 mail postfwd[5158]: postfwd n.nn ready for input</pre>
 | 
				
			||||||
<p>and use `netstat -an|grep 10040` to check for something like</p>
 | 
					<p>and use `netstat -an|grep 10040` to check for something like</p>
 | 
				
			||||||
| 
						 | 
					@ -1307,7 +1334,7 @@ I won`t discuss that here. If you plan to do so, just add the following line to
 | 
				
			||||||
                disable         = no
 | 
					                disable         = no
 | 
				
			||||||
        }</pre>
 | 
					        }</pre>
 | 
				
			||||||
<p>and restart the xinetd daemon (usually a SIGHUP should be fine). If you experience problems
 | 
					<p>and restart the xinetd daemon (usually a SIGHUP should be fine). If you experience problems
 | 
				
			||||||
you might want to check your system's log for xinetd errors like ``socket already in use''.</p>
 | 
					you might want to check your system's log for xinetd errors like "socket already in use".</p>
 | 
				
			||||||
<p>The integration with postfix is similar to the <em>Integration via daemon mode</em> section above.
 | 
					<p>The integration with postfix is similar to the <em>Integration via daemon mode</em> section above.
 | 
				
			||||||
Reload postfix and watch your logs to see if everything works.</p>
 | 
					Reload postfix and watch your logs to see if everything works.</p>
 | 
				
			||||||
<p>
 | 
					<p>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,7 @@ SYNOPSIS
 | 
				
			||||||
                --keep_rates             do not clear rate limit counters on reload
 | 
					                --keep_rates             do not clear rate limit counters on reload
 | 
				
			||||||
                --save_rates <file>      save and load rate limits on disk
 | 
					                --save_rates <file>      save and load rate limits on disk
 | 
				
			||||||
                --fast_limit_evaluation  evaluate rate limits before ruleset is parsed
 | 
					                --fast_limit_evaluation  evaluate rate limits before ruleset is parsed
 | 
				
			||||||
 | 
					                                         (please note the limitations)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Plugins:
 | 
					            Plugins:
 | 
				
			||||||
                --plugins <file>        loads postfwd plugins from file
 | 
					                --plugins <file>        loads postfwd plugins from file
 | 
				
			||||||
| 
						 | 
					@ -133,6 +134,8 @@ DESCRIPTION
 | 
				
			||||||
             ITEM == VALUE                true if ITEM equals VALUE
 | 
					             ITEM == VALUE                true if ITEM equals VALUE
 | 
				
			||||||
             ITEM => VALUE                true if ITEM >= VALUE
 | 
					             ITEM => VALUE                true if ITEM >= VALUE
 | 
				
			||||||
             ITEM =< VALUE                true if ITEM <= VALUE
 | 
					             ITEM =< VALUE                true if ITEM <= VALUE
 | 
				
			||||||
 | 
					             ITEM >  VALUE                true if ITEM >  VALUE
 | 
				
			||||||
 | 
					             ITEM <  VALUE                true if ITEM <  VALUE
 | 
				
			||||||
             ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
					             ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
				
			||||||
             ITEM != VALUE                false if ITEM equals VALUE
 | 
					             ITEM != VALUE                false if ITEM equals VALUE
 | 
				
			||||||
             ITEM !> VALUE                false if ITEM >= VALUE
 | 
					             ITEM !> VALUE                false if ITEM >= VALUE
 | 
				
			||||||
| 
						 | 
					@ -457,7 +460,7 @@ DESCRIPTION
 | 
				
			||||||
            -- FILE /etc/postfwd/clients_west.cf --
 | 
					            -- FILE /etc/postfwd/clients_west.cf --
 | 
				
			||||||
            192.168.3.0/24
 | 
					            192.168.3.0/24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Remind that there is currently no loop detection (/a/file calls /a/file)
 | 
					    Note that there is currently no loop detection (/a/file calls /a/file)
 | 
				
			||||||
    and that this feature is only available with postfwd1 v1.15 and postfwd2
 | 
					    and that this feature is only available with postfwd1 v1.15 and postfwd2
 | 
				
			||||||
    v0.18 and higher.
 | 
					    v0.18 and higher.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -520,7 +523,7 @@ DESCRIPTION
 | 
				
			||||||
            this command creates a counter for the given <item>, which will be increased any time a request
 | 
					            this command creates a counter for the given <item>, which will be increased any time a request
 | 
				
			||||||
            containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
					            containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
				
			||||||
            rate counters are very fast as they are executed before the ruleset is parsed.
 | 
					            rate counters are very fast as they are executed before the ruleset is parsed.
 | 
				
			||||||
            please note that <action> is currently limited to postfix actions (no postfwd actions)!
 | 
					            please note that <action> was limited to postfix actions (no postfwd actions) for postfwd versions <1.33!
 | 
				
			||||||
                # no more than 3 requests per 5 minutes
 | 
					                # no more than 3 requests per 5 minutes
 | 
				
			||||||
                # from the same "unknown" client
 | 
					                # from the same "unknown" client
 | 
				
			||||||
                id=RATE01 ;  client_name==unknown
 | 
					                id=RATE01 ;  client_name==unknown
 | 
				
			||||||
| 
						 | 
					@ -552,6 +555,11 @@ DESCRIPTION
 | 
				
			||||||
               id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address!=10.1.1.1
 | 
					               id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address!=10.1.1.1
 | 
				
			||||||
                  action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)
 | 
					                  action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            rate5321,size5321,rcpt5321 (<item>/<max>/<time>/<action>)
 | 
				
			||||||
 | 
					            same as the corresponding non-5321 functions, with the difference that the localpart of
 | 
				
			||||||
 | 
					            sender oder recipient addresses are evaluated case-sensitive according to rfc5321. That
 | 
				
			||||||
 | 
					            means that requests from bob@example.local and BoB@example.local will be treated differently
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ask (<addr>:<port>[:<ignore>])
 | 
					            ask (<addr>:<port>[:<ignore>])
 | 
				
			||||||
            allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
					            allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
				
			||||||
            and the second argument (address and port) are mandatory. a third optional argument may be
 | 
					            and the second argument (address and port) are mandatory. a third optional argument may be
 | 
				
			||||||
| 
						 | 
					@ -563,10 +571,16 @@ DESCRIPTION
 | 
				
			||||||
               id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)
 | 
					               id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            mail(server/helo/from/to/subject/body)
 | 
					            mail(server/helo/from/to/subject/body)
 | 
				
			||||||
 | 
					            This command is deprecated. You should try to use the sendmail() action instead.
 | 
				
			||||||
            Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
					            Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
				
			||||||
            This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
					            This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
				
			||||||
            not track notification state and will notify you any time, the corresponding rule hits.
 | 
					            not track notification state and will notify you any time, the corresponding rule hits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            sendmail(sendmail-path::from::to::subject::body)
 | 
				
			||||||
 | 
					            Mail command, that uses an existing sendmail binary and sends a message with the given arguments.
 | 
				
			||||||
 | 
					            LIMITATIONS: The command does not track notification state and will notify you any time, the
 | 
				
			||||||
 | 
					            corresponding rule hits (which could mean 100 mails for a mail with 100 recipients at RCPT stage).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            wait (<delay>)
 | 
					            wait (<delay>)
 | 
				
			||||||
            pauses the program execution for <delay> seconds. use this for
 | 
					            pauses the program execution for <delay> seconds. use this for
 | 
				
			||||||
            delaying or throtteling connections.
 | 
					            delaying or throtteling connections.
 | 
				
			||||||
| 
						 | 
					@ -724,6 +738,10 @@ DESCRIPTION
 | 
				
			||||||
                                            $myresult = ($myitem <= $val);
 | 
					                                            $myresult = ($myitem <= $val);
 | 
				
			||||||
                                    } elsif ($cmp eq '=>') {
 | 
					                                    } elsif ($cmp eq '=>') {
 | 
				
			||||||
                                            $myresult = ($myitem >= $val);
 | 
					                                            $myresult = ($myitem >= $val);
 | 
				
			||||||
 | 
					                                    } elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
					                                            $myresult = ($myitem < $val);
 | 
				
			||||||
 | 
					                                    } elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
					                                            $myresult = ($myitem > $val);
 | 
				
			||||||
                                    } elsif ($cmp eq '!=') {
 | 
					                                    } elsif ($cmp eq '!=') {
 | 
				
			||||||
                                            $myresult = not($myitem == $val);
 | 
					                                            $myresult = not($myitem == $val);
 | 
				
			||||||
                                    } elsif ($cmp eq '!<') {
 | 
					                                    } elsif ($cmp eq '!<') {
 | 
				
			||||||
| 
						 | 
					@ -755,15 +773,15 @@ DESCRIPTION
 | 
				
			||||||
                            # note(<logstring>) command
 | 
					                            # note(<logstring>) command
 | 
				
			||||||
                            "note"  => sub {
 | 
					                            "note"  => sub {
 | 
				
			||||||
                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                    my($myaction) = $default_action; my($stop) = 0;
 | 
					                                    my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                    mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
					                                    log_info "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
				
			||||||
                                    return ($stop,$index,$myaction,$myline,%request);
 | 
					                                    return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                            # skips next <myarg> rules
 | 
					                            # skips next <myarg> rules
 | 
				
			||||||
                            "skip" => sub {
 | 
					                            "skip" => sub {
 | 
				
			||||||
                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                    my($myaction) = $default_action; my($stop) = 0;
 | 
					                                    my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                    $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
					                                    $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
				
			||||||
                                    return ($stop,$index,$myaction,$myline,%request);
 | 
					                                    return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
| 
						 | 
					@ -771,8 +789,8 @@ DESCRIPTION
 | 
				
			||||||
                            # dumps current request contents to syslog
 | 
					                            # dumps current request contents to syslog
 | 
				
			||||||
                            "dumprequest" => sub {
 | 
					                            "dumprequest" => sub {
 | 
				
			||||||
                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                    my($myaction) = $default_action; my($stop) = 0;
 | 
					                                    my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                    map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
					                                    map { log_info "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
				
			||||||
                                    return ($stop,$index,$myaction,$myline,%request);
 | 
					                                    return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1038,6 +1056,9 @@ DESCRIPTION
 | 
				
			||||||
            before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
					            before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
				
			||||||
            With this mode rate limits will be faster, but also eventually set up
 | 
					            With this mode rate limits will be faster, but also eventually set up
 | 
				
			||||||
            whitelisting-rules within the ruleset might not work as expected.
 | 
					            whitelisting-rules within the ruleset might not work as expected.
 | 
				
			||||||
 | 
					            LIMITATIONS: This option does not allow nested postfwd commands like
 | 
				
			||||||
 | 
					                    action=rate(sender/3/60/wait(3))
 | 
				
			||||||
 | 
					            This option doe not work with the strict-rfc5321 rate() functions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *Informational arguments*
 | 
					    *Informational arguments*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,41 @@
 | 
				
			||||||
 | 
					postfwd2 1.35
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					- code:    rate(), size() and rcpt() function index is now case insensitive by default
 | 
				
			||||||
 | 
					           (same limit counters for from@example.org and fRom@eXample.org)
 | 
				
			||||||
 | 
					           if you need to treat the localpart case-sensitive according to rfc5321
 | 
				
			||||||
 | 
					           you may use rate5321(), size5321() and rcpt5321().
 | 
				
			||||||
 | 
					- bugfix:  fixed segfault when using new perl versions (prevented to work with upstart)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					postfwd2 1.34
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					- bugfix:  fixed taint mode logging error for verbose --showconfig and --stdoutlog
 | 
				
			||||||
 | 
					           options and newer perl versions.
 | 
				
			||||||
 | 
					- bugfix:  check_* functions use print/getline instead of send/recv for large
 | 
				
			||||||
 | 
					           --dumpcache output (thanks to Alexandre Simon)
 | 
				
			||||||
 | 
					- code:    added more information when using --debug=cleanup
 | 
				
			||||||
 | 
					- docs:    documentation updates
 | 
				
			||||||
 | 
					- feature: new sendmail(sendmail-path::from::to::subject::body) action.
 | 
				
			||||||
 | 
					           Please take a look at the manual, especially about
 | 
				
			||||||
 | 
					           it's limitations, before using it!
 | 
				
			||||||
 | 
					    ------------------------------------------------------------
 | 
				
			||||||
 | 
					     # alert
 | 
				
			||||||
 | 
					     action=sendmail(/usr/sbin/sendmail::from@example.org::to@example.org::Subject::Text)
 | 
				
			||||||
 | 
					    ------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					postfwd2 1.33
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					- feature: new compare operators *
 | 
				
			||||||
 | 
					        ====================================================================
 | 
				
			||||||
 | 
					         ITEM > VALUE                true if ITEM > VALUE
 | 
				
			||||||
 | 
					         ITEM < VALUE                true if ITEM < VALUE
 | 
				
			||||||
 | 
					        ====================================================================
 | 
				
			||||||
 | 
					- bugfix:  fixed bug when computing scores with more than 1 digit after the "." (n.nn)
 | 
				
			||||||
 | 
					- bugfix:  fixed bug when computing negative values with the set action
 | 
				
			||||||
 | 
					- bugfix:  ITEMS plugins returning zero values were handled incorrectly
 | 
				
			||||||
 | 
					- bugfix:  max command recursion was not reset for each rule
 | 
				
			||||||
 | 
					- bugfix:  fixed warning about use of (uninitialized value) when STORABLE is available
 | 
				
			||||||
 | 
					           but no cache file was defined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
postfwd2 1.32
 | 
					postfwd2 1.32
 | 
				
			||||||
=============
 | 
					=============
 | 
				
			||||||
- feature: new option --save_rates=<file> allows to load and save
 | 
					- feature: new option --save_rates=<file> allows to load and save
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,18 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" ?>
 | 
				
			||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
					<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
				
			||||||
<html xmlns="http://www.w3.org/1999/xhtml">
 | 
					<html xmlns="http://www.w3.org/1999/xhtml">
 | 
				
			||||||
<head>
 | 
					<head>
 | 
				
			||||||
<title>postfwd2 - postfix firewall daemon</title>
 | 
					<title>postfwd2 - postfix firewall daemon</title>
 | 
				
			||||||
 | 
					<meta http-equiv="content-type" content="text/html; charset=utf-8" />
 | 
				
			||||||
<link rev="made" href="mailto:root@localhost" />
 | 
					<link rev="made" href="mailto:root@localhost" />
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<body style="background-color: white">
 | 
					<body style="background-color: white">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<p><a name="__index__"></a></p>
 | 
					
 | 
				
			||||||
<!-- INDEX BEGIN -->
 | 
					<!-- INDEX BEGIN -->
 | 
				
			||||||
 | 
					<div name="index">
 | 
				
			||||||
 | 
					<p><a name="__index__"></a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<ul>
 | 
					<ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,9 +42,11 @@
 | 
				
			||||||
	<li><a href="#license">LICENSE</a></li>
 | 
						<li><a href="#license">LICENSE</a></li>
 | 
				
			||||||
	<li><a href="#author">AUTHOR</a></li>
 | 
						<li><a href="#author">AUTHOR</a></li>
 | 
				
			||||||
</ul>
 | 
					</ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<hr name="index" />
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
<!-- INDEX END -->
 | 
					<!-- INDEX END -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<hr />
 | 
					 | 
				
			||||||
<p>
 | 
					<p>
 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
<h1><a name="name">NAME</a></h1>
 | 
					<h1><a name="name">NAME</a></h1>
 | 
				
			||||||
| 
						 | 
					@ -125,7 +131,8 @@
 | 
				
			||||||
            --config_timeout <i>        parser timeout in seconds
 | 
					            --config_timeout <i>        parser timeout in seconds
 | 
				
			||||||
            --keep_rates                do not clear rate limit counters on reload
 | 
					            --keep_rates                do not clear rate limit counters on reload
 | 
				
			||||||
            --save_rates <file>         save and load rate limits on disk
 | 
					            --save_rates <file>         save and load rate limits on disk
 | 
				
			||||||
            --fast_limit_evaluation     evaluate rate limits before ruleset is parsed</pre>
 | 
					            --fast_limit_evaluation     evaluate rate limits before ruleset is parsed
 | 
				
			||||||
 | 
					                                        (please note the limitations)</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        Plugins:
 | 
					        Plugins:
 | 
				
			||||||
            --plugins <file>            loads postfwd plugins from file</pre>
 | 
					            --plugins <file>            loads postfwd plugins from file</pre>
 | 
				
			||||||
| 
						 | 
					@ -194,6 +201,8 @@ is not important. So the following would lead to the same result as the previous
 | 
				
			||||||
         ITEM == VALUE                true if ITEM equals VALUE
 | 
					         ITEM == VALUE                true if ITEM equals VALUE
 | 
				
			||||||
         ITEM => VALUE                true if ITEM >= VALUE
 | 
					         ITEM => VALUE                true if ITEM >= VALUE
 | 
				
			||||||
         ITEM =< VALUE                true if ITEM <= VALUE
 | 
					         ITEM =< VALUE                true if ITEM <= VALUE
 | 
				
			||||||
 | 
					         ITEM >  VALUE                true if ITEM >  VALUE
 | 
				
			||||||
 | 
					         ITEM <  VALUE                true if ITEM <  VALUE
 | 
				
			||||||
         ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
					         ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
				
			||||||
         ITEM != VALUE                false if ITEM equals VALUE
 | 
					         ITEM != VALUE                false if ITEM equals VALUE
 | 
				
			||||||
         ITEM !> VALUE                false if ITEM >= VALUE
 | 
					         ITEM !> VALUE                false if ITEM >= VALUE
 | 
				
			||||||
| 
						 | 
					@ -471,7 +480,7 @@ necessary. Of course this might increase the system load, so please use it with
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        -- FILE /etc/postfwd/clients_west.cf --
 | 
					        -- FILE /etc/postfwd/clients_west.cf --
 | 
				
			||||||
        192.168.3.0/24</pre>
 | 
					        192.168.3.0/24</pre>
 | 
				
			||||||
<p>Remind that there is currently no loop detection (/a/file calls /a/file) and that this feature is only available
 | 
					<p>Note that there is currently no loop detection (/a/file calls /a/file) and that this feature is only available
 | 
				
			||||||
with postfwd1 v1.15 and postfwd2 v0.18 and higher.</p>
 | 
					with postfwd1 v1.15 and postfwd2 v0.18 and higher.</p>
 | 
				
			||||||
<p>
 | 
					<p>
 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
| 
						 | 
					@ -485,7 +494,7 @@ request attributes by preceeding $$ characters, like:</p>
 | 
				
			||||||
        id=R-003; client_name = !!$$helo_name; action=WARN helo '$$(helo_name)' does not match DNS '$$(client_name)'</pre>
 | 
					        id=R-003; client_name = !!$$helo_name; action=WARN helo '$$(helo_name)' does not match DNS '$$(client_name)'</pre>
 | 
				
			||||||
<p><em>postfix actions</em></p>
 | 
					<p><em>postfix actions</em></p>
 | 
				
			||||||
<p>Actions will be replied to postfix as result to policy delegation requests. Any action that postfix understands is allowed - see
 | 
					<p>Actions will be replied to postfix as result to policy delegation requests. Any action that postfix understands is allowed - see
 | 
				
			||||||
``man 5 access'' or <a href="http://www.postfix.org/access.5.html">http://www.postfix.org/access.5.html</a> for a description. If no action is specified, the postfix WARN action
 | 
					"man 5 access" or <a href="http://www.postfix.org/access.5.html">http://www.postfix.org/access.5.html</a> for a description. If no action is specified, the postfix WARN action
 | 
				
			||||||
which simply logs the event will be used for the corresponding rule.</p>
 | 
					which simply logs the event will be used for the corresponding rule.</p>
 | 
				
			||||||
<p>postfwd2 will return dunno if it has reached the end of the ruleset and no rule has matched. This can be changed by placing a last
 | 
					<p>postfwd2 will return dunno if it has reached the end of the ruleset and no rule has matched. This can be changed by placing a last
 | 
				
			||||||
rule containing only an action statement:</p>
 | 
					rule containing only an action statement:</p>
 | 
				
			||||||
| 
						 | 
					@ -523,7 +532,7 @@ rule containing only an action statement:</p>
 | 
				
			||||||
        this command creates a counter for the given <item>, which will be increased any time a request
 | 
					        this command creates a counter for the given <item>, which will be increased any time a request
 | 
				
			||||||
        containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
					        containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
				
			||||||
        rate counters are very fast as they are executed before the ruleset is parsed.
 | 
					        rate counters are very fast as they are executed before the ruleset is parsed.
 | 
				
			||||||
        please note that <action> is currently limited to postfix actions (no postfwd actions)!
 | 
					        please note that <action> was limited to postfix actions (no postfwd actions) for postfwd versions <1.33!
 | 
				
			||||||
            # no more than 3 requests per 5 minutes
 | 
					            # no more than 3 requests per 5 minutes
 | 
				
			||||||
            # from the same "unknown" client
 | 
					            # from the same "unknown" client
 | 
				
			||||||
            id=RATE01 ;  client_name==unknown
 | 
					            id=RATE01 ;  client_name==unknown
 | 
				
			||||||
| 
						 | 
					@ -545,6 +554,11 @@ rule containing only an action statement:</p>
 | 
				
			||||||
           # recipient count limit 3 per hour per client
 | 
					           # recipient count limit 3 per hour per client
 | 
				
			||||||
           id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address==!!(10.1.1.1)
 | 
					           id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address==!!(10.1.1.1)
 | 
				
			||||||
              action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)</pre>
 | 
					              action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)</pre>
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					        rate5321,size5321,rcpt5321 (<item>/<max>/<time>/<action>)
 | 
				
			||||||
 | 
					        same as the corresponding non-5321 functions, with the difference that the localpart of
 | 
				
			||||||
 | 
					        sender oder recipient addresses are evaluated case-sensitive according to rfc5321. That
 | 
				
			||||||
 | 
					        means that requests from bob@example.local and BoB@example.local will be treated differently</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        ask (<addr>:<port>[:<ignore>])
 | 
					        ask (<addr>:<port>[:<ignore>])
 | 
				
			||||||
        allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
					        allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
				
			||||||
| 
						 | 
					@ -557,9 +571,15 @@ rule containing only an action statement:</p>
 | 
				
			||||||
           id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)</pre>
 | 
					           id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        mail(server/helo/from/to/subject/body)
 | 
					        mail(server/helo/from/to/subject/body)
 | 
				
			||||||
 | 
					        This command is deprecated. You should try to use the sendmail() action instead.
 | 
				
			||||||
        Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
					        Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
				
			||||||
        This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
					        This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
				
			||||||
        not track notification state and will notify you any time, the corresponding rule hits.</pre>
 | 
					        not track notification state and will notify you any time, the corresponding rule hits.</pre>
 | 
				
			||||||
 | 
					<pre>
 | 
				
			||||||
 | 
					        sendmail(sendmail-path::from::to::subject::body)
 | 
				
			||||||
 | 
					        Mail command, that uses an existing sendmail binary and sends a message with the given arguments.
 | 
				
			||||||
 | 
					        LIMITATIONS: The command does not track notification state and will notify you any time, the
 | 
				
			||||||
 | 
					        corresponding rule hits (which could mean 100 mails for a mail with 100 recipients at RCPT stage).</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        wait (<delay>)
 | 
					        wait (<delay>)
 | 
				
			||||||
        pauses the program execution for <delay> seconds. use this for
 | 
					        pauses the program execution for <delay> seconds. use this for
 | 
				
			||||||
| 
						 | 
					@ -700,6 +720,10 @@ will be used.</p>
 | 
				
			||||||
                                        $myresult = ($myitem <= $val);
 | 
					                                        $myresult = ($myitem <= $val);
 | 
				
			||||||
                                } elsif ($cmp eq '=>') {
 | 
					                                } elsif ($cmp eq '=>') {
 | 
				
			||||||
                                        $myresult = ($myitem >= $val);
 | 
					                                        $myresult = ($myitem >= $val);
 | 
				
			||||||
 | 
					                                } elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
					                                        $myresult = ($myitem < $val);
 | 
				
			||||||
 | 
					                                } elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
					                                        $myresult = ($myitem > $val);
 | 
				
			||||||
                                } elsif ($cmp eq '!=') {
 | 
					                                } elsif ($cmp eq '!=') {
 | 
				
			||||||
                                        $myresult = not($myitem == $val);
 | 
					                                        $myresult = not($myitem == $val);
 | 
				
			||||||
                                } elsif ($cmp eq '!<') {
 | 
					                                } elsif ($cmp eq '!<') {
 | 
				
			||||||
| 
						 | 
					@ -729,15 +753,15 @@ continue or to stop parsing the ruleset.</p>
 | 
				
			||||||
                        # note(<logstring>) command
 | 
					                        # note(<logstring>) command
 | 
				
			||||||
                        "note"  => sub {
 | 
					                        "note"  => sub {
 | 
				
			||||||
                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                my($myaction) = $default_action; my($stop) = 0;
 | 
					                                my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
					                                log_info "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
				
			||||||
                                return ($stop,$index,$myaction,$myline,%request);
 | 
					                                return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                        # skips next <myarg> rules
 | 
					                        # skips next <myarg> rules
 | 
				
			||||||
                        "skip" => sub {
 | 
					                        "skip" => sub {
 | 
				
			||||||
                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                my($myaction) = $default_action; my($stop) = 0;
 | 
					                                my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
					                                $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
				
			||||||
                                return ($stop,$index,$myaction,$myline,%request);
 | 
					                                return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
| 
						 | 
					@ -745,8 +769,8 @@ continue or to stop parsing the ruleset.</p>
 | 
				
			||||||
                        # dumps current request contents to syslog
 | 
					                        # dumps current request contents to syslog
 | 
				
			||||||
                        "dumprequest" => sub {
 | 
					                        "dumprequest" => sub {
 | 
				
			||||||
                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                my($myaction) = $default_action; my($stop) = 0;
 | 
					                                my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
					                                map { log_info "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
				
			||||||
                                return ($stop,$index,$myaction,$myline,%request);
 | 
					                                return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                        },</pre>
 | 
					                        },</pre>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
| 
						 | 
					@ -978,7 +1002,10 @@ The following arguments will control it's behaviour in this case.</p>
 | 
				
			||||||
        Once a ratelimit was set by the ruleset, future requests will be evaluated against it
 | 
					        Once a ratelimit was set by the ruleset, future requests will be evaluated against it
 | 
				
			||||||
        before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
					        before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
				
			||||||
        With this mode rate limits will be faster, but also eventually set up
 | 
					        With this mode rate limits will be faster, but also eventually set up
 | 
				
			||||||
        whitelisting-rules within the ruleset might not work as expected.</pre>
 | 
					        whitelisting-rules within the ruleset might not work as expected.
 | 
				
			||||||
 | 
					        LIMITATIONS: This option does not allow nested postfwd commands like
 | 
				
			||||||
 | 
					                action=rate(sender/3/60/wait(3))
 | 
				
			||||||
 | 
					        This option doe not work with the strict-rfc5321 rate() functions.</pre>
 | 
				
			||||||
<p><em>Informational arguments</em></p>
 | 
					<p><em>Informational arguments</em></p>
 | 
				
			||||||
<p>These arguments are for command line usage only. Never ever use them with postfix!</p>
 | 
					<p>These arguments are for command line usage only. Never ever use them with postfix!</p>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
| 
						 | 
					@ -1215,7 +1242,7 @@ check the parser with the -C | --showconfig switch at the command line before ap
 | 
				
			||||||
        Rule   0: id->"RBL001"; action->"REJECT listed on spamcop and bad rdns"; rbl->"bl.spamcop.net"; client_name->"^unknown$"</pre>
 | 
					        Rule   0: id->"RBL001"; action->"REJECT listed on spamcop and bad rdns"; rbl->"bl.spamcop.net"; client_name->"^unknown$"</pre>
 | 
				
			||||||
<p><em>Request processing</em></p>
 | 
					<p><em>Request processing</em></p>
 | 
				
			||||||
<p>When a policy delegation request arrives it will be compared against postfwd`s ruleset. To inspect the processing in detail you should increase
 | 
					<p>When a policy delegation request arrives it will be compared against postfwd`s ruleset. To inspect the processing in detail you should increase
 | 
				
			||||||
verbority using use the ``-v'' or ``-vv'' switch. ``-L'' redirects log messages to stdout.</p>
 | 
					verbority using use the "-v" or "-vv" switch. "-L" redirects log messages to stdout.</p>
 | 
				
			||||||
<p>Keeping the order of the ruleset in general, items will be compared in random order, which basically means that</p>
 | 
					<p>Keeping the order of the ruleset in general, items will be compared in random order, which basically means that</p>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        id=R001; action=dunno; client_address=192.168.1.1; sender=bob@alice.local</pre>
 | 
					        id=R001; action=dunno; client_address=192.168.1.1; sender=bob@alice.local</pre>
 | 
				
			||||||
| 
						 | 
					@ -1254,7 +1281,7 @@ to compare against the request attribute the parser will jump to the next rule i
 | 
				
			||||||
<p>If a rule matches, there are two options:</p>
 | 
					<p>If a rule matches, there are two options:</p>
 | 
				
			||||||
<p>* Rule returns postfix action (dunno, reject, ...)
 | 
					<p>* Rule returns postfix action (dunno, reject, ...)
 | 
				
			||||||
The parser stops rule processing and returns the action to postfix. Other rules will not be evaluated.</p>
 | 
					The parser stops rule processing and returns the action to postfix. Other rules will not be evaluated.</p>
 | 
				
			||||||
<p>* Rule returns postfwd2 action (jump(), note(), ...)
 | 
					<p>* Rule returns postfwd2 action (jump(), <code>note()</code>, ...)
 | 
				
			||||||
The parser evaluates the given action and continues with the next rule (except for the <code>jump()</code> or <code>quit()</code> actions - please see the <a href="#actions">ACTIONS</a> section
 | 
					The parser evaluates the given action and continues with the next rule (except for the <code>jump()</code> or <code>quit()</code> actions - please see the <a href="#actions">ACTIONS</a> section
 | 
				
			||||||
for more information). Nothing will be sent to postfix.</p>
 | 
					for more information). Nothing will be sent to postfix.</p>
 | 
				
			||||||
<p>If no rule has matched and the end of the ruleset is reached postfwd2 will return dunno without logging anything unless in verbose mode. You may
 | 
					<p>If no rule has matched and the end of the ruleset is reached postfwd2 will return dunno without logging anything unless in verbose mode. You may
 | 
				
			||||||
| 
						 | 
					@ -1283,7 +1310,7 @@ the prefered way to use postfwd2 in high volume environments. Start postfwd2 wit
 | 
				
			||||||
        postfwd2 -d -f /etc/postfwd.cf -i 127.0.0.1 -p 10045 -u nobody -g nobody -S</pre>
 | 
					        postfwd2 -d -f /etc/postfwd.cf -i 127.0.0.1 -p 10045 -u nobody -g nobody -S</pre>
 | 
				
			||||||
<p>For efficient caching you should check if you can use the options --cacheid, --cache-rdomain-only,
 | 
					<p>For efficient caching you should check if you can use the options --cacheid, --cache-rdomain-only,
 | 
				
			||||||
--cache-no-sender and --cache-no-size.</p>
 | 
					--cache-no-sender and --cache-no-size.</p>
 | 
				
			||||||
<p>Now check your syslogs (default facility ``mail'') for a line like:</p>
 | 
					<p>Now check your syslogs (default facility "mail") for a line like:</p>
 | 
				
			||||||
<pre>
 | 
					<pre>
 | 
				
			||||||
        Aug  9 23:00:24 mail postfwd[5158]: postfwd2 n.nn ready for input</pre>
 | 
					        Aug  9 23:00:24 mail postfwd[5158]: postfwd2 n.nn ready for input</pre>
 | 
				
			||||||
<p>and use `netstat -an|grep 10045` to check for something like</p>
 | 
					<p>and use `netstat -an|grep 10045` to check for something like</p>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,8 @@ SYNOPSIS
 | 
				
			||||||
                --keep_rates                do not clear rate limit counters on reload
 | 
					                --keep_rates                do not clear rate limit counters on reload
 | 
				
			||||||
                --save_rates <file>         save and load rate limits on disk
 | 
					                --save_rates <file>         save and load rate limits on disk
 | 
				
			||||||
                --fast_limit_evaluation     evaluate rate limits before ruleset is parsed
 | 
					                --fast_limit_evaluation     evaluate rate limits before ruleset is parsed
 | 
				
			||||||
 | 
					                                            (please note the limitations)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Plugins:
 | 
					            Plugins:
 | 
				
			||||||
                --plugins <file>            loads postfwd plugins from file
 | 
					                --plugins <file>            loads postfwd plugins from file
 | 
				
			||||||
| 
						 | 
					@ -161,6 +163,8 @@ DESCRIPTION
 | 
				
			||||||
             ITEM == VALUE                true if ITEM equals VALUE
 | 
					             ITEM == VALUE                true if ITEM equals VALUE
 | 
				
			||||||
             ITEM => VALUE                true if ITEM >= VALUE
 | 
					             ITEM => VALUE                true if ITEM >= VALUE
 | 
				
			||||||
             ITEM =< VALUE                true if ITEM <= VALUE
 | 
					             ITEM =< VALUE                true if ITEM <= VALUE
 | 
				
			||||||
 | 
					             ITEM >  VALUE                true if ITEM >  VALUE
 | 
				
			||||||
 | 
					             ITEM <  VALUE                true if ITEM <  VALUE
 | 
				
			||||||
             ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
					             ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
				
			||||||
             ITEM != VALUE                false if ITEM equals VALUE
 | 
					             ITEM != VALUE                false if ITEM equals VALUE
 | 
				
			||||||
             ITEM !> VALUE                false if ITEM >= VALUE
 | 
					             ITEM !> VALUE                false if ITEM >= VALUE
 | 
				
			||||||
| 
						 | 
					@ -485,7 +489,7 @@ DESCRIPTION
 | 
				
			||||||
            -- FILE /etc/postfwd/clients_west.cf --
 | 
					            -- FILE /etc/postfwd/clients_west.cf --
 | 
				
			||||||
            192.168.3.0/24
 | 
					            192.168.3.0/24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Remind that there is currently no loop detection (/a/file calls /a/file)
 | 
					    Note that there is currently no loop detection (/a/file calls /a/file)
 | 
				
			||||||
    and that this feature is only available with postfwd1 v1.15 and postfwd2
 | 
					    and that this feature is only available with postfwd1 v1.15 and postfwd2
 | 
				
			||||||
    v0.18 and higher.
 | 
					    v0.18 and higher.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -548,7 +552,7 @@ DESCRIPTION
 | 
				
			||||||
            this command creates a counter for the given <item>, which will be increased any time a request
 | 
					            this command creates a counter for the given <item>, which will be increased any time a request
 | 
				
			||||||
            containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
					            containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
				
			||||||
            rate counters are very fast as they are executed before the ruleset is parsed.
 | 
					            rate counters are very fast as they are executed before the ruleset is parsed.
 | 
				
			||||||
            please note that <action> is currently limited to postfix actions (no postfwd actions)!
 | 
					            please note that <action> was limited to postfix actions (no postfwd actions) for postfwd versions <1.33!
 | 
				
			||||||
                # no more than 3 requests per 5 minutes
 | 
					                # no more than 3 requests per 5 minutes
 | 
				
			||||||
                # from the same "unknown" client
 | 
					                # from the same "unknown" client
 | 
				
			||||||
                id=RATE01 ;  client_name==unknown
 | 
					                id=RATE01 ;  client_name==unknown
 | 
				
			||||||
| 
						 | 
					@ -571,6 +575,11 @@ DESCRIPTION
 | 
				
			||||||
               id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address==!!(10.1.1.1)
 | 
					               id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address==!!(10.1.1.1)
 | 
				
			||||||
                  action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)
 | 
					                  action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            rate5321,size5321,rcpt5321 (<item>/<max>/<time>/<action>)
 | 
				
			||||||
 | 
					            same as the corresponding non-5321 functions, with the difference that the localpart of
 | 
				
			||||||
 | 
					            sender oder recipient addresses are evaluated case-sensitive according to rfc5321. That
 | 
				
			||||||
 | 
					            means that requests from bob@example.local and BoB@example.local will be treated differently
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ask (<addr>:<port>[:<ignore>])
 | 
					            ask (<addr>:<port>[:<ignore>])
 | 
				
			||||||
            allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
					            allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
				
			||||||
            and the second argument (address and port) are mandatory. a third optional argument may be
 | 
					            and the second argument (address and port) are mandatory. a third optional argument may be
 | 
				
			||||||
| 
						 | 
					@ -582,10 +591,16 @@ DESCRIPTION
 | 
				
			||||||
               id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)
 | 
					               id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            mail(server/helo/from/to/subject/body)
 | 
					            mail(server/helo/from/to/subject/body)
 | 
				
			||||||
 | 
					            This command is deprecated. You should try to use the sendmail() action instead.
 | 
				
			||||||
            Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
					            Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
				
			||||||
            This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
					            This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
				
			||||||
            not track notification state and will notify you any time, the corresponding rule hits.
 | 
					            not track notification state and will notify you any time, the corresponding rule hits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            sendmail(sendmail-path::from::to::subject::body)
 | 
				
			||||||
 | 
					            Mail command, that uses an existing sendmail binary and sends a message with the given arguments.
 | 
				
			||||||
 | 
					            LIMITATIONS: The command does not track notification state and will notify you any time, the
 | 
				
			||||||
 | 
					            corresponding rule hits (which could mean 100 mails for a mail with 100 recipients at RCPT stage).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            wait (<delay>)
 | 
					            wait (<delay>)
 | 
				
			||||||
            pauses the program execution for <delay> seconds. use this for
 | 
					            pauses the program execution for <delay> seconds. use this for
 | 
				
			||||||
            delaying or throtteling connections.
 | 
					            delaying or throtteling connections.
 | 
				
			||||||
| 
						 | 
					@ -743,6 +758,10 @@ DESCRIPTION
 | 
				
			||||||
                                            $myresult = ($myitem <= $val);
 | 
					                                            $myresult = ($myitem <= $val);
 | 
				
			||||||
                                    } elsif ($cmp eq '=>') {
 | 
					                                    } elsif ($cmp eq '=>') {
 | 
				
			||||||
                                            $myresult = ($myitem >= $val);
 | 
					                                            $myresult = ($myitem >= $val);
 | 
				
			||||||
 | 
					                                    } elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
					                                            $myresult = ($myitem < $val);
 | 
				
			||||||
 | 
					                                    } elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
					                                            $myresult = ($myitem > $val);
 | 
				
			||||||
                                    } elsif ($cmp eq '!=') {
 | 
					                                    } elsif ($cmp eq '!=') {
 | 
				
			||||||
                                            $myresult = not($myitem == $val);
 | 
					                                            $myresult = not($myitem == $val);
 | 
				
			||||||
                                    } elsif ($cmp eq '!<') {
 | 
					                                    } elsif ($cmp eq '!<') {
 | 
				
			||||||
| 
						 | 
					@ -774,15 +793,15 @@ DESCRIPTION
 | 
				
			||||||
                            # note(<logstring>) command
 | 
					                            # note(<logstring>) command
 | 
				
			||||||
                            "note"  => sub {
 | 
					                            "note"  => sub {
 | 
				
			||||||
                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                    my($myaction) = $default_action; my($stop) = 0;
 | 
					                                    my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                    mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
					                                    log_info "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
				
			||||||
                                    return ($stop,$index,$myaction,$myline,%request);
 | 
					                                    return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                            # skips next <myarg> rules
 | 
					                            # skips next <myarg> rules
 | 
				
			||||||
                            "skip" => sub {
 | 
					                            "skip" => sub {
 | 
				
			||||||
                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                    my($myaction) = $default_action; my($stop) = 0;
 | 
					                                    my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                    $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
					                                    $index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
				
			||||||
                                    return ($stop,$index,$myaction,$myline,%request);
 | 
					                                    return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
| 
						 | 
					@ -790,8 +809,8 @@ DESCRIPTION
 | 
				
			||||||
                            # dumps current request contents to syslog
 | 
					                            # dumps current request contents to syslog
 | 
				
			||||||
                            "dumprequest" => sub {
 | 
					                            "dumprequest" => sub {
 | 
				
			||||||
                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
					                                    my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
                                    my($myaction) = $default_action; my($stop) = 0;
 | 
					                                    my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
                                    map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
					                                    map { log_info "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
				
			||||||
                                    return ($stop,$index,$myaction,$myline,%request);
 | 
					                                    return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1035,6 +1054,9 @@ DESCRIPTION
 | 
				
			||||||
            before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
					            before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
				
			||||||
            With this mode rate limits will be faster, but also eventually set up
 | 
					            With this mode rate limits will be faster, but also eventually set up
 | 
				
			||||||
            whitelisting-rules within the ruleset might not work as expected.
 | 
					            whitelisting-rules within the ruleset might not work as expected.
 | 
				
			||||||
 | 
					            LIMITATIONS: This option does not allow nested postfwd commands like
 | 
				
			||||||
 | 
					                    action=rate(sender/3/60/wait(3))
 | 
				
			||||||
 | 
					            This option doe not work with the strict-rfc5321 rate() functions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *Informational arguments*
 | 
					    *Informational arguments*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1202
									
								
								man/man8/postfwd.8
									
										
									
									
									
								
							
							
						
						
									
										1202
									
								
								man/man8/postfwd.8
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1267
									
								
								man/man8/postfwd2.8
									
										
									
									
									
								
							
							
						
						
									
										1267
									
								
								man/man8/postfwd2.8
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -137,15 +137,15 @@
 | 
				
			||||||
	#	# note(<logstring>) command
 | 
						#	# note(<logstring>) command
 | 
				
			||||||
	#	"note"  => sub {
 | 
						#	"note"  => sub {
 | 
				
			||||||
	#		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
						#		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
	#		my($myaction) = $default_action; my($stop) = 0;
 | 
						#		my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
	#		mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
						#		log_info ("[RULES] ".$myline." - note: ".$myarg) if $myarg;
 | 
				
			||||||
	#		return ($stop,$index,$myaction,$myline,%request);
 | 
						#		return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
	#	},
 | 
						#	},
 | 
				
			||||||
	#
 | 
						#
 | 
				
			||||||
	#	# skips next <myarg> rules
 | 
						#	# skips next <myarg> rules
 | 
				
			||||||
        #	"skip" => sub {
 | 
					        #	"skip" => sub {
 | 
				
			||||||
	#		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
						#		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
	#		my($myaction) = $default_action; my($stop) = 0;
 | 
						#		my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
	#		$index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
						#		$index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
				
			||||||
	#		return ($stop,$index,$myaction,$myline,%request);
 | 
						#		return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
        #	},
 | 
					        #	},
 | 
				
			||||||
| 
						 | 
					@ -153,8 +153,8 @@
 | 
				
			||||||
	#	# dumps current request contents to syslog
 | 
						#	# dumps current request contents to syslog
 | 
				
			||||||
        #	"dumprequest" => sub {
 | 
					        #	"dumprequest" => sub {
 | 
				
			||||||
	#		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
						#		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
	#		my($myaction) = $default_action; my($stop) = 0;
 | 
						#		my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
	#		map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
						#		map { log_info ("[DUMP] rule=$index, Attribute: $_=$request{$_}") } (keys %request);
 | 
				
			||||||
	#		return ($stop,$index,$myaction,$myline,%request);
 | 
						#		return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
        #	},
 | 
					        #	},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										376
									
								
								sbin/postfwd
									
										
									
									
									
								
							
							
						
						
									
										376
									
								
								sbin/postfwd
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										131
									
								
								sbin/postfwd2
									
										
									
									
									
								
							
							
						
						
									
										131
									
								
								sbin/postfwd2
									
										
									
									
									
								
							| 
						 | 
					@ -34,7 +34,7 @@ BEGIN {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# basics
 | 
					# basics
 | 
				
			||||||
our $NAME	= "postfwd2";
 | 
					our $NAME	= "postfwd2";
 | 
				
			||||||
our $VERSION	= "1.32";
 | 
					our $VERSION	= "1.35";
 | 
				
			||||||
our $DEFAULT	= 'DUNNO';
 | 
					our $DEFAULT	= 'DUNNO';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# change this, to match your POD requirements
 | 
					# change this, to match your POD requirements
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,6 @@ our %postfwd_settings = (
 | 
				
			||||||
		proto		 => (($nounixsock) ? "tcp" : "unix"),
 | 
							proto		 => (($nounixsock) ? "tcp" : "unix"),
 | 
				
			||||||
		check		 => (($nounixsock) ? \&check_inet : \&check_unix),
 | 
							check		 => (($nounixsock) ? \&check_inet : \&check_unix),
 | 
				
			||||||
		umask		 => "0177",
 | 
							umask		 => "0177",
 | 
				
			||||||
		recvbuffer	 => 65535,
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	server => {
 | 
						server => {
 | 
				
			||||||
		commandline	 => " ".$NAME."::policy",
 | 
							commandline	 => " ".$NAME."::policy",
 | 
				
			||||||
| 
						 | 
					@ -85,7 +84,6 @@ our %postfwd_settings = (
 | 
				
			||||||
		proto            => "tcp",
 | 
							proto            => "tcp",
 | 
				
			||||||
		check		 => \&check_inet,
 | 
							check		 => \&check_inet,
 | 
				
			||||||
		umask		 => "0111",
 | 
							umask		 => "0111",
 | 
				
			||||||
		recvbuffer	 => 65535,
 | 
					 | 
				
			||||||
		# child control
 | 
							# child control
 | 
				
			||||||
		#check_for_dead         => 30,
 | 
							#check_for_dead         => 30,
 | 
				
			||||||
		#check_for_waiting      => 10,
 | 
							#check_for_waiting      => 10,
 | 
				
			||||||
| 
						 | 
					@ -299,8 +297,8 @@ sub mylogs_new {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Syslog to stdout
 | 
					# Syslog to stdout
 | 
				
			||||||
sub mylogs_stdout {
 | 
					sub mylogs_stdout {
 | 
				
			||||||
	my($prio,$msg) = @_;
 | 
						my($prio,$msg) = @_; $msg =~ /^(.*)$/;
 | 
				
			||||||
	printf STDOUT "[LOG $prio]: $msg\n", @_;
 | 
						printf STDOUT "[LOG $prio]: $1\n", @_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# send log message
 | 
					# send log message
 | 
				
			||||||
| 
						 | 
					@ -345,8 +343,8 @@ sub check_inet {
 | 
				
			||||||
		Proto    => 'tcp',
 | 
							Proto    => 'tcp',
 | 
				
			||||||
		Timeout  => $postfwd_settings{timeout}{$type},
 | 
							Timeout  => $postfwd_settings{timeout}{$type},
 | 
				
			||||||
		Type     => SOCK_STREAM ) ) {
 | 
							Type     => SOCK_STREAM ) ) {
 | 
				
			||||||
		$socket->send("$send\n");
 | 
							$socket->print("$send\n");
 | 
				
			||||||
		$socket->recv($send, $postfwd_settings{$type}{recvbuffer});
 | 
							$send = $socket->getline();
 | 
				
			||||||
		$socket->close();
 | 
							$socket->close();
 | 
				
			||||||
		chomp($send);
 | 
							chomp($send);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -363,8 +361,8 @@ sub check_unix {
 | 
				
			||||||
		Peer     => $postfwd_settings{$type}{port},
 | 
							Peer     => $postfwd_settings{$type}{port},
 | 
				
			||||||
		Timeout  => $postfwd_settings{timeout}{$type},
 | 
							Timeout  => $postfwd_settings{timeout}{$type},
 | 
				
			||||||
		Type     => SOCK_STREAM ) ) {
 | 
							Type     => SOCK_STREAM ) ) {
 | 
				
			||||||
		$socket->send("$send\n");
 | 
							$socket->print("$send\n");
 | 
				
			||||||
		$socket->recv($send, $postfwd_settings{$type}{recvbuffer});
 | 
							$send = $socket->getline();
 | 
				
			||||||
		$socket->close();
 | 
							$socket->close();
 | 
				
			||||||
		chomp($send);
 | 
							chomp($send);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -638,6 +636,7 @@ sub cleanup_cache {
 | 
				
			||||||
# saves rate limits to disk
 | 
					# saves rate limits to disk
 | 
				
			||||||
sub save_rates {
 | 
					sub save_rates {
 | 
				
			||||||
    return unless ($STORABLE and $postfwd_settings{rate}{store} and defined $Cache{rate});
 | 
					    return unless ($STORABLE and $postfwd_settings{rate}{store} and defined $Cache{rate});
 | 
				
			||||||
 | 
					    cleanup_cache ('rate', time());
 | 
				
			||||||
    eval {
 | 
					    eval {
 | 
				
			||||||
	local $SIG{__DIE__} = sub { log_note ("ERROR: Could not store rate limits to ".$postfwd_settings{rate}{store}.": $! @_") };
 | 
						local $SIG{__DIE__} = sub { log_note ("ERROR: Could not store rate limits to ".$postfwd_settings{rate}{store}.": $! @_") };
 | 
				
			||||||
	store ($Cache{rate}, $postfwd_settings{rate}{store});
 | 
						store ($Cache{rate}, $postfwd_settings{rate}{store});
 | 
				
			||||||
| 
						 | 
					@ -651,7 +650,7 @@ sub save_rates {
 | 
				
			||||||
# loads rate limits from disk
 | 
					# loads rate limits from disk
 | 
				
			||||||
sub load_rates {
 | 
					sub load_rates {
 | 
				
			||||||
    my $loadrate = undef;
 | 
					    my $loadrate = undef;
 | 
				
			||||||
    return unless ($STORABLE and (-f $postfwd_settings{rate}{store}));
 | 
					    return unless ($STORABLE and $postfwd_settings{rate}{store} and (-f $postfwd_settings{rate}{store}));
 | 
				
			||||||
    eval {
 | 
					    eval {
 | 
				
			||||||
	local $SIG{__DIE__} = sub { log_note ("Could not load rate limits from ".$postfwd_settings{rate}{store}.": $! @_") };
 | 
						local $SIG{__DIE__} = sub { log_note ("Could not load rate limits from ".$postfwd_settings{rate}{store}.": $! @_") };
 | 
				
			||||||
	$loadrate = retrieve($postfwd_settings{rate}{store});
 | 
						$loadrate = retrieve($postfwd_settings{rate}{store});
 | 
				
			||||||
| 
						 | 
					@ -660,6 +659,7 @@ sub load_rates {
 | 
				
			||||||
	$Cache{rate} = $loadrate;
 | 
						$Cache{rate} = $loadrate;
 | 
				
			||||||
        log_info ("Fetched ".(scalar %{$Cache{rate}})." rates from ".$postfwd_settings{rate}{store})
 | 
					        log_info ("Fetched ".(scalar %{$Cache{rate}})." rates from ".$postfwd_settings{rate}{store})
 | 
				
			||||||
                if wantsdebug(qw[ all verbose rates loadrates saverates ]);
 | 
					                if wantsdebug(qw[ all verbose rates loadrates saverates ]);
 | 
				
			||||||
 | 
						cleanup_cache ('rate', time());
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -880,7 +880,7 @@ my $COMP_HITS                 = "request_hits";
 | 
				
			||||||
# item match counter
 | 
					# item match counter
 | 
				
			||||||
my $COMP_MATCHES              = "matches";
 | 
					my $COMP_MATCHES              = "matches";
 | 
				
			||||||
# separator
 | 
					# separator
 | 
				
			||||||
my $COMP_SEPARATOR            = "[=\~\<\>]=|[=\!][=\~\<\>]|=";
 | 
					my $COMP_SEPARATOR            = "[=\~\<\>]=|[\<\>]|[=\!][=\~\<\>]|=";
 | 
				
			||||||
# macros
 | 
					# macros
 | 
				
			||||||
my $COMP_ACL                  = "[\&][\&]";
 | 
					my $COMP_ACL                  = "[\&][\&]";
 | 
				
			||||||
# negation
 | 
					# negation
 | 
				
			||||||
| 
						 | 
					@ -1141,7 +1141,7 @@ sub check_for_old_syntax {
 | 
				
			||||||
  if ($mykey =~ /^action$/) {
 | 
					  if ($mykey =~ /^action$/) {
 | 
				
			||||||
    if ($myvalue =~ /^(\w[\-\w]+)\s*\(\s*(.*?)\s*\)$/) {
 | 
					    if ($myvalue =~ /^(\w[\-\w]+)\s*\(\s*(.*?)\s*\)$/) {
 | 
				
			||||||
	my($mycmd,$myarg) = ($1, $2);
 | 
						my($mycmd,$myarg) = ($1, $2);
 | 
				
			||||||
	if ($mycmd =~ /^(rate|size|rcpt)$/i) {
 | 
						if ($mycmd =~ /^(rate|size|rcpt)(5321)?$/i) {
 | 
				
			||||||
	  if ($myarg =~ /^\$\$(.*)$/) {
 | 
						  if ($myarg =~ /^\$\$(.*)$/) {
 | 
				
			||||||
	    $myarg = $1;
 | 
						    $myarg = $1;
 | 
				
			||||||
	    $myvalue = "$mycmd($myarg)";
 | 
						    $myvalue = "$mycmd($myarg)";
 | 
				
			||||||
| 
						 | 
					@ -1630,7 +1630,7 @@ sub postfwd_items {
 | 
				
			||||||
	%result = (%result, &{$postfwd_items{$_}}((%request,%result)))
 | 
						%result = (%result, &{$postfwd_items{$_}}((%request,%result)))
 | 
				
			||||||
		if (defined $postfwd_items{$_});
 | 
							if (defined $postfwd_items{$_});
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    map { $result{$_} = '' unless $result{$_}; log_info ("[PLUGIN]  Added key: $_=$result{$_}") if wantsdebug (qw[ all thisrequest ]) } (keys %result);
 | 
					    map { $result{$_} = '' unless (defined $result{$_}); log_info ("[PLUGIN]  Added key: $_=$result{$_}") if wantsdebug (qw[ all thisrequest ]) } (keys %result);
 | 
				
			||||||
    return %result;
 | 
					    return %result;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -1671,6 +1671,10 @@ sub postfwd_items {
 | 
				
			||||||
                        $myresult = ($myitem <= $val);
 | 
					                        $myresult = ($myitem <= $val);
 | 
				
			||||||
                } elsif ($cmp eq '=>') {
 | 
					                } elsif ($cmp eq '=>') {
 | 
				
			||||||
                        $myresult = ($myitem >= $val);
 | 
					                        $myresult = ($myitem >= $val);
 | 
				
			||||||
 | 
					                } elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
					                        $myresult = ($myitem < $val);
 | 
				
			||||||
 | 
					                } elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
					                        $myresult = ($myitem > $val);
 | 
				
			||||||
                } elsif ($cmp eq '!=') {
 | 
					                } elsif ($cmp eq '!=') {
 | 
				
			||||||
                        $myresult = not($myitem == $val);
 | 
					                        $myresult = not($myitem == $val);
 | 
				
			||||||
                } elsif ($cmp eq '!<') {
 | 
					                } elsif ($cmp eq '!<') {
 | 
				
			||||||
| 
						 | 
					@ -1835,6 +1839,10 @@ sub postfwd_items {
 | 
				
			||||||
			$myresult = (($myitem || 0) >= $val);
 | 
								$myresult = (($myitem || 0) >= $val);
 | 
				
			||||||
		} elsif ($cmp eq '!>') {
 | 
							} elsif ($cmp eq '!>') {
 | 
				
			||||||
			$myresult = not(($myitem || 0) >= $val);
 | 
								$myresult = not(($myitem || 0) >= $val);
 | 
				
			||||||
 | 
							} elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
								$myresult = (($myitem || 0) < $val);
 | 
				
			||||||
 | 
							} elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
								$myresult = (($myitem || 0) > $val);
 | 
				
			||||||
		} elsif ($cmp eq '=~') {
 | 
							} elsif ($cmp eq '=~') {
 | 
				
			||||||
			$myresult = ($myitem =~ /$val/i);
 | 
								$myresult = ($myitem =~ /$val/i);
 | 
				
			||||||
		} elsif ($cmp eq '!~') {
 | 
							} elsif ($cmp eq '!~') {
 | 
				
			||||||
| 
						 | 
					@ -1895,13 +1903,13 @@ sub postfwd_items {
 | 
				
			||||||
					$m_val = $r_val;
 | 
										$m_val = $r_val;
 | 
				
			||||||
				} elsif ( ($mod eq '.=') or ($mod eq '=.') ) {
 | 
									} elsif ( ($mod eq '.=') or ($mod eq '=.') ) {
 | 
				
			||||||
					$m_val .= $r_val;
 | 
										$m_val .= $r_val;
 | 
				
			||||||
				} elsif ( (($mod eq '+=') or ($mod eq '=+')) and (($m_val=~/^\d+(\.\d+)?$/) and ($r_val=~/^\d+(\.\d+)?$/)) ) {
 | 
									} elsif ( (($mod eq '+=') or ($mod eq '=+')) and (($m_val=~/^\-?\d+(\.\d+)?$/) and ($r_val=~/^\-?\d+(\.\d+)?$/)) ) {
 | 
				
			||||||
					$m_val += $r_val;
 | 
										$m_val += $r_val;
 | 
				
			||||||
				} elsif ( (($mod eq '-=') or ($mod eq '=-')) and (($m_val=~/^\d+(\.\d+)?$/) and ($r_val=~/^\d+(\.\d+)?$/)) ) {
 | 
									} elsif ( (($mod eq '-=') or ($mod eq '=-')) and (($m_val=~/^\-?\d+(\.\d+)?$/) and ($r_val=~/^\-?\d+(\.\d+)?$/)) ) {
 | 
				
			||||||
					$m_val -= $r_val;
 | 
										$m_val -= $r_val;
 | 
				
			||||||
				} elsif ( (($mod eq '*=') or ($mod eq '=*')) and (($m_val=~/^\d+(\.\d+)?$/) and ($r_val=~/^\d+(\.\d+)?$/)) ) {
 | 
									} elsif ( (($mod eq '*=') or ($mod eq '=*')) and (($m_val=~/^\-?\d+(\.\d+)?$/) and ($r_val=~/^\-?\d+(\.\d+)?$/)) ) {
 | 
				
			||||||
					$m_val *= $r_val;
 | 
										$m_val *= $r_val;
 | 
				
			||||||
				} elsif ( (($mod eq '/=') or ($mod eq '=/')) and (($m_val=~/^\d+(\.\d+)?$/) and ($r_val=~/^\d+(\.\d+)?$/)) ) {
 | 
									} elsif ( (($mod eq '/=') or ($mod eq '=/')) and (($m_val=~/^\-?\d+(\.\d+)?$/) and ($r_val=~/^\-?\d+(\.\d+)?$/)) ) {
 | 
				
			||||||
					$m_val /= (($r_val == 0) ? 1 : $r_val);
 | 
										$m_val /= (($r_val == 0) ? 1 : $r_val);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					$m_val = $r_val;
 | 
										$m_val = $r_val;
 | 
				
			||||||
| 
						 | 
					@ -1924,7 +1932,7 @@ sub postfwd_items {
 | 
				
			||||||
		my($myaction) = $postfwd_settings{default}; my($stop) = 0;
 | 
							my($myaction) = $postfwd_settings{default}; my($stop) = 0;
 | 
				
			||||||
		my($score) = (defined $request{request_score}) ? $request{request_score} : 0;
 | 
							my($score) = (defined $request{request_score}) ? $request{request_score} : 0;
 | 
				
			||||||
		if ($myarg =~/^([\+\-\*\/\=]?)(\d+)([\.,](\d+))?$/) {
 | 
							if ($myarg =~/^([\+\-\*\/\=]?)(\d+)([\.,](\d+))?$/) {
 | 
				
			||||||
			my($mod, $val) = ($1, $2 + ((defined $4) ? ($4 / 10) : 0));
 | 
								my($mod, $val) = ($1, $2 + ((defined $4) ? "0.$4" : 0));
 | 
				
			||||||
			if ($mod eq '-') {
 | 
								if ($mod eq '-') {
 | 
				
			||||||
				$score -= $val;
 | 
									$score -= $val;
 | 
				
			||||||
			} elsif ($mod eq '*') {
 | 
								} elsif ($mod eq '*') {
 | 
				
			||||||
| 
						 | 
					@ -1968,7 +1976,7 @@ sub postfwd_items {
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
		if ( my $socket = IO::Socket::INET->new(
 | 
							if ( my $socket = IO::Socket::INET->new(
 | 
				
			||||||
			PeerAddr => $mserver,
 | 
								PeerAddr => $mserver,
 | 
				
			||||||
			PeerPort => ($mport || 25),
 | 
								PeerPort => ($mport ||= 25),
 | 
				
			||||||
			Proto    => 'tcp',
 | 
								Proto    => 'tcp',
 | 
				
			||||||
			Timeout  => 30,
 | 
								Timeout  => 30,
 | 
				
			||||||
			Type     => SOCK_STREAM,
 | 
								Type     => SOCK_STREAM,
 | 
				
			||||||
| 
						 | 
					@ -1984,16 +1992,40 @@ sub postfwd_items {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		return ($stop,$index,$myaction,$myline,%request);
 | 
							return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						# sendmail()
 | 
				
			||||||
 | 
						"sendmail" => sub {
 | 
				
			||||||
 | 
							my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
 | 
							my($myaction) = $postfwd_settings{default}; my($stop) = 0;
 | 
				
			||||||
 | 
							my($mcmd,$mfrom,$mto,$msubject,$mbody) = split '::', $myarg, 5;
 | 
				
			||||||
 | 
							my($msg) = "From: $mfrom\nTo: $mto\nSubject: $msubject\n\n$mbody\n";
 | 
				
			||||||
 | 
							if ( (-x $mcmd) and open (SM, "| $mcmd -i -f $mfrom $mto") ) {
 | 
				
			||||||
 | 
								if ( print SM "$msg" ) {
 | 
				
			||||||
 | 
									log_info ("[SENDMAIL] ".$myline.", $mcmd from=<$mfrom>, to=<$mto>, subject=<$msubject>");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									log_note ("[SENDMAIL] ".$myline.", could not print to $mcmd pipe: '$!'");
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								close(SM);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								log_note ("[SENDMAIL] ".$myline.", could not open pipe to $mcmd: '$!'");
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	# rate() command
 | 
						# rate() command
 | 
				
			||||||
	"rate"	=> sub {
 | 
						"rate"	=> sub {
 | 
				
			||||||
		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
							my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
		my($myaction) = $postfwd_settings{default}; my($stop) = 0; my $prate = '';
 | 
							my($myaction) = $postfwd_settings{default}; my($stop) = 0; my $prate = '';
 | 
				
			||||||
		my($ratetype,$ratecount,$ratetime,$ratecmd) = split "/", $myarg, 4;
 | 
							my($ratetype,$ratecount,$ratetime,$ratecmd) = split "/", $myarg, 4;
 | 
				
			||||||
		my($rcount) = ( ($mycmd eq 'size') ? $request{size} : (($mycmd eq 'rcpt') ? $request{recipient_count} : 1 ) );
 | 
							my($rcount) = ( ($mycmd =~ /^size/) ? $request{size} : (($mycmd =~ /^rcpt/) ? $request{recipient_count} : 1 ) );
 | 
				
			||||||
		if ($ratetype and $ratecount and $ratetime and $ratecmd and $rcount) {
 | 
							if ($ratetype and $ratecount and $ratetime and $ratecmd and $rcount) {
 | 
				
			||||||
		  my $crate = $Rules[$index]{$COMP_ID}.'+'.$ratecount.'_'.$ratetime;
 | 
							  my $crate = $Rules[$index]{$COMP_ID}.'+'.$ratecount.'_'.$ratetime;
 | 
				
			||||||
		  if ( defined $request{$ratetype} ) {
 | 
							  if ( defined $request{$ratetype} ) {
 | 
				
			||||||
			$ratetype .= "=".$request{$ratetype};
 | 
					                        my $r = $request{$ratetype};
 | 
				
			||||||
 | 
					                        unless ($mycmd =~ /5321$/) {
 | 
				
			||||||
 | 
					                                $r = lc($r);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                                $r = ($r =~ /^([^@]+)@(\S+)$/) ? $1.'@'.lc($2) : lc($r);
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        $ratetype .= "=".$r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ( $postfwd_settings{rate}{fast_eval} ) {
 | 
								if ( $postfwd_settings{rate}{fast_eval} ) {
 | 
				
			||||||
				# Check if rate already exists in cache
 | 
									# Check if rate already exists in cache
 | 
				
			||||||
| 
						 | 
					@ -2077,6 +2109,12 @@ sub postfwd_items {
 | 
				
			||||||
	"size"	=> sub { return &{$postfwd_actions{rate}}(@_); },
 | 
						"size"	=> sub { return &{$postfwd_actions{rate}}(@_); },
 | 
				
			||||||
	# rcpt() command
 | 
						# rcpt() command
 | 
				
			||||||
	"rcpt"	=> sub { return &{$postfwd_actions{rate}}(@_); },
 | 
						"rcpt"	=> sub { return &{$postfwd_actions{rate}}(@_); },
 | 
				
			||||||
 | 
						# rate() command, according to rfc5321 case-sensivity
 | 
				
			||||||
 | 
						"rate5321"      => sub { return &{$postfwd_actions{rate}}(@_); },
 | 
				
			||||||
 | 
						# rcpt() command, according to rfc5321 case-sensivity
 | 
				
			||||||
 | 
						"rcpt5321"      => sub { return &{$postfwd_actions{rate}}(@_); },
 | 
				
			||||||
 | 
						# size() command, according to rfc5321 case-sensivity
 | 
				
			||||||
 | 
						"size5321"      => sub { return &{$postfwd_actions{rate}}(@_); },
 | 
				
			||||||
	# wait() command
 | 
						# wait() command
 | 
				
			||||||
	"wait"	=> sub {
 | 
						"wait"	=> sub {
 | 
				
			||||||
		my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
							my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
| 
						 | 
					@ -2206,7 +2244,7 @@ sub compare_item {
 | 
				
			||||||
    # now compare request to every single item
 | 
					    # now compare request to every single item
 | 
				
			||||||
    ITEM: foreach (@items) {
 | 
					    ITEM: foreach (@items) {
 | 
				
			||||||
	($cmp, $val) = split ";";
 | 
						($cmp, $val) = split ";";
 | 
				
			||||||
	next ITEM unless ($cmp and $val and $mykey);
 | 
						next ITEM unless ($cmp and (defined $val) and $mykey);
 | 
				
			||||||
	# prepare_file
 | 
						# prepare_file
 | 
				
			||||||
	if ($val =~ /$COMP_LIVE_FILE_TABLE/) {
 | 
						if ($val =~ /$COMP_LIVE_FILE_TABLE/) {
 | 
				
			||||||
		push @items, prepare_file (0, $1, $cmp, $2);
 | 
							push @items, prepare_file (0, $1, $cmp, $2);
 | 
				
			||||||
| 
						 | 
					@ -2215,7 +2253,7 @@ sub compare_item {
 | 
				
			||||||
	log_info ("compare $mykey:  \"$myitem\"  \"$cmp\"  \"$val\"") if wantsdebug (qw[ all thisrequest ]);
 | 
						log_info ("compare $mykey:  \"$myitem\"  \"$cmp\"  \"$val\"") if wantsdebug (qw[ all thisrequest ]);
 | 
				
			||||||
	$val = $neg if ($neg = deneg_item($val));
 | 
						$val = $neg if ($neg = deneg_item($val));
 | 
				
			||||||
	log_info ("deneg $mykey:  \"$myitem\"  \"$cmp\"  \"$val\"") if ($neg and wantsdebug (qw[ all thisrequest ]));
 | 
						log_info ("deneg $mykey:  \"$myitem\"  \"$cmp\"  \"$val\"") if ($neg and wantsdebug (qw[ all thisrequest ]));
 | 
				
			||||||
	next ITEM unless $val;
 | 
						next ITEM unless (defined $val);
 | 
				
			||||||
	# substitute check for $$vars in rule item
 | 
						# substitute check for $$vars in rule item
 | 
				
			||||||
	if ( $var = devar_item ($cmp,$val,$myitem,%request) ) {
 | 
						if ( $var = devar_item ($cmp,$val,$myitem,%request) ) {
 | 
				
			||||||
		$val = $var; $val =~ s/([^-_@\.\w\s])/\\$1/g unless ($cmp eq '==');
 | 
							$val = $var; $val =~ s/([^-_@\.\w\s])/\\$1/g unless ($cmp eq '==');
 | 
				
			||||||
| 
						 | 
					@ -2288,7 +2326,7 @@ sub compare_rule {
 | 
				
			||||||
			? $date
 | 
								? $date
 | 
				
			||||||
			# default: compare against request attribute
 | 
								# default: compare against request attribute
 | 
				
			||||||
			: $request{$mykey};
 | 
								: $request{$mykey};
 | 
				
			||||||
		$myresult[0] = ($res = compare_item($mykey, $Rules[$index]{$mykey}, $num, ($val || ''), %request)) ? ($myresult[0] + $res) : 0;
 | 
							$myresult[0] = ($res = compare_item($mykey, $Rules[$index]{$mykey}, $num, ((defined $val) ? $val : ''), %request)) ? ($myresult[0] + $res) : 0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	last ITEM unless ($myresult[0] > 0);
 | 
						last ITEM unless ($myresult[0] > 0);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -2493,7 +2531,7 @@ sub compare_rule {
 | 
				
			||||||
	$myline  = "[RULES]  RULE: ".$index."  MATCHES: ".((($myresult[0] - 2) > 0) ? ($myresult[0] - 2) : 0);
 | 
						$myline  = "[RULES]  RULE: ".$index."  MATCHES: ".((($myresult[0] - 2) > 0) ? ($myresult[0] - 2) : 0);
 | 
				
			||||||
	$myline .= "  RBLCOUNT: ".$myresult[1] if $myresult[1];
 | 
						$myline .= "  RBLCOUNT: ".$myresult[1] if $myresult[1];
 | 
				
			||||||
	$myline .= "  RHSBLCOUNT: ".$myresult[2] if $myresult[2];
 | 
						$myline .= "  RHSBLCOUNT: ".$myresult[2] if $myresult[2];
 | 
				
			||||||
	$myline .= "  DNSBLTEXT: ".(join ("; ", @DNSBL_Text)) if ( (defined @DNSBL_Text) and (($myresult[1] > 0) or ($myresult[2] > 0)) );
 | 
						$myline .= "  DNSBLTEXT: ".(join ("; ", @DNSBL_Text)) if ( (@DNSBL_Text) and (($myresult[1] > 0) or ($myresult[2] > 0)) );
 | 
				
			||||||
	log_info ($myline);
 | 
						log_info ($myline);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    return @myresult;
 | 
					    return @myresult;
 | 
				
			||||||
| 
						 | 
					@ -2549,7 +2587,7 @@ sub smtpd_access_policy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # increase rate limits
 | 
					    # increase rate limits
 | 
				
			||||||
    if (@Rate_Items and $postfwd_settings{rate}{fast_eval}) {
 | 
					    if (@Rate_Items and $postfwd_settings{rate}{fast_eval}) {
 | 
				
			||||||
	map { $checkval .= $_."=".$request{$_}.$postfwd_settings{seplst} if $request{$_} } (@Rate_Items);
 | 
						map { $checkval .= $_."=".lc($request{$_}).$postfwd_settings{seplst} if $request{$_} } (@Rate_Items);
 | 
				
			||||||
	if ($checkval) {
 | 
						if ($checkval) {
 | 
				
			||||||
		$checkval = "CMD=".$postfwd_commands{checkrate}.";TYPE=rate;ITEM=$checkval;SIZE=".($request{'size'} || 0).";RCPT=".($request{'recipient_count'} || 0);
 | 
							$checkval = "CMD=".$postfwd_commands{checkrate}.";TYPE=rate;ITEM=$checkval;SIZE=".($request{'size'} || 0).";RCPT=".($request{'recipient_count'} || 0);
 | 
				
			||||||
			log_info ("[RATES] parent rate limit query: ".$checkval) if wantsdebug (qw[ all thisrequest verbose rates ]);
 | 
								log_info ("[RATES] parent rate limit query: ".$checkval) if wantsdebug (qw[ all thisrequest verbose rates ]);
 | 
				
			||||||
| 
						 | 
					@ -2746,6 +2784,7 @@ sub smtpd_access_policy {
 | 
				
			||||||
					. ", state=".$request{protocol_state};
 | 
										. ", state=".$request{protocol_state};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				# check for postfwd action
 | 
									# check for postfwd action
 | 
				
			||||||
 | 
									$ai = 0; # (re)set max_command_recursion counter
 | 
				
			||||||
				while ($ai++ < $postfwd_settings{max_command_recursion} and $myaction =~ /^(\w[\-\w]+)\s*\(\s*(.*?)\s*\)$/) {
 | 
									while ($ai++ < $postfwd_settings{max_command_recursion} and $myaction =~ /^(\w[\-\w]+)\s*\(\s*(.*?)\s*\)$/) {
 | 
				
			||||||
					my($mycmd,$myarg) = ($1, $2); $stop = 0;
 | 
										my($mycmd,$myarg) = ($1, $2); $stop = 0;
 | 
				
			||||||
					if (defined $postfwd_actions{$mycmd}) {
 | 
										if (defined $postfwd_actions{$mycmd}) {
 | 
				
			||||||
| 
						 | 
					@ -3199,6 +3238,7 @@ log_note ("NODNS: set - will skip all dns based checks") if $postfwd_settings{dn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# check for --nodaemon option
 | 
					# check for --nodaemon option
 | 
				
			||||||
unless ($postfwd_settings{daemon}) {
 | 
					unless ($postfwd_settings{daemon}) {
 | 
				
			||||||
 | 
						log_note ("NODAEMON: Please note that rate() commands do not work with postfwd2 and --nodaemon option due to the missing cache daemon");
 | 
				
			||||||
	my(%attr) = ();
 | 
						my(%attr) = ();
 | 
				
			||||||
	get_plugins (@{$postfwd_settings{Plugins}}) if $postfwd_settings{Plugins};
 | 
						get_plugins (@{$postfwd_settings{Plugins}}) if $postfwd_settings{Plugins};
 | 
				
			||||||
	read_config(1);
 | 
						read_config(1);
 | 
				
			||||||
| 
						 | 
					@ -3280,7 +3320,8 @@ die "master-daemon: should never see me!\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# cleanup children and files and terminate
 | 
					# cleanup children and files and terminate
 | 
				
			||||||
sub end_program {
 | 
					sub end_program {
 | 
				
			||||||
	local $SIG{TERM} = 'IGNORE';
 | 
						# ignore further TERM signals
 | 
				
			||||||
 | 
						$SIG{TERM} = 'IGNORE';
 | 
				
			||||||
	if ($postfwd_settings{summary}) {
 | 
						if ($postfwd_settings{summary}) {
 | 
				
			||||||
		undef $postfwd_settings{syslog}{noidlestats};
 | 
							undef $postfwd_settings{syslog}{noidlestats};
 | 
				
			||||||
		log_stats();
 | 
							log_stats();
 | 
				
			||||||
| 
						 | 
					@ -3445,6 +3486,8 @@ B<postfwd2> [OPTIONS] [SOURCE1, SOURCE2, ...]
 | 
				
			||||||
            --keep_rates		do not clear rate limit counters on reload
 | 
					            --keep_rates		do not clear rate limit counters on reload
 | 
				
			||||||
            --save_rates <file>		save and load rate limits on disk
 | 
					            --save_rates <file>		save and load rate limits on disk
 | 
				
			||||||
	    --fast_limit_evaluation	evaluate rate limits before ruleset is parsed
 | 
						    --fast_limit_evaluation	evaluate rate limits before ruleset is parsed
 | 
				
			||||||
 | 
					                                        (please note the limitations)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Plugins:
 | 
						Plugins:
 | 
				
			||||||
	    --plugins <file>            loads postfwd plugins from file
 | 
						    --plugins <file>            loads postfwd plugins from file
 | 
				
			||||||
| 
						 | 
					@ -3527,6 +3570,8 @@ The way how request items are compared to the ruleset can be influenced in the f
 | 
				
			||||||
	 ITEM == VALUE                true if ITEM equals VALUE
 | 
						 ITEM == VALUE                true if ITEM equals VALUE
 | 
				
			||||||
	 ITEM => VALUE                true if ITEM >= VALUE
 | 
						 ITEM => VALUE                true if ITEM >= VALUE
 | 
				
			||||||
	 ITEM =< VALUE                true if ITEM <= VALUE
 | 
						 ITEM =< VALUE                true if ITEM <= VALUE
 | 
				
			||||||
 | 
						 ITEM >  VALUE                true if ITEM >  VALUE
 | 
				
			||||||
 | 
						 ITEM <  VALUE                true if ITEM <  VALUE
 | 
				
			||||||
	 ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
						 ITEM =~ VALUE                true if ITEM ~= /^VALUE$/i
 | 
				
			||||||
	 ITEM != VALUE                false if ITEM equals VALUE
 | 
						 ITEM != VALUE                false if ITEM equals VALUE
 | 
				
			||||||
	 ITEM !> VALUE                false if ITEM >= VALUE
 | 
						 ITEM !> VALUE                false if ITEM >= VALUE
 | 
				
			||||||
| 
						 | 
					@ -3837,7 +3882,7 @@ Files can refer to other files. The following is valid.
 | 
				
			||||||
	-- FILE /etc/postfwd/clients_west.cf --
 | 
						-- FILE /etc/postfwd/clients_west.cf --
 | 
				
			||||||
	192.168.3.0/24
 | 
						192.168.3.0/24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Remind that there is currently no loop detection (/a/file calls /a/file) and that this feature is only available
 | 
					Note that there is currently no loop detection (/a/file calls /a/file) and that this feature is only available
 | 
				
			||||||
with postfwd1 v1.15 and postfwd2 v0.18 and higher.
 | 
					with postfwd1 v1.15 and postfwd2 v0.18 and higher.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3896,7 +3941,7 @@ postfwd2 actions control the behaviour of the program. Currently you can specify
 | 
				
			||||||
	this command creates a counter for the given <item>, which will be increased any time a request
 | 
						this command creates a counter for the given <item>, which will be increased any time a request
 | 
				
			||||||
	containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
						containing it arrives. if it exceeds <max> within <time> seconds it will return <action> to postfix.
 | 
				
			||||||
	rate counters are very fast as they are executed before the ruleset is parsed.
 | 
						rate counters are very fast as they are executed before the ruleset is parsed.
 | 
				
			||||||
	please note that <action> is currently limited to postfix actions (no postfwd actions)!
 | 
						please note that <action> was limited to postfix actions (no postfwd actions) for postfwd versions <1.33!
 | 
				
			||||||
	    # no more than 3 requests per 5 minutes
 | 
						    # no more than 3 requests per 5 minutes
 | 
				
			||||||
	    # from the same "unknown" client
 | 
						    # from the same "unknown" client
 | 
				
			||||||
	    id=RATE01 ;  client_name==unknown
 | 
						    id=RATE01 ;  client_name==unknown
 | 
				
			||||||
| 
						 | 
					@ -3919,6 +3964,11 @@ postfwd2 actions control the behaviour of the program. Currently you can specify
 | 
				
			||||||
	   id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address==!!(10.1.1.1)
 | 
						   id=RCPT01 ;  protocol_state==END-OF-MESSAGE ;  client_address==!!(10.1.1.1)
 | 
				
			||||||
	      action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)
 | 
						      action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rate5321,size5321,rcpt5321 (<item>/<max>/<time>/<action>)
 | 
				
			||||||
 | 
					        same as the corresponding non-5321 functions, with the difference that the localpart of
 | 
				
			||||||
 | 
					        sender oder recipient addresses are evaluated case-sensitive according to rfc5321. That
 | 
				
			||||||
 | 
						means that requests from bob@example.local and BoB@example.local will be treated differently
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ask (<addr>:<port>[:<ignore>])
 | 
						ask (<addr>:<port>[:<ignore>])
 | 
				
			||||||
	allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
						allows to delegate the policy decision to another policy service (e.g. postgrey). the first
 | 
				
			||||||
	and the second argument (address and port) are mandatory. a third optional argument may be
 | 
						and the second argument (address and port) are mandatory. a third optional argument may be
 | 
				
			||||||
| 
						 | 
					@ -3930,10 +3980,16 @@ postfwd2 actions control the behaviour of the program. Currently you can specify
 | 
				
			||||||
	   id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)
 | 
						   id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mail(server/helo/from/to/subject/body)
 | 
					        mail(server/helo/from/to/subject/body)
 | 
				
			||||||
 | 
						This command is deprecated. You should try to use the sendmail() action instead.
 | 
				
			||||||
        Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
					        Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
 | 
				
			||||||
        This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
					        This basically performs a telnet. No authentication or TLS are available. Additionally it does
 | 
				
			||||||
        not track notification state and will notify you any time, the corresponding rule hits.
 | 
					        not track notification state and will notify you any time, the corresponding rule hits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sendmail(sendmail-path::from::to::subject::body)
 | 
				
			||||||
 | 
						Mail command, that uses an existing sendmail binary and sends a message with the given arguments.
 | 
				
			||||||
 | 
						LIMITATIONS: The command does not track notification state and will notify you any time, the
 | 
				
			||||||
 | 
						corresponding rule hits (which could mean 100 mails for a mail with 100 recipients at RCPT stage).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wait (<delay>)
 | 
						wait (<delay>)
 | 
				
			||||||
	pauses the program execution for <delay> seconds. use this for
 | 
						pauses the program execution for <delay> seconds. use this for
 | 
				
			||||||
	delaying or throtteling connections.
 | 
						delaying or throtteling connections.
 | 
				
			||||||
| 
						 | 
					@ -4091,6 +4147,10 @@ will be used.
 | 
				
			||||||
					$myresult = ($myitem <= $val);
 | 
										$myresult = ($myitem <= $val);
 | 
				
			||||||
				} elsif ($cmp eq '=>') {
 | 
									} elsif ($cmp eq '=>') {
 | 
				
			||||||
					$myresult = ($myitem >= $val);
 | 
										$myresult = ($myitem >= $val);
 | 
				
			||||||
 | 
									} elsif ($cmp eq '<') {
 | 
				
			||||||
 | 
										$myresult = ($myitem < $val);
 | 
				
			||||||
 | 
									} elsif ($cmp eq '>') {
 | 
				
			||||||
 | 
										$myresult = ($myitem > $val);
 | 
				
			||||||
				} elsif ($cmp eq '!=') {
 | 
									} elsif ($cmp eq '!=') {
 | 
				
			||||||
					$myresult = not($myitem == $val);
 | 
										$myresult = not($myitem == $val);
 | 
				
			||||||
				} elsif ($cmp eq '!<') {
 | 
									} elsif ($cmp eq '!<') {
 | 
				
			||||||
| 
						 | 
					@ -4122,15 +4182,15 @@ continue or to stop parsing the ruleset.
 | 
				
			||||||
			# note(<logstring>) command
 | 
								# note(<logstring>) command
 | 
				
			||||||
			"note"  => sub {
 | 
								"note"  => sub {
 | 
				
			||||||
				my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
									my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
				my($myaction) = $default_action; my($stop) = 0;
 | 
									my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
				mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
									log_info "[RULES] ".$myline." - note: ".$myarg if $myarg;
 | 
				
			||||||
				return ($stop,$index,$myaction,$myline,%request);
 | 
									return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
			# skips next <myarg> rules
 | 
								# skips next <myarg> rules
 | 
				
			||||||
        		"skip" => sub {
 | 
					        		"skip" => sub {
 | 
				
			||||||
				my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
									my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
				my($myaction) = $default_action; my($stop) = 0;
 | 
									my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
				$index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
									$index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
 | 
				
			||||||
				return ($stop,$index,$myaction,$myline,%request);
 | 
									return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
        		},
 | 
					        		},
 | 
				
			||||||
| 
						 | 
					@ -4138,8 +4198,8 @@ continue or to stop parsing the ruleset.
 | 
				
			||||||
			# dumps current request contents to syslog
 | 
								# dumps current request contents to syslog
 | 
				
			||||||
        		"dumprequest" => sub {
 | 
					        		"dumprequest" => sub {
 | 
				
			||||||
				my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
									my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
 | 
				
			||||||
				my($myaction) = $default_action; my($stop) = 0;
 | 
									my($myaction) = 'dunno'; my($stop) = 0;
 | 
				
			||||||
				map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
									map { log_info "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
 | 
				
			||||||
				return ($stop,$index,$myaction,$myline,%request);
 | 
									return ($stop,$index,$myaction,$myline,%request);
 | 
				
			||||||
        		},
 | 
					        		},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4382,6 +4442,9 @@ These parameters influence the way postfwd2 is working. Any of them can be combi
 | 
				
			||||||
	before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
						before consulting the ruleset. This mode was the default behaviour until v1.30.
 | 
				
			||||||
	With this mode rate limits will be faster, but also eventually set up
 | 
						With this mode rate limits will be faster, but also eventually set up
 | 
				
			||||||
	whitelisting-rules within the ruleset might not work as expected.
 | 
						whitelisting-rules within the ruleset might not work as expected.
 | 
				
			||||||
 | 
					        LIMITATIONS: This option does not allow nested postfwd commands like
 | 
				
			||||||
 | 
					                action=rate(sender/3/60/wait(3))
 | 
				
			||||||
 | 
					        This option doe not work with the strict-rfc5321 rate() functions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
I<Informational arguments>
 | 
					I<Informational arguments>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue