mantools/postlink, proto/SMTPD_POLICY_README.html,
proto/postconf.proto, smtpd/smtpd.c, smtpd/smtpd_check.c,
util/attr_clnt.[hc].
+
+20140701
+
+ Cleanup: documented how Postfix maintains dictionary
+ provenance. Provenance matters: for example, the owner UID
+ of an aliases(5) database file determines the execution
+ privileges for delivery to |command or /file/name. Refined
+ the algorithm that computes the provenance of a pipemap,
+ based on the provenance of its constituent lookup tables.
+ Files: util/dict.[hc], util/dict_pipe.c.
+
+ Cleanup: made mail_spool_directory configurable with "make
+ makefiles mail_spool_directory=/path/name". This allows
+ Postfix to be built without any pathnames that reference
+ system directories. This is useful for testing and sandboxing.
+ Files: global/mail_params.h, makedefs.
+
+ Cleanup: configurable attr_clnt(3) retry strategy (try limit
+ and retry delay). Files: util/attr_clnt.[hc].
+
+ Feature: control over SMTPD policy lookup error handling:
+ smtpd_policy_service_try_limit, smtpd_policy_service_retry_delay,
+ smtpd_policy_service_default_action determine how many times
+ to try to send a policy request before giving up, the delay
+ before resending a failed policy request, and a default
+ action when giving up. The defaults are backwards-compatible.
+ Files: global/mail_params.h, mantools/postlink,
+ proto/postconf.proto, smtpd/smtpd.c, smtpd/smtpd_check.c.
|_____________________|____________________|
|html_directory |no |
|_____________________|____________________|
+ |mail_spool_directory |/var/mail |
+ |_____________________|____________________|
|mailq_path |/usr/bin/mailq |
|_____________________|____________________|
|manpage_directory |/usr/local/man |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|html_directory |no |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+ |mail_spool_directory |/var/mail |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|mailq_path |/usr/bin/mailq |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|manpage_directory |/usr/local/man |
Configuration parameters that control the client side of the policy delegation
protocol:
+ * smtpd_policy_service_default_action (default: 451 4.3.5 Server
+ configuration problem): The default action when an SMTPD policy service
+ request fails. Available with Postfix 2.12 and later.
+
* smtpd_policy_service_max_idle (default: 300s): The amount of time before
the Postfix SMTP server closes an unused policy client connection.
* smtpd_policy_service_max_ttl (default: 1000s): The amount of time before
the Postfix SMTP server closes an active policy client connection.
+ * smtpd_policy_service_request_limit (default: 0): The maximal number of
+ requests per policy connection, or zero (no limit). Available with Postfix
+ 2.12 and later.
+
* smtpd_policy_service_timeout (default: 100s): The time limit to connect to,
send to or receive from a policy server.
- * smtpd_policy_service_request_limit (default: 0): The maximal number of
- requests per policy connection, or zero (no limit).
+ * smtpd_policy_service_try_limit (default: 2): The maximal number of attempts
+ to send an SMTPD policy service request before giving up. Available with
+ Postfix 2.12 and later.
+
+ * smtpd_policy_service_retry_delay (default: 1s): The delay between attempts
+ to resend a failed SMTPD policy service request. Available with Postfix
+ 2.12 and later.
Configuration parameters that control the server side of the policy delegation
protocol:
<tr> <td><a href="postconf.5.html#html_directory">html_directory</a></td> <td>no</td> </tr>
+<tr> <td><a href="postconf.5.html#mail_spool_directory">mail_spool_directory</a></td> <td>/var/mail</td> </tr>
+
<tr> <td><a href="postconf.5.html#mailq_path">mailq_path</a></td> <td>/usr/bin/mailq</td> </tr>
<tr> <td><a href="postconf.5.html#manpage_directory">manpage_directory</a></td> <td>/usr/local/man</td> </tr>
<ul>
+<li> <p> <a href="postconf.5.html#smtpd_policy_service_default_action">smtpd_policy_service_default_action</a> (default: 451 4.3.5
+Server configuration problem): The default action when an SMTPD
+policy service request fails. Available with Postfix 2.12 and
+later. </p>
+
<li> <p> <a href="postconf.5.html#smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a> (default: 300s): The amount
of time before the Postfix SMTP server closes an unused policy
client connection. </p>
of time before the Postfix SMTP server closes an active policy
client connection. </p>
+<li> <p> <a href="postconf.5.html#smtpd_policy_service_request_limit">smtpd_policy_service_request_limit</a> (default: 0): The maximal
+number of requests per policy connection, or zero (no limit).
+Available with Postfix 2.12 and later. </p>
+
<li> <p> <a href="postconf.5.html#smtpd_policy_service_timeout">smtpd_policy_service_timeout</a> (default: 100s): The time
limit to connect to, send to or receive from a policy server. </p>
-<li> <p> <a href="postconf.5.html#smtpd_policy_service_request_limit">smtpd_policy_service_request_limit</a> (default: 0): The maximal
-number of requests per policy connection, or zero (no limit). </p>
+<li> <p> <a href="postconf.5.html#smtpd_policy_service_try_limit">smtpd_policy_service_try_limit</a> (default: 2): The maximal
+number of attempts to send an SMTPD policy service request before
+giving up. Available with Postfix 2.12 and later. </p>
+
+<li> <p> <a href="postconf.5.html#smtpd_policy_service_retry_delay">smtpd_policy_service_retry_delay</a> (default: 1s): The delay
+between attempts to resend a failed SMTPD policy service request.
+Available with Postfix 2.12 and later. </p>
</ul>
"no". </p>
+</DD>
+
+<DT><b><a name="smtpd_policy_service_default_action">smtpd_policy_service_default_action</a>
+(default: 451 4.3.5 Server configuration problem)</b></DT><DD>
+
+<p> The default action when an SMTPD policy service request fails.
+Specify "DUNNO" to behave as if the failed SMTPD policy service
+request was not sent, and to continue processing other access
+restrictions, if any. </p>
+
+<p> Limitations: </p>
+
+<ul>
+
+<li> <p> This parameter may specify any value that would be a valid
+SMTPD policy server response (or <a href="access.5.html">access(5)</a> map lookup result). An
+<a href="access.5.html">access(5)</a> map or policy server in this parameter value may need to
+be declared in advance with a restriction_class setting. </p>
+
+<li> <p> If the specified action invokes another <a href="postconf.5.html#check_policy_service">check_policy_service</a>
+request, that request will have the built-in default action. </p>
+
+</ul>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+
</DD>
<DT><b><a name="smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a>
(default: 0)</b></DT><DD>
<p>
-The maximal number of requests per Postfix SMTP server policy
-connection, or zero (no limit). Once a connection reaches this
-limit, the connection is closed and the next request will be sent
-over a new connection. This is a workaround to avoid error-recovery
-delays with policy servers that cannot maintain a persistent
-connection.
+The maximal number of requests per SMTPD policy service connection,
+or zero (no limit). Once a connection reaches this limit, the
+connection is closed and the next request will be sent over a new
+connection. This is a workaround to avoid error-recovery delays
+with policy servers that cannot maintain a persistent connection.
</p>
<p>
</p>
+</DD>
+
+<DT><b><a name="smtpd_policy_service_retry_delay">smtpd_policy_service_retry_delay</a>
+(default: 1s)</b></DT><DD>
+
+<p> The delay between attempts to resend a failed SMTPD policy
+service request. Specify a value greater than zero. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+
</DD>
<DT><b><a name="smtpd_policy_service_timeout">smtpd_policy_service_timeout</a>
(default: 100s)</b></DT><DD>
<p>
-The time limit for connecting to, writing to or receiving from a
+The time limit for connecting to, writing to, or receiving from a
delegated SMTPD policy server.
</p>
</p>
+</DD>
+
+<DT><b><a name="smtpd_policy_service_try_limit">smtpd_policy_service_try_limit</a>
+(default: 2)</b></DT><DD>
+
+<p> The maximal number of attempts to send an SMTPD policy service
+request before giving up. Specify a value greater than zero. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+
</DD>
<DT><b><a name="smtpd_proxy_ehlo">smtpd_proxy_ehlo</a>
is closed.
<b><a href="postconf.5.html#smtpd_policy_service_timeout">smtpd_policy_service_timeout</a> (100s)</b>
- The time limit for connecting to, writing to or receiving from a
- delegated SMTPD policy server.
+ The time limit for connecting to, writing to, or receiving from
+ a delegated SMTPD policy server.
Available in Postfix version 2.12 and later:
+ <b><a href="postconf.5.html#smtpd_policy_service_default_action">smtpd_policy_service_default_action</a> (451 4.3.5 Server configuration</b>
+ <b>problem)</b>
+ The default action when an SMTPD policy service request fails.
+
<b><a href="postconf.5.html#smtpd_policy_service_request_limit">smtpd_policy_service_request_limit</a> (0)</b>
- The maximal number of requests per Postfix SMTP server policy
- connection, or zero (no limit).
+ The maximal number of requests per SMTPD policy service connec-
+ tion, or zero (no limit).
+
+ <b><a href="postconf.5.html#smtpd_policy_service_try_limit">smtpd_policy_service_try_limit</a> (2)</b>
+ The maximal number of attempts to send an SMTPD policy service
+ request before giving up.
+
+ <b><a href="postconf.5.html#smtpd_policy_service_retry_delay">smtpd_policy_service_retry_delay</a> (1s)</b>
+ The delay between attempts to resend a failed SMTPD policy ser-
+ vice request.
<b>ACCESS CONTROLS</b>
The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to all the SMTP
#
# command_directory config_directory daemon_directory
# data_directory default_database_type html_directory
-# mailq_path manpage_directory meta_directory newaliases_path
-# queue_directory readme_directory sendmail_path shlib_directory
+# mail_spool_directory mailq_path manpage_directory meta_directory
+# newaliases_path queue_directory readme_directory sendmail_path
+# shlib_directory
#
# See the postconf(5) manpage for a description of these
# parameters.
config_directory_macro=DEF_CONFIG_DIR
daemon_directory_macro=DEF_DAEMON_DIR
data_directory_macro=DEF_DATA_DIR
+mail_spool_directory_macro=DEF_MAIL_SPOOL_DIR
mailq_path_macro=DEF_MAILQ_PATH
meta_directory_macro=DEF_META_DIR
newaliases_path_macro=DEF_NEWALIAS_PATH
# Instead, build with "dynamicmaps=no" and "shared=no" as appropriate.
for parm_name in command_directory config_directory daemon_directory \
- data_directory mailq_path meta_directory newaliases_path \
- queue_directory sendmail_path shlib_directory
+ data_directory mail_spool_directory mailq_path meta_directory \
+ newaliases_path queue_directory sendmail_path shlib_directory
do
eval parm_val=\"\$$parm_name\"
eval parm_macro=\"\$${parm_name}_macro\"
This feature is available in Postfix 2.9 and later. With older
Postfix releases, the behavior is as if this parameter is set to
"no".
+.SH smtpd_policy_service_default_action (default: 451 4.3.5 Server configuration problem)
+The default action when an SMTPD policy service request fails.
+Specify "DUNNO" to behave as if the failed SMTPD policy service
+request was not sent, and to continue processing other access
+restrictions, if any.
+.PP
+Limitations:
+.IP \(bu
+This parameter may specify any value that would be a valid
+SMTPD policy server response (or \fBaccess\fR(5) map lookup result). An
+\fBaccess\fR(5) map or policy server in this parameter value may need to
+be declared in advance with a restriction_class setting.
+.IP \(bu
+If the specified action invokes another check_policy_service
+request, that request will have the built-in default action.
+.br
+.PP
+This feature is available in Postfix 2.12 and later.
.SH smtpd_policy_service_max_idle (default: 300s)
The time after which an idle SMTPD policy service connection is
closed.
.PP
This feature is available in Postfix 2.1 and later.
.SH smtpd_policy_service_request_limit (default: 0)
-The maximal number of requests per Postfix SMTP server policy
-connection, or zero (no limit). Once a connection reaches this
-limit, the connection is closed and the next request will be sent
-over a new connection. This is a workaround to avoid error-recovery
-delays with policy servers that cannot maintain a persistent
-connection.
+The maximal number of requests per SMTPD policy service connection,
+or zero (no limit). Once a connection reaches this limit, the
+connection is closed and the next request will be sent over a new
+connection. This is a workaround to avoid error-recovery delays
+with policy servers that cannot maintain a persistent connection.
+.PP
+This feature is available in Postfix 2.12 and later.
+.SH smtpd_policy_service_retry_delay (default: 1s)
+The delay between attempts to resend a failed SMTPD policy
+service request. Specify a value greater than zero.
.PP
This feature is available in Postfix 2.12 and later.
.SH smtpd_policy_service_timeout (default: 100s)
-The time limit for connecting to, writing to or receiving from a
+The time limit for connecting to, writing to, or receiving from a
delegated SMTPD policy server.
.PP
This feature is available in Postfix 2.1 and later.
+.SH smtpd_policy_service_try_limit (default: 2)
+The maximal number of attempts to send an SMTPD policy service
+request before giving up. Specify a value greater than zero.
+.PP
+This feature is available in Postfix 2.12 and later.
.SH smtpd_proxy_ehlo (default: $myhostname)
How the Postfix SMTP server announces itself to the proxy filter.
By default, the Postfix hostname is used.
The time after which an active SMTPD policy service connection is
closed.
.IP "\fBsmtpd_policy_service_timeout (100s)\fR"
-The time limit for connecting to, writing to or receiving from a
+The time limit for connecting to, writing to, or receiving from a
delegated SMTPD policy server.
.PP
Available in Postfix version 2.12 and later:
+.IP "\fBsmtpd_policy_service_default_action (451 4.3.5 Server configuration problem)\fR"
+The default action when an SMTPD policy service request fails.
.IP "\fBsmtpd_policy_service_request_limit (0)\fR"
-The maximal number of requests per Postfix SMTP server policy
-connection, or zero (no limit).
+The maximal number of requests per SMTPD policy service connection,
+or zero (no limit).
+.IP "\fBsmtpd_policy_service_try_limit (2)\fR"
+The maximal number of attempts to send an SMTPD policy service
+request before giving up.
+.IP "\fBsmtpd_policy_service_retry_delay (1s)\fR"
+The delay between attempts to resend a failed SMTPD policy
+service request.
.SH "ACCESS CONTROLS"
.na
.nf
s;\bsmtpd_policy_service_max_ttl\b;<a href="postconf.5.html#smtpd_policy_service_max_ttl">$&</a>;g;
s;\bsmtpd_policy_service_timeout\b;<a href="postconf.5.html#smtpd_policy_service_timeout">$&</a>;g;
s;\bsmtpd_policy_service_request_limit\b;<a href="postconf.5.html#smtpd_policy_service_request_limit">$&</a>;g;
+ s;\bsmtpd_policy_service_default_action\b;<a href="postconf.5.html#smtpd_policy_service_default_action">$&</a>;g;
+ s;\bsmtpd_policy_service_try_limit\b;<a href="postconf.5.html#smtpd_policy_service_try_limit">$&</a>;g;
+ s;\bsmtpd_policy_service_retry_delay\b;<a href="postconf.5.html#smtpd_policy_service_retry_delay">$&</a>;g;
s;\bsmtpd_proxy_ehlo\b;<a href="postconf.5.html#smtpd_proxy_ehlo">$&</a>;g;
s;\bsmtpd_proxy_filter\b;<a href="postconf.5.html#smtpd_proxy_filter">$&</a>;g;
s;\bsmtpd_proxy_timeout\b;<a href="postconf.5.html#smtpd_proxy_timeout">$&</a>;g;
<tr> <td>html_directory</td> <td>no</td> </tr>
+<tr> <td>mail_spool_directory</td> <td>/var/mail</td> </tr>
+
<tr> <td>mailq_path</td> <td>/usr/bin/mailq</td> </tr>
<tr> <td>manpage_directory</td> <td>/usr/local/man</td> </tr>
<ul>
+<li> <p> smtpd_policy_service_default_action (default: 451 4.3.5
+Server configuration problem): The default action when an SMTPD
+policy service request fails. Available with Postfix 2.12 and
+later. </p>
+
<li> <p> smtpd_policy_service_max_idle (default: 300s): The amount
of time before the Postfix SMTP server closes an unused policy
client connection. </p>
of time before the Postfix SMTP server closes an active policy
client connection. </p>
+<li> <p> smtpd_policy_service_request_limit (default: 0): The maximal
+number of requests per policy connection, or zero (no limit).
+Available with Postfix 2.12 and later. </p>
+
<li> <p> smtpd_policy_service_timeout (default: 100s): The time
limit to connect to, send to or receive from a policy server. </p>
-<li> <p> smtpd_policy_service_request_limit (default: 0): The maximal
-number of requests per policy connection, or zero (no limit). </p>
+<li> <p> smtpd_policy_service_try_limit (default: 2): The maximal
+number of attempts to send an SMTPD policy service request before
+giving up. Available with Postfix 2.12 and later. </p>
+
+<li> <p> smtpd_policy_service_retry_delay (default: 1s): The delay
+between attempts to resend a failed SMTPD policy service request.
+Available with Postfix 2.12 and later. </p>
</ul>
%PARAM smtpd_policy_service_timeout 100s
<p>
-The time limit for connecting to, writing to or receiving from a
+The time limit for connecting to, writing to, or receiving from a
delegated SMTPD policy server.
</p>
%PARAM smtpd_policy_service_request_limit 0
<p>
-The maximal number of requests per Postfix SMTP server policy
-connection, or zero (no limit). Once a connection reaches this
-limit, the connection is closed and the next request will be sent
-over a new connection. This is a workaround to avoid error-recovery
-delays with policy servers that cannot maintain a persistent
-connection.
+The maximal number of requests per SMTPD policy service connection,
+or zero (no limit). Once a connection reaches this limit, the
+connection is closed and the next request will be sent over a new
+connection. This is a workaround to avoid error-recovery delays
+with policy servers that cannot maintain a persistent connection.
</p>
<p>
command line. </p>
<p> This feature is available in Postfix 2.12 and later. </p>
+
+%PARAM smtpd_policy_service_default_action 451 4.3.5 Server configuration problem
+
+<p> The default action when an SMTPD policy service request fails.
+Specify "DUNNO" to behave as if the failed SMTPD policy service
+request was not sent, and to continue processing other access
+restrictions, if any. </p>
+
+<p> Limitations: </p>
+
+<ul>
+
+<li> <p> This parameter may specify any value that would be a valid
+SMTPD policy server response (or access(5) map lookup result). An
+access(5) map or policy server in this parameter value may need to
+be declared in advance with a restriction_class setting. </p>
+
+<li> <p> If the specified action invokes another check_policy_service
+request, that request will have the built-in default action. </p>
+
+</ul>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+%PARAM smtpd_policy_service_try_limit 2
+
+<p> The maximal number of attempts to send an SMTPD policy service
+request before giving up. Specify a value greater than zero. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+%PARAM smtpd_policy_service_retry_delay 1s
+
+<p> The delay between attempts to resend a failed SMTPD policy
+service request. Specify a value greater than zero. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
* Local delivery: mailbox delivery.
*/
#define VAR_MAIL_SPOOL_DIR "mail_spool_directory"
+#ifndef DEF_MAIL_SPOOL_DIR
#define DEF_MAIL_SPOOL_DIR _PATH_MAILDIR
+#endif
extern char *var_mail_spool_dir;
#define VAR_HOME_MAILBOX "home_mailbox"
#define DEF_SMTPD_POLICY_TTL "1000s"
extern int var_smtpd_policy_ttl;
+#define VAR_SMTPD_POLICY_TRY_LIMIT "smtpd_policy_service_try_limit"
+#define DEF_SMTPD_POLICY_TRY_LIMIT 2
+extern int var_smtpd_policy_try_limit;
+
+#define VAR_SMTPD_POLICY_TRY_DELAY "smtpd_policy_service_retry_delay"
+#define DEF_SMTPD_POLICY_TRY_DELAY "1s"
+extern int var_smtpd_policy_try_delay;
+
+#define VAR_SMTPD_POLICY_DEF_ACTION "smtpd_policy_service_default_action"
+#define DEF_SMTPD_POLICY_DEF_ACTION "451 4.3.5 Server configuration problem"
+extern char *var_smtpd_policy_def_action;
+
#define CHECK_POLICY_SERVICE "check_policy_service"
/*
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20140701"
+#define MAIL_RELEASE_DATE "20140703"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT
/* The time after which an active SMTPD policy service connection is
/* closed.
/* .IP "\fBsmtpd_policy_service_timeout (100s)\fR"
-/* The time limit for connecting to, writing to or receiving from a
+/* The time limit for connecting to, writing to, or receiving from a
/* delegated SMTPD policy server.
/* .PP
/* Available in Postfix version 2.12 and later:
+/* .IP "\fBsmtpd_policy_service_default_action (451 4.3.5 Server configuration problem)\fR"
+/* The default action when an SMTPD policy service request fails.
/* .IP "\fBsmtpd_policy_service_request_limit (0)\fR"
-/* The maximal number of requests per Postfix SMTP server policy
-/* connection, or zero (no limit).
+/* The maximal number of requests per SMTPD policy service connection,
+/* or zero (no limit).
+/* .IP "\fBsmtpd_policy_service_try_limit (2)\fR"
+/* The maximal number of attempts to send an SMTPD policy service
+/* request before giving up.
+/* .IP "\fBsmtpd_policy_service_retry_delay (1s)\fR"
+/* The delay between attempts to resend a failed SMTPD policy
+/* service request.
/* ACCESS CONTROLS
/* .ad
/* .fi
char *var_input_transp;
int var_smtpd_policy_tmout;
int var_smtpd_policy_req_limit;
+int var_smtpd_policy_try_limit;
+int var_smtpd_policy_try_delay;
+char *var_smtpd_policy_def_action;
int var_smtpd_policy_idle;
int var_smtpd_policy_ttl;
char *var_xclient_hosts;
VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
#endif
VAR_SMTPD_POLICY_REQ_LIMIT, DEF_SMTPD_POLICY_REQ_LIMIT, &var_smtpd_policy_req_limit, 0, 0,
+ VAR_SMTPD_POLICY_TRY_LIMIT, DEF_SMTPD_POLICY_TRY_LIMIT, &var_smtpd_policy_try_limit, 1, 0,
0,
};
static const CONFIG_TIME_TABLE time_table[] = {
VAR_MILT_MSG_TIME, DEF_MILT_MSG_TIME, &var_milt_msg_time, 1, 0,
VAR_VERIFY_SENDER_TTL, DEF_VERIFY_SENDER_TTL, &var_verify_sender_ttl, 0, 0,
VAR_SMTPD_UPROXY_TMOUT, DEF_SMTPD_UPROXY_TMOUT, &var_smtpd_uproxy_tmout, 1, 0,
+ VAR_SMTPD_POLICY_TRY_DELAY, DEF_SMTPD_POLICY_TRY_DELAY, &var_smtpd_policy_try_delay, 1, 0,
0,
};
static const CONFIG_BOOL_TABLE bool_table[] = {
#endif
VAR_SMTPD_ACL_PERM_LOG, DEF_SMTPD_ACL_PERM_LOG, &var_smtpd_acl_perm_log, 0, 0,
VAR_SMTPD_UPROXY_PROTO, DEF_SMTPD_UPROXY_PROTO, &var_smtpd_uproxy_proto, 0, 0,
+ VAR_SMTPD_POLICY_DEF_ACTION, DEF_SMTPD_POLICY_DEF_ACTION, &var_smtpd_policy_def_action, 1, 0,
0,
};
static const CONFIG_RAW_TABLE raw_table[] = {
var_smtpd_policy_tmout,
var_smtpd_policy_idle,
var_smtpd_policy_ttl);
- attr_clnt_control(client, ATTR_CLNT_CTL_REQ_LIMIT,
- var_smtpd_policy_req_limit, ATTR_CLNT_CTL_END);
+ attr_clnt_control(client,
+ ATTR_CLNT_CTL_REQ_LIMIT, var_smtpd_policy_req_limit,
+ ATTR_CLNT_CTL_TRY_LIMIT, var_smtpd_policy_try_limit,
+ ATTR_CLNT_CTL_TRY_DELAY, var_smtpd_policy_try_delay,
+ ATTR_CLNT_CTL_END);
htable_enter(policy_clnt_table, name, (char *) client);
}
}
ATTR_FLAG_MISSING, /* Reply attributes. */
ATTR_TYPE_STR, MAIL_ATTR_ACTION, action,
ATTR_TYPE_END) != 1) {
- ret = smtpd_check_reject(state, MAIL_ERROR_POLICY,
- 451, "4.3.5",
- "Server configuration problem");
+ NOCLOBBER static int nesting_level = 0;
+ jmp_buf savebuf;
+ int status;
+
+ /*
+ * Safety to prevent recursive execution of the default action.
+ */
+ nesting_level += 1;
+ memcpy(ADDROF(savebuf), ADDROF(smtpd_check_buf), sizeof(savebuf));
+ status = setjmp(smtpd_check_buf);
+ if (status != 0) {
+ nesting_level -= 1;
+ memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf),
+ sizeof(smtpd_check_buf));
+ longjmp(smtpd_check_buf, status);
+ }
+ ret = check_table_result(state, server, nesting_level == 1 ?
+ var_smtpd_policy_def_action :
+ DEF_SMTPD_POLICY_DEF_ACTION,
+ "policy query", reply_name,
+ reply_class, def_acl);
+ nesting_level -= 1;
} else {
/*
/* Specifies alternatives for the attr_plain_print() and
/* attr_plain_scan() functions.
/* .IP "ATTR_CLNT_CTL_REQ_LIMIT(int)"
-/* The maximal number of requests per connection. To enable
-/* the limit, specify a value greater than zero.
+/* The maximal number of requests per connection (default: 0,
+/* i.e. no limit). To enable the limit, specify a value greater
+/* than zero.
+/* .IP "ATTR_CLNT_CTL_TRY_LIMIT(int)"
+/* The maximal number of attempts to send a request before
+/* giving up (default: 2). To disable the limit, specify a
+/* value equal to zero.
+/* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)"
+/* The time in seconds between attempts to send a request
+/* (default: 1). Specify a value greater than zero.
/* DIAGNOSTICS
/* Warnings: communication failure.
/* SEE ALSO
struct ATTR_CLNT {
AUTO_CLNT *auto_clnt;
+ /* Remaining properties are set with attr_clnt_control(). */
ATTR_CLNT_PRINT_FN print;
ATTR_CLNT_SCAN_FN scan;
int req_limit;
int req_count;
+ int try_limit;
+ int try_delay;
};
+#define ATTR_CLNT_DEF_REQ_LIMIT (0) /* default per-session request limit */
+#define ATTR_CLNT_DEF_TRY_LIMIT (2) /* default request (re)try limit */
+#define ATTR_CLNT_DEF_TRY_DELAY (1) /* default request (re)try delay */
+
/* attr_clnt_free - destroy attribute client */
void attr_clnt_free(ATTR_CLNT *client)
client->auto_clnt = auto_clnt_create(service, timeout, max_idle, max_ttl);
client->scan = attr_vscan_plain;
client->print = attr_vprint_plain;
- client->req_limit = 0;
+ client->req_limit = ATTR_CLNT_DEF_REQ_LIMIT;
client->req_count = 0;
+ client->try_limit = ATTR_CLNT_DEF_TRY_LIMIT;
+ client->try_delay = ATTR_CLNT_DEF_TRY_DELAY;
return (client);
}
}
}
}
- if (++count >= 2
+ if ((++count >= client->try_limit && client->try_limit > 0)
|| msg_verbose
|| (errno && errno != EPIPE && errno != ENOENT && errno != ECONNRESET))
msg_warn("problem talking to server %s: %m",
auto_clnt_name(client->auto_clnt));
/* Finalize argument lists before returning. */
- if (count >= 2) {
+ if (count >= client->try_limit && client->try_limit > 0) {
ret = -1;
break;
}
- sleep(1); /* XXX make configurable */
+ sleep(client->try_delay);
auto_clnt_recover(client->auto_clnt);
client->req_count = 0;
}
break;
case ATTR_CLNT_CTL_REQ_LIMIT:
client->req_limit = va_arg(ap, int);
+ if (client->req_limit < 0)
+ msg_panic("%s: bad request limit: %d",
+ myname, client->req_limit);
if (msg_verbose)
- msg_info("%s: new request limit %d", myname, client->req_limit);
+ msg_info("%s: new request limit %d",
+ myname, client->req_limit);
+ break;
+ case ATTR_CLNT_CTL_TRY_LIMIT:
+ client->try_limit = va_arg(ap, int);
+ if (client->try_limit < 0)
+ msg_panic("%s: bad retry limit: %d", myname, client->try_limit);
+ if (msg_verbose)
+ msg_info("%s: new retry limit %d", myname, client->try_limit);
+ break;
+ case ATTR_CLNT_CTL_TRY_DELAY:
+ client->try_delay = va_arg(ap, int);
+ if (client->try_delay <= 0)
+ msg_panic("%s: bad retry delay: %d", myname, client->try_delay);
+ if (msg_verbose)
+ msg_info("%s: new retry delay %d", myname, client->try_delay);
break;
default:
msg_panic("%s: bad name %d", myname, name);
extern void attr_clnt_control(ATTR_CLNT *, int, ...);
#define ATTR_CLNT_CTL_END 0
-#define ATTR_CLNT_CTL_PROTO 1
-#define ATTR_CLNT_CTL_REQ_LIMIT 2
+#define ATTR_CLNT_CTL_PROTO 1 /* print/scan functions */
+#define ATTR_CLNT_CTL_REQ_LIMIT 2 /* requests per connection */
+#define ATTR_CLNT_CTL_TRY_LIMIT 3 /* attempts per request */
+#define ATTR_CLNT_CTL_TRY_DELAY 4 /* pause between requests */
/* LICENSE
/* .ad
/* const char *dict_name;
/*
/* const char *dict_changed_name()
+/*
+/* void DICT_OWNER_AGGREGATE_INIT(aggregate)
+/* DICT_OWNER aggregate;
+/*
+/* void DICT_OWNER_AGGREGATE_UPDATE(aggregate, source)
+/* DICT_OWNER aggregate;
+/* DICT_OWNER source;
/* AUXILIARY FUNCTIONS
/* int dict_load_file_xt(dict_name, path)
/* const char *dict_name;
/*
/* dict_flags_mask() returns the bitmask for the specified
/* comma/space-separated dictionary flag names.
+/* TRUST AND PROVENANCE
+/* .ad
+/* .fi
+/* Each dictionary has an owner attribute that contains (status,
+/* uid) information about the owner of a dictionary. The
+/* status is one of the following:
+/* .IP DICT_OWNER_TRUSTED
+/* The dictionary is owned by a trusted user. The uid is zero,
+/* and specifies a UNIX user ID.
+/* .IP DICT_OWNER_UNTRUSTED
+/* The dictionary is owned by an untrusted user. The uid is
+/* non-zero, and specifies a UNIX user ID.
+/* .IP DICT_OWNER_UNKNOWN
+/* The dictionary is owned by an unspecified user. For example,
+/* the origin is unauthenticated, or different parts of a
+/* dictionary aggregate (see below) are owned by different
+/* untrusted users. The uid is non-zero and does not specify
+/* a UNIX user ID.
+/* .PP
+/* Note that dictionary ownership does not necessarily imply
+/* ownership of lookup results. For example, a PCRE table may
+/* be owned by the trusted root user, but the result of $number
+/* expansion can contain data from an arbitrary remote SMTP
+/* client. See dict_open(3) for how to disallow $number
+/* expansions with security-sensitive operations.
+/*
+/* Two macros are available to help determine the provenance
+/* and trustworthiness of a dictionary aggregate. The macros
+/* are unsafe because they may evaluate arguments more than
+/* once.
+/*
+/* DICT_OWNER_AGGREGATE_INIT() initialize aggregate owner
+/* attributes to the highest trust level.
+/*
+/* DICT_OWNER_AGGREGATE_UPDATE() updates the aggregate owner
+/* attributes with the attributes of the specified source, and
+/* reduces the aggregate trust level as appropriate.
/* SEE ALSO
/* htable(3)
/* BUGS
uid_t uid; /* use only if status == UNTRUSTED */
} DICT_OWNER;
+ /*
+ * Note that trust levels are not in numerical order.
+ */
#define DICT_OWNER_UNKNOWN (-1) /* ex: unauthenticated tcp, proxy */
#define DICT_OWNER_TRUSTED (!1) /* ex: root-owned config file */
#define DICT_OWNER_UNTRUSTED (!0) /* ex: non-root config file */
-#define DICT_OWNER_AGGREGATE(dst, src) do { \
- if ((src).status == DICT_OWNER_UNKNOWN) { \
- (dst).status = (src).status; \
- (dst).uid = ~0; \
- } else if ((src).status == DICT_OWNER_UNTRUSTED) { \
- (dst).status = (src).status; \
+ /*
+ * When combining tables with different provenance, we initialize to the
+ * highest trust level, and remember the lowest trust level that we find
+ * during aggregation. If we combine tables that are owned by different
+ * untrusted users, the resulting provenance is "unknown".
+ */
+#define DICT_OWNER_AGGREGATE_INIT(dst) { \
+ (dst).status = DICT_OWNER_TRUSTED; \
+ (dst).uid = 0; \
+ } while (0)
+
+ /*
+ * The following is derived from the 3x3 transition matrix.
+ */
+#define DICT_OWNER_AGGREGATE_UPDATE(dst, src) do { \
+ if ((dst).status == DICT_OWNER_TRUSTED \
+ || (src).status == DICT_OWNER_UNKNOWN) { \
+ (dst) = (src); \
+ } else if ((dst).status == (src).status \
+ && (dst).uid != (src).uid) { \
+ (dst).status = DICT_OWNER_UNKNOWN; \
(dst).uid = ~0; \
} \
} while (0)
/* When any table lookup produces no result, the pipeline
/* produces no result.
/*
-/* The ASCII character after "pipemap:" will be used as the
-/* separator between the lookup tables that follow (do not use
-/* space, ",", ":" or non-ASCII).
+/* The first ASCII character after "pipemap:" will be used as
+/* the separator between the lookup tables that follow (do not
+/* use space, ",", ":" or non-ASCII).
/*
/* The open_flags and dict_flags arguments are passed on to
/* the underlying dictionaries.
struct DICT_OWNER aggr_owner;
char delim[2];
-#ifdef DICT_TYPE_PIPE_LEGACY
- msg_warn("obsolete dictionary type: \"%s\"; use \"%s\" instead",
- DICT_TYPE_PIPE_LEGACY, DICT_TYPE_PIPE);
-#endif
-
/*
* Clarity first. Let the optimizer worry about redundant code.
*/
if (*saved_name == 0)
DICT_PIPE_RETURN(dict_surrogate(DICT_TYPE_PIPE, name,
open_flags, dict_flags,
- "bad syntax: \"%s:%s\"; need \"%s:%stype:name%s...\"",
+ "bad syntax: \"%s:%s\"; "
+ "need \"%s:%stype:name%s...\"",
DICT_TYPE_PIPE, name,
DICT_TYPE_PIPE, delim, delim));
* The least-trusted table in the pipeline determines the over-all trust
* level. The first table determines the pattern-matching flags.
*/
- aggr_owner.status = DICT_OWNER_TRUSTED;
- aggr_owner.uid = 0;
+ DICT_OWNER_AGGREGATE_INIT(aggr_owner);
argv = argv_split(saved_name, delim);
for (cpp = argv->argv; (dict_type_name = *cpp) != 0; cpp++) {
if (msg_verbose)
if (strchr(dict_type_name, ':') == 0)
DICT_PIPE_RETURN(dict_surrogate(DICT_TYPE_PIPE, name,
open_flags, dict_flags,
- "bad syntax: \"%s\" in \"%s:%s\"; "
- "need \"type:name\"",
- dict_type_name, DICT_TYPE_PIPE,
- name));
+ "bad syntax: \"%s:%s\"; "
+ "need \"%s:%stype:name%s...\"",
+ DICT_TYPE_PIPE, name,
+ DICT_TYPE_PIPE, delim, delim));
if ((dict = dict_handle(dict_type_name)) == 0)
dict = dict_open(dict_type_name, open_flags, dict_flags);
dict_register(dict_type_name, dict);
- DICT_OWNER_AGGREGATE(aggr_owner, dict->owner);
+ DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
if (cpp == argv->argv)
match_flags = dict->flags & (DICT_FLAG_FIXED | DICT_FLAG_PATTERN);
}
char *saved_name = 0;
char delim[2];
-#ifdef DICT_TYPE_RANDOM_LEGACY
- msg_warn("obsolete dictionary type: \"%s\"; use \"%s\" instead",
- DICT_TYPE_RANDOM_LEGACY, DICT_TYPE_RANDOM);
-#endif
-
/*
* Clarity first. Let the optimizer worry about redundant code.
*/
dict_allow_surrogate = 1;
dict = dict_open(dict_name, open_flags, dict_flags);
dict_register(dict_name, dict);
+ vstream_printf("owner=%s (uid=%ld)\n",
+ dict->owner.status == DICT_OWNER_TRUSTED ? "trusted" :
+ dict->owner.status == DICT_OWNER_UNTRUSTED? "untrusted" :
+ dict->owner.status == DICT_OWNER_UNKNOWN? "unspecified" :
+ "error", (long) dict->owner.uid);
+ vstream_fflush(VSTREAM_OUT);
+
while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
bufp = vstring_str(inbuf);
if (!isatty(0)) {