From: Wietse Venema Date: Mon, 19 Dec 2011 05:00:00 +0000 (-0500) Subject: postfix-2.9-20111219 X-Git-Tag: v2.9.0-RC1~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=297fca9c4c0bf9961a181de4f1e2cac3acfc9f9b;p=thirdparty%2Fpostfix.git postfix-2.9-20111219 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index d2e1c26f5..097a67a2c 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -69,6 +69,7 @@ -TDICT_DBM -TDICT_DEBUG -TDICT_ENV +-TDICT_FAIL -TDICT_HT -TDICT_LDAP -TDICT_MC @@ -161,6 +162,7 @@ -TMASTER_STATUS -TMASTER_STR_WATCH -TMATCH_LIST +-TMATCH_OPS -TMBLOCK -TMBOX -TMILTER diff --git a/postfix/HISTORY b/postfix/HISTORY index 6afc09ae0..ea798e676 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -17372,3 +17372,33 @@ Apologies for any names omitted. Incompatibility: the Postfix SMTP server now always checks the smtpd_sender_login_maps table, even without having "smtpd_sasl_auth_enable = yes" in main.cf. + +20111219 + + Cleanup: the match_list-based primitives now provide an + option to return an error result instead of terminating the + process with a fatal error. Files: util/match_ops.[hc], + util/match_list.c, global/addr_list_match.c, domain_list.c, + string_list.c, namadr_list.c. + + Cleanup: a "fail:" database type that reliably fails all + requests. The lookup table name specifies the internal error + result code. having this table facilitates a systematic + review of all Postfix table lookup error handling. + + Cleanup: trivial-rewrite now "catches" errors with implicit + database lookups in virtual_alias_domains, relay_domains, + virtual_mailbox_domains, just like it already caught explicit + database lookup errors. This means there are fewer occasions + where trivial-rewrite clients will appear to hang. File: + trivial-rewrite/resolve.c. + + Cleanup: a broken relay_domains table would cause many + Postfix processes to terminate with fatal error. Postfix + now logs a warning instead. File: global/flush_clnt.c. + + Cleanup: the Postfix SMTP server now "catches" some of the + errors with implicit database lookups in mynetworks and TLS + client certificate tables, and reports "server configuration + error" instead of terminating with a fatal error. This is + work in progress. Files: smtpd/smtpd.c, smtpd/smtpd_check.c. diff --git a/postfix/README_FILES/DATABASE_README b/postfix/README_FILES/DATABASE_README index dcd395294..4353752c6 100644 --- a/postfix/README_FILES/DATABASE_README +++ b/postfix/README_FILES/DATABASE_README @@ -198,6 +198,10 @@ To find out what database types your Postfix system supports, use the "ppooss eennvviirroonn The UNIX process environment array. The lookup key is the variable name. The lookup table name in "environ:table" is ignored. + ffaaiill (read-write) + A table that reliably fails all requests. The lookup table name + provides the internal error result code. This table exists to simplify + Postfix error tests. hhaasshh An indexed file type based on hashing. This is available only on systems with support for Berkeley DB databases. Database files are diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index ab67e1f75..ae73b5015 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -14,14 +14,14 @@ specifies the release date of a stable release or snapshot release. If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8 before proceeding. -Incompatible changes with snapshot 201112XX +Incompatible changes with snapshot 20111218 =========================================== To support external SASL authentication, the Postfix SMTP server now always checks the smtpd_sender_login_maps table, even without having "smtpd_sasl_auth_enable = yes" in main.cf. -Major changes with snapshot 201112XX +Major changes with snapshot 20111218 ==================================== Support for external SASL authentication via the XCLIENT command. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index c38f721db..4162c84ab 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -7,6 +7,9 @@ Wish list: limits on attribute string length in IPC protocols. 10-20KB seems OK. We could start with limits enabled only in proxymap. + move flush_init() etc. from defer service clients to the + bounce daemon? + Either make all void dict_* operations return an error code, or require that they reset dict_errno on entry, either exit with a fatal error or set dict_errno on error. diff --git a/postfix/html/DATABASE_README.html b/postfix/html/DATABASE_README.html index f394976c5..1beb1c898 100644 --- a/postfix/html/DATABASE_README.html +++ b/postfix/html/DATABASE_README.html @@ -292,6 +292,12 @@ the ".dir" or ".pag" suffix. variable name. The lookup table name in "environ:table" is ignored. +
fail (read-write)
+ +
A table that reliably fails all requests. The lookup table +name provides the internal error result code. This table exists to +simplify Postfix error tests.
+
hash
An indexed file type based on hashing. This is available only diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index cf4086fc7..63d1483e5 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -181,8 +181,13 @@ POSTCONF(1) POSTCONF(1) implemented for testing, someone may find this useful someday. + fail A table that reliably fails all requests. + The lookup table name provides the internal + error result code. This table exists to sim- + plify Postfix error tests. + hash An indexed file type based on hashing. This - is available on systems with support for + is available on systems with support for Berkeley DB databases. internal @@ -190,7 +195,7 @@ POSTCONF(1) POSTCONF(1) tent are lost when a process terminates. ldap (read-only) - Perform lookups using the LDAP protocol. + Perform lookups using the LDAP protocol. This is described in ldap_table(5). memcache (read-write) @@ -198,126 +203,126 @@ POSTCONF(1) POSTCONF(1) This is described in memcache_table(5). mysql (read-only) - Perform lookups using the MYSQL protocol. + Perform lookups using the MYSQL protocol. This is described in mysql_table(5). pcre (read-only) A lookup table based on Perl Compatible Reg- - ular Expressions. The file format is + ular Expressions. The file format is described in pcre_table(5). pgsql (read-only) - Perform lookups using the PostgreSQL proto- + Perform lookups using the PostgreSQL proto- col. This is described in pgsql_table(5). proxy (read-only) - A lookup table that is implemented via the - Postfix proxymap(8) service. The table name + A lookup table that is implemented via the + Postfix proxymap(8) service. The table name syntax is type:name. regexp (read-only) A lookup table based on regular expressions. - The file format is described in regexp_ta- + The file format is described in regexp_ta- ble(5). sdbm An indexed file type based on hashing. This - is available on systems with support for + is available on systems with support for SDBM databases. sqlite (read-only) - Perform lookups from SQLite database files. + Perform lookups from SQLite database files. This is described in sqlite_table(5). static (read-only) - A table that always returns its name as - lookup result. For example, static:foobar - always returns the string foobar as lookup + A table that always returns its name as + lookup result. For example, static:foobar + always returns the string foobar as lookup result. tcp (read-only) Perform lookups using a simple request-reply - protocol that is described in tcp_table(5). + protocol that is described in tcp_table(5). texthash (read-only) - Produces similar results as hash: files, + Produces similar results as hash: files, except that you don't need to run the - postmap(1) command before you can use the - file, and that it does not detect changes + postmap(1) command before you can use the + file, and that it does not detect changes after the file is read. unix (read-only) - A limited way to query the UNIX authentica- + A limited way to query the UNIX authentica- tion database. The following tables are implemented: unix:passwd.byname - The table is the UNIX password data- - base. The key is a login name. The - result is a password file entry in + The table is the UNIX password data- + base. The key is a login name. The + result is a password file entry in passwd(5) format. unix:group.byname The table is the UNIX group database. - The key is a group name. The result - is a group file entry in group(5) + The key is a group name. The result + is a group file entry in group(5) format. - Other table types may exist depending on how Post- + Other table types may exist depending on how Post- fix was built. - -M Show master.cf file contents instead of main.cf - file contents. Specify -Mf to fold long lines for + -M Show master.cf file contents instead of main.cf + file contents. Specify -Mf to fold long lines for human readability. If service ... is specified, only the matching ser- - vices will be output. For example, "postconf -Mf - inet" will output all services that listen on the + vices will be output. For example, "postconf -Mf + inet" will output all services that listen on the network. - Specify zero or more arguments, each with a ser- - vice-type name (inet, unix, fifo, or pass) or with - a service-name.service-type pair, where service- + Specify zero or more arguments, each with a ser- + vice-type name (inet, unix, fifo, or pass) or with + a service-name.service-type pair, where service- name is the first field of a master.cf entry. - This feature is available with Postfix 2.9 and + This feature is available with Postfix 2.9 and later. - -n Print main.cf parameter settings that are explic- - itly specified in main.cf. Specify -nf to fold - long lines for human readability (Postfix 2.9 and + -n Print main.cf parameter settings that are explic- + itly specified in main.cf. Specify -nf to fold + long lines for human readability (Postfix 2.9 and later). -t [template_file] - Display the templates for text that appears at the - beginning of delivery status notification (DSN) + Display the templates for text that appears at the + beginning of delivery status notification (DSN) messages, without expanding $name expressions. - To override the built-in templates, specify a tem- - plate file name at the end of the postconf(1) com- - mand line, or specify a file name in main.cf with + To override the built-in templates, specify a tem- + plate file name at the end of the postconf(1) com- + mand line, or specify a file name in main.cf with the bounce_template_file parameter. To force selection of the built-in templates, spec- - ify an empty template file name on the postconf(1) + ify an empty template file name on the postconf(1) command line (in shell language: ""). - This feature is available with Postfix 2.3 and + This feature is available with Postfix 2.3 and later. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. - -# Edit the main.cf configuration file, and comment + -# Edit the main.cf configuration file, and comment out the parameters given on the postconf(1) command - line, so that those parameters revert to their - default values. The file is copied to a temporary - file then renamed into place. Specify a list of + line, so that those parameters revert to their + default values. The file is copied to a temporary + file then renamed into place. Specify a list of parameter names, not name=value pairs. There is no - postconf(1) command to perform the reverse opera- + postconf(1) command to perform the reverse opera- tion. - This feature is available with Postfix 2.6 and + This feature is available with Postfix 2.6 and later. DIAGNOSTICS @@ -328,18 +333,18 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. bounce_template_file (empty) - Pathname of a configuration file with bounce mes- + Pathname of a configuration file with bounce mes- sage templates. FILES @@ -355,7 +360,7 @@ POSTCONF(1) POSTCONF(1) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/qmqpd.8.html b/postfix/html/qmqpd.8.html index 94eac6a42..47f1c0fbc 100644 --- a/postfix/html/qmqpd.8.html +++ b/postfix/html/qmqpd.8.html @@ -95,17 +95,17 @@ QMQPD(8) QMQPD(8) TARPIT CONTROLS qmqpd_error_delay (1s) - How long the QMQP server will pause before sending - a negative reply to the client. + How long the Postfix QMQP server will pause before + sending a negative reply to the remote QMQP client. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to - handle a request before it is terminated by a + How much time a Postfix daemon process may take to + handle a request before it is terminated by a built-in watchdog timer. ipc_timeout (3600s) @@ -113,48 +113,48 @@ QMQPD(8) QMQPD(8) over an internal communication channel. max_idle (100s) - The maximum amount of time that an idle Postfix - daemon process waits for an incoming connection + The maximum amount of time that an idle Postfix + daemon process waits for an incoming connection before terminating voluntarily. max_use (100) - The maximal number of incoming connections that a - Postfix daemon process will service before termi- + The maximal number of incoming connections that a + Postfix daemon process will service before termi- nating voluntarily. process_id (read-only) - The process ID of a Postfix command or daemon + The process ID of a Postfix command or daemon process. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. qmqpd_authorized_clients (empty) - What clients are allowed to connect to the QMQP - server port. + What remote QMQP clients are allowed to connect to + the Postfix QMQP server port. queue_directory (see 'postconf -d' output) - The location of the Postfix top-level queue direc- + The location of the Postfix top-level queue direc- tory. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - The mail system name that is prepended to the - process name in syslog records, so that "smtpd" + The mail system name that is prepended to the + process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". verp_delimiter_filter (-=+) - The characters Postfix accepts as VERP delimiter - characters on the Postfix sendmail(1) command line + The characters Postfix accepts as VERP delimiter + characters on the Postfix sendmail(1) command line and in SMTP commands. Available in Postfix version 2.5 and later: qmqpd_client_port_logging (no) - Enable logging of the remote QMQP client port in + Enable logging of the remote QMQP client port in addition to the hostname and IP address. SEE ALSO @@ -167,7 +167,7 @@ QMQPD(8) QMQPD(8) QMQP_README, Postfix ezmlm-idx howto. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. HISTORY diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index c2a83503f..3711f8dd2 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -171,6 +171,10 @@ This is available on systems with support for DBM databases. The UNIX process environment array. The lookup key is the variable name. Originally implemented for testing, someone may find this useful someday. +.IP \fBfail\fR +A table that reliably fails all requests. The lookup table +name provides the internal error result code. This table +exists to simplify Postfix error tests. .IP \fBhash\fR An indexed file type based on hashing. This is available on systems with support for Berkeley DB diff --git a/postfix/man/man8/qmqpd.8 b/postfix/man/man8/qmqpd.8 index ca193b205..758a5dcab 100644 --- a/postfix/man/man8/qmqpd.8 +++ b/postfix/man/man8/qmqpd.8 @@ -102,8 +102,8 @@ the sender. .ad .fi .IP "\fBqmqpd_error_delay (1s)\fR" -How long the QMQP server will pause before sending a negative reply -to the client. +How long the Postfix QMQP server will pause before sending a negative +reply to the remote QMQP client. .SH "MISCELLANEOUS CONTROLS" .na .nf @@ -129,7 +129,8 @@ The process ID of a Postfix command or daemon process. .IP "\fBprocess_name (read-only)\fR" The process name of a Postfix command or daemon process. .IP "\fBqmqpd_authorized_clients (empty)\fR" -What clients are allowed to connect to the QMQP server port. +What remote QMQP clients are allowed to connect to the Postfix QMQP +server port. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top-level queue directory. .IP "\fBsyslog_facility (mail)\fR" diff --git a/postfix/proto/DATABASE_README.html b/postfix/proto/DATABASE_README.html index 1b0237b37..ca1627c74 100644 --- a/postfix/proto/DATABASE_README.html +++ b/postfix/proto/DATABASE_README.html @@ -292,6 +292,12 @@ the ".dir" or ".pag" suffix.
variable name. The lookup table name in "environ:table" is ignored. +
fail (read-write)
+ +
A table that reliably fails all requests. The lookup table +name provides the internal error result code. This table exists to +simplify Postfix error tests.
+
hash
An indexed file type based on hashing. This is available only diff --git a/postfix/src/dns/dns_rr_eq_sa.ref b/postfix/src/dns/dns_rr_eq_sa.ref index 389164ff8..e633274a3 100644 --- a/postfix/src/dns/dns_rr_eq_sa.ref +++ b/postfix/src/dns/dns_rr_eq_sa.ref @@ -1,22 +1,22 @@ -2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 168.100.189.2 +2604:8d00:189::2 =?= 168.100.189.2 tested by function: no tested by macro: no 168.100.189.2 =?= 168.100.189.2 tested by function: yes tested by macro: yes -2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 168.100.189.3 +2604:8d00:189::2 =?= 168.100.189.3 tested by function: no tested by macro: no 168.100.189.2 =?= 168.100.189.3 tested by function: no tested by macro: no -2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 2001:240:587:0:2d0:b7ff:fe88:2ca7 -tested by function: yes -tested by macro: yes +2604:8d00:189::2 =?= 2001:240:587:0:2d0:b7ff:fe88:2ca7 +tested by function: no +tested by macro: no 168.100.189.2 =?= 2001:240:587:0:2d0:b7ff:fe88:2ca7 tested by function: no tested by macro: no -2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 2001:240:587:0:2d0:b7ff:febe:ca9f +2604:8d00:189::2 =?= 2001:240:587:0:2d0:b7ff:febe:ca9f tested by function: no tested by macro: no 168.100.189.2 =?= 2001:240:587:0:2d0:b7ff:febe:ca9f diff --git a/postfix/src/dns/dns_rr_to_pa.ref b/postfix/src/dns/dns_rr_to_pa.ref index 742c95a0f..86c022d56 100644 --- a/postfix/src/dns/dns_rr_to_pa.ref +++ b/postfix/src/dns/dns_rr_to_pa.ref @@ -1,2 +1,2 @@ spike.porcupine.org -> 168.100.189.2 -spike.porcupine.org -> 2001:240:587:0:2d0:b7ff:fe88:2ca7 +spike.porcupine.org -> 2604:8d00:189::2 diff --git a/postfix/src/dns/dns_rr_to_sa.ref b/postfix/src/dns/dns_rr_to_sa.ref index b9f0c4eeb..217b9a253 100644 --- a/postfix/src/dns/dns_rr_to_sa.ref +++ b/postfix/src/dns/dns_rr_to_sa.ref @@ -1,2 +1,2 @@ spike.porcupine.org 25 -> 168.100.189.2 25 -spike.porcupine.org 25 -> 2001:240:587:0:2d0:b7ff:fe88:2ca7 25 +spike.porcupine.org 25 -> 2604:8d00:189::2 25 diff --git a/postfix/src/dns/dns_sa_to_rr.ref b/postfix/src/dns/dns_sa_to_rr.ref index e2f24ce77..0b67b74e2 100644 --- a/postfix/src/dns/dns_sa_to_rr.ref +++ b/postfix/src/dns/dns_sa_to_rr.ref @@ -1,2 +1,2 @@ -spike.porcupine.org -> 2001:240:587:0:2d0:b7ff:fe88:2ca7 +spike.porcupine.org -> 2604:8d00:189::2 spike.porcupine.org -> 168.100.189.2 diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index 53a2c8f44..a87a0f18c 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -280,7 +280,7 @@ static VSTRING *flush_site_to_path(VSTRING *path, const char *site) static int flush_policy_ok(const char *site) { - return (domain_list_match(flush_domains, site)); + return (domain_list_match(flush_domains, site) > 0); } /* flush_add_service - append queue ID to per-site fast flush logfile */ @@ -810,7 +810,8 @@ static void flush_service(VSTREAM *client_stream, char *unused_service, static void pre_jail_init(char *unused_name, char **unused_argv) { - flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS), + flush_domains = domain_list_init(MATCH_FLAG_RETURN + | match_parent_style(VAR_FFLUSH_DOMAINS), var_fflush_domains); } diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 586d05646..379d0e50f 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -308,7 +308,7 @@ server_acl: server_acl.c $(LIB) $(LIBS) tests: tok822_test mime_tests strip_addr_test tok822_limit_test \ xtext_test scache_multi_test ehlo_mask_test \ namadr_list_test mail_conf_time_test header_body_checks_tests \ - mail_version_test + mail_version_test server_acl_test mime_tests: mime_test mime_nest mime_8bit mime_dom mime_trunc mime_cvt \ mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3 mime_garb4 @@ -405,6 +405,11 @@ mail_version_test: mail_version mail_version.in mail_version.ref diff mail_version.ref mail_version.tmp rm -f mail_version.tmp +server_acl_test: server_acl server_acl.in server_acl.ref + ./server_acl server_acl.tmp 2>&1 + diff server_acl.ref server_acl.tmp + rm -f server_acl.tmp + # Requires: Postfix running, root privileges rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref diff --git a/postfix/src/global/addr_match_list.c b/postfix/src/global/addr_match_list.c index 7ba1166bb..ad1a249e3 100644 --- a/postfix/src/global/addr_match_list.c +++ b/postfix/src/global/addr_match_list.c @@ -35,7 +35,13 @@ /* The matching process is case insensitive. /* /* addr_match_list_init() performs initializations. The first -/* argument is MATCH_FLAG_NONE for future extension. +/* argument is the bit-wise OR of zero or more of the following: +/* .IP MATCH_FLAG_RETURN +/* Request that addr_match_list_match() returns a negative result +/* (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a fatal +/* error. +/* .PP +/* Specify MATCH_FLAG_NONE to request none of the above. /* The second argument is a list of patterns, or the absolute /* pathname of a file with patterns. /* @@ -93,6 +99,7 @@ int main(int argc, char **argv) ADDR_MATCH_LIST *list; char *addr; int ch; + int rc; msg_vstream_init(argv[0], VSTREAM_ERR); @@ -107,20 +114,21 @@ int main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = addr_match_list_init(MATCH_FLAG_PARENT, argv[optind]); + list = addr_match_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]); addr = argv[optind + 1]; if (strcmp(addr, "-") == 0) { VSTRING *buf = vstring_alloc(100); - while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) + while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { + rc = addr_match_list_match(list, vstring_str(buf)); vstream_printf("%s: %s\n", vstring_str(buf), - addr_match_list_match(list, vstring_str(buf)) ? - "YES" : "NO"); + rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR"); + } vstring_free(buf); } else { + rc = addr_match_list_match(list, addr); vstream_printf("%s: %s\n", addr, - addr_match_list_match(list, addr) ? - "YES" : "NO"); + rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR"); } vstream_fflush(VSTREAM_OUT); addr_match_list_free(list); diff --git a/postfix/src/global/addr_match_list.h b/postfix/src/global/addr_match_list.h index d27c672b3..67c7e2316 100644 --- a/postfix/src/global/addr_match_list.h +++ b/postfix/src/global/addr_match_list.h @@ -15,7 +15,6 @@ * Utility library. */ #include -#include /* * External interface. diff --git a/postfix/src/global/debug_peer.c b/postfix/src/global/debug_peer.c index 97b42bd4e..bdd623beb 100644 --- a/postfix/src/global/debug_peer.c +++ b/postfix/src/global/debug_peer.c @@ -99,7 +99,8 @@ void debug_peer_init(void) */ if (*var_debug_peer_list) debug_peer_list = - namadr_list_init(match_parent_style(VAR_DEBUG_PEER_LIST), + namadr_list_init(MATCH_FLAG_RETURN + | match_parent_style(VAR_DEBUG_PEER_LIST), var_debug_peer_list); } @@ -113,7 +114,7 @@ int debug_peer_check(const char *name, const char *addr) */ if (debug_peer_list != 0 && saved_level == UNUSED_SAVED_LEVEL - && namadr_list_match(debug_peer_list, name, addr) != 0) { + && namadr_list_match(debug_peer_list, name, addr) > 0) { saved_level = msg_verbose; msg_verbose += var_debug_peer_level; return (1); diff --git a/postfix/src/global/dict_memcache.c b/postfix/src/global/dict_memcache.c index 3fc6101c0..9e64d1e1d 100644 --- a/postfix/src/global/dict_memcache.c +++ b/postfix/src/global/dict_memcache.c @@ -152,27 +152,24 @@ static void dict_memcache_set(DICT_MC *dict_mc, const char *value, int ttl) if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) { if (errno == ECONNREFUSED) break; + } else if (memcache_printf(fp, "set %s %d %d %ld", + STR(dict_mc->key_buf), dict_mc->mc_flags, ttl, data_len) < 0 + || memcache_fwrite(fp, value, strlen(value)) < 0 + || memcache_get(fp, dict_mc->clnt_buf, + dict_mc->max_line) < 0) { + if (count > 0) + msg_warn(errno ? "database %s:%s: I/O error: %m" : + "database %s:%s: I/O error", + DICT_TYPE_MEMCACHE, dict_mc->dict.name); + } else if (strcmp(STR(dict_mc->clnt_buf), "STORED") != 0) { + if (count > 0) + msg_warn("database %s:%s: update failed: %.30s", + DICT_TYPE_MEMCACHE, dict_mc->dict.name, + STR(dict_mc->clnt_buf)); } else { - if (memcache_printf(fp, "set %s %d %d %ld", - STR(dict_mc->key_buf), dict_mc->mc_flags, - ttl, data_len) < 0 - || memcache_fwrite(fp, value, strlen(value)) < 0 - || memcache_get(fp, dict_mc->clnt_buf, - dict_mc->max_line) < 0) { - if (count > 0) - msg_warn(errno ? "database %s:%s: I/O error: %m" : - "database %s:%s: I/O error", - DICT_TYPE_MEMCACHE, dict_mc->dict.name); - } else if (strcmp(STR(dict_mc->clnt_buf), "STORED") != 0) { - if (count > 0) - msg_warn("database %s:%s: update failed: %.30s", - DICT_TYPE_MEMCACHE, dict_mc->dict.name, - STR(dict_mc->clnt_buf)); - } else { - /* Victory! */ - dict_mc->mc_errno = 0; - break; - } + /* Victory! */ + dict_mc->mc_errno = 0; + break; } auto_clnt_recover(dict_mc->clnt); } @@ -195,36 +192,34 @@ static const char *dict_memcache_get(DICT_MC *dict_mc) if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) { if (errno == ECONNREFUSED) break; - } else { - if (memcache_printf(fp, "get %s", STR(dict_mc->key_buf)) < 0 + } else if (memcache_printf(fp, "get %s", STR(dict_mc->key_buf)) < 0 || memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0) { - if (count > 0) - msg_warn(errno ? "database %s:%s: I/O error: %m" : - "database %s:%s: I/O error", - DICT_TYPE_MEMCACHE, dict_mc->dict.name); - } else if (strcmp(STR(dict_mc->clnt_buf), "END") == 0) { - /* Not found. */ - dict_mc->mc_errno = 0; - break; - } else if (sscanf(STR(dict_mc->clnt_buf), - "VALUE %*s %*s %ld", &todo) != 1 - || todo < 0 || todo > dict_mc->max_data) { - if (count > 0) - msg_warn("%s: unexpected memcache server reply: %.30s", - dict_mc->dict.name, STR(dict_mc->clnt_buf)); - } else if (memcache_fread(fp, dict_mc->res_buf, todo) < 0) { - if (count > 0) - msg_warn("%s: EOF receiving memcache server reply", - dict_mc->dict.name); - } else { - /* Victory! */ - retval = STR(dict_mc->res_buf); - dict_mc->mc_errno = 0; - if (memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0 - || strcmp(STR(dict_mc->clnt_buf), "END") != 0) - auto_clnt_recover(dict_mc->clnt); - break; - } + if (count > 0) + msg_warn(errno ? "database %s:%s: I/O error: %m" : + "database %s:%s: I/O error", + DICT_TYPE_MEMCACHE, dict_mc->dict.name); + } else if (strcmp(STR(dict_mc->clnt_buf), "END") == 0) { + /* Not found. */ + dict_mc->mc_errno = 0; + break; + } else if (sscanf(STR(dict_mc->clnt_buf), + "VALUE %*s %*s %ld", &todo) != 1 + || todo < 0 || todo > dict_mc->max_data) { + if (count > 0) + msg_warn("%s: unexpected memcache server reply: %.30s", + dict_mc->dict.name, STR(dict_mc->clnt_buf)); + } else if (memcache_fread(fp, dict_mc->res_buf, todo) < 0) { + if (count > 0) + msg_warn("%s: EOF receiving memcache server reply", + dict_mc->dict.name); + } else { + /* Victory! */ + retval = STR(dict_mc->res_buf); + dict_mc->mc_errno = 0; + if (memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0 + || strcmp(STR(dict_mc->clnt_buf), "END") != 0) + auto_clnt_recover(dict_mc->clnt); + break; } auto_clnt_recover(dict_mc->clnt); } @@ -246,30 +241,27 @@ static int dict_memcache_del(DICT_MC *dict_mc) if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) { if (errno == ECONNREFUSED) break; + } else if (memcache_printf(fp, "delete %s", STR(dict_mc->key_buf)) < 0 + || memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0) { + if (count > 0) + msg_warn(errno ? "database %s:%s: I/O error: %m" : + "database %s:%s: I/O error", + DICT_TYPE_MEMCACHE, dict_mc->dict.name); + } else if (strcmp(STR(dict_mc->clnt_buf), "DELETED") == 0) { + /* Victory! */ + dict_mc->mc_errno = 0; + retval = 0; + break; + } else if (strcmp(STR(dict_mc->clnt_buf), "NOT_FOUND") == 0) { + /* Not found! */ + dict_mc->mc_errno = 0; + retval = 1; + break; } else { - if (memcache_printf(fp, "delete %s", STR(dict_mc->key_buf)) < 0 - || memcache_get(fp, dict_mc->clnt_buf, - dict_mc->max_line) < 0) { - if (count > 0) - msg_warn(errno ? "database %s:%s: I/O error: %m" : - "database %s:%s: I/O error", - DICT_TYPE_MEMCACHE, dict_mc->dict.name); - } else if (strcmp(STR(dict_mc->clnt_buf), "DELETED") == 0) { - /* Victory! */ - dict_mc->mc_errno = 0; - retval = 0; - break; - } else if (strcmp(STR(dict_mc->clnt_buf), "NOT_FOUND") == 0) { - /* Not found! */ - dict_mc->mc_errno = 0; - retval = 1; - break; - } else { - if (count > 0) - msg_warn("database %s:%s: delete failed: %.30s", - DICT_TYPE_MEMCACHE, dict_mc->dict.name, - STR(dict_mc->clnt_buf)); - } + if (count > 0) + msg_warn("database %s:%s: delete failed: %.30s", + DICT_TYPE_MEMCACHE, dict_mc->dict.name, + STR(dict_mc->clnt_buf)); } auto_clnt_recover(dict_mc->clnt); } diff --git a/postfix/src/global/domain_list.c b/postfix/src/global/domain_list.c index 9535ac223..57c3c1d66 100644 --- a/postfix/src/global/domain_list.c +++ b/postfix/src/global/domain_list.c @@ -35,12 +35,15 @@ /* /* domain_list_init() performs initializations. The first argument /* is the bit-wise OR of zero or more of the following: -/* .RS /* .IP MATCH_FLAG_PARENT /* The hostname pattern foo.com matches itself and any name below /* the domain foo.com. If this flag is cleared, foo.com matches itself /* only, and .foo.com matches any name below the domain foo.com. -/* .RE +/* .IP MATCH_FLAG_RETURN +/* Request that domain_list_match() returns a negative result +/* (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a +/* fatal error. +/* .PP /* Specify MATCH_FLAG_NONE to request none of the above. /* The second argument is a list of domain patterns, or the name of /* a file containing domain patterns. @@ -96,6 +99,7 @@ int main(int argc, char **argv) DOMAIN_LIST *list; char *host; int ch; + int rc; msg_vstream_init(argv[0], VSTREAM_ERR); @@ -110,10 +114,11 @@ int main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = domain_list_init(MATCH_FLAG_PARENT, argv[optind]); + list = domain_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]); host = argv[optind + 1]; - vstream_printf("%s: %s\n", host, domain_list_match(list, host) ? - "YES" : "NO"); + rc = domain_list_match(list, host); + vstream_printf("%s: %s\n", host, + rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR"); vstream_fflush(VSTREAM_OUT); domain_list_free(list); return (0); diff --git a/postfix/src/global/domain_list.h b/postfix/src/global/domain_list.h index 23f60c789..8612219d9 100644 --- a/postfix/src/global/domain_list.h +++ b/postfix/src/global/domain_list.h @@ -15,7 +15,6 @@ * Utility library. */ #include -#include /* * External interface. diff --git a/postfix/src/global/flush_clnt.c b/postfix/src/global/flush_clnt.c index 043754f9b..d7a51f9fe 100644 --- a/postfix/src/global/flush_clnt.c +++ b/postfix/src/global/flush_clnt.c @@ -103,7 +103,8 @@ static DOMAIN_LIST *flush_domains; void flush_init(void) { - flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS), + flush_domains = domain_list_init(MATCH_FLAG_RETURN + | match_parent_style(VAR_FFLUSH_DOMAINS), var_fflush_domains); } @@ -165,6 +166,7 @@ int flush_send_site(const char *site) { const char *myname = "flush_send_site"; int status; + int rc; if (msg_verbose) msg_info("%s: site %s", myname, site); @@ -175,13 +177,15 @@ int flush_send_site(const char *site) */ if (flush_domains == 0) msg_panic("missing flush client initialization"); - if (domain_list_match(flush_domains, site) == 0) + if ((rc = domain_list_match(flush_domains, site)) == 0) status = FLUSH_STAT_DENY; - else + else if (rc > 0) status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE, ATTR_TYPE_STR, MAIL_ATTR_SITE, site, ATTR_TYPE_END); + else + status = FLUSH_STAT_FAIL; if (msg_verbose) msg_info("%s: site %s status %d", myname, site, status); @@ -219,6 +223,7 @@ int flush_add(const char *site, const char *queue_id) { const char *myname = "flush_add"; int status; + int rc; if (msg_verbose) msg_info("%s: site %s id %s", myname, site, queue_id); @@ -229,14 +234,16 @@ int flush_add(const char *site, const char *queue_id) */ if (flush_domains == 0) msg_panic("missing flush client initialization"); - if (domain_list_match(flush_domains, site) == 0) + if ((rc = domain_list_match(flush_domains, site)) == 0) status = FLUSH_STAT_DENY; - else + else if (rc > 0) status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_ADD, ATTR_TYPE_STR, MAIL_ATTR_SITE, site, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_END); + else + status = FLUSH_STAT_FAIL; if (msg_verbose) msg_info("%s: site %s id %s status %d", myname, site, queue_id, diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index a4e1808e1..3812da471 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20111218" +#define MAIL_RELEASE_DATE "20111219" #define MAIL_VERSION_NUMBER "2.9" #ifdef SNAPSHOT diff --git a/postfix/src/global/namadr_list.c b/postfix/src/global/namadr_list.c index 883b64a8f..9dfc87f39 100644 --- a/postfix/src/global/namadr_list.c +++ b/postfix/src/global/namadr_list.c @@ -41,12 +41,15 @@ /* namadr_list_init() performs initializations. The first /* argument is the bit-wise OR of zero or more of the /* following: -/* .RS /* .IP MATCH_FLAG_PARENT /* The hostname pattern foo.com matches itself and any name below /* the domain foo.com. If this flag is cleared, foo.com matches itself /* only, and .foo.com matches any name below the domain foo.com. -/* .RE +/* .IP MATCH_FLAG_RETURN +/* Request that namadr_list_match() returns a negative result +/* (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a +/* fatal error. +/* .PP /* Specify MATCH_FLAG_NONE to request none of the above. /* The second argument is a list of patterns, or the absolute /* pathname of a file with patterns. @@ -103,6 +106,7 @@ int main(int argc, char **argv) char *host; char *addr; int ch; + int rc; msg_vstream_init(argv[0], VSTREAM_ERR); @@ -117,12 +121,12 @@ int main(int argc, char **argv) } if (argc != optind + 3) usage(argv[0]); - list = namadr_list_init(MATCH_FLAG_PARENT, argv[optind]); + list = namadr_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]); host = argv[optind + 1]; addr = argv[optind + 2]; + rc = namadr_list_match(list, host, addr); vstream_printf("%s/%s: %s\n", host, addr, - namadr_list_match(list, host, addr) ? - "YES" : "NO"); + rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR"); vstream_fflush(VSTREAM_OUT); namadr_list_free(list); return (0); diff --git a/postfix/src/global/namadr_list.h b/postfix/src/global/namadr_list.h index 9bf90d768..b2322edf8 100644 --- a/postfix/src/global/namadr_list.h +++ b/postfix/src/global/namadr_list.h @@ -15,7 +15,6 @@ * Utility library. */ #include -#include /* * External interface. diff --git a/postfix/src/global/namadr_list.in b/postfix/src/global/namadr_list.in index 2eaeea315..c1cd8f2c4 100644 --- a/postfix/src/global/namadr_list.in +++ b/postfix/src/global/namadr_list.in @@ -1,4 +1,6 @@ ./namadr_list 168.100.189.0/28 dummy 168.100.189.2 +./namadr_list '!168.100.189.2 168.100.189.0/28' dummy 168.100.189.2 +./namadr_list '!168.100.189.2 168.100.189.0/28' dummy 168.100.189.3 ./namadr_list 168.100.189.0/28 dummy 168.100.189.16 ./namadr_list 168.100.189.0/98 dummy 168.100.189.16 ./namadr_list 168.100.589.0/28 dummy 168.100.189.16 @@ -35,3 +37,5 @@ env foo=x ./namadr_list !environ:junk foo 168.100.189.3 env foo=x ./namadr_list !environ:junk bar 168.100.189.3 env foo=x ./namadr_list !!environ:junk foo 168.100.189.3 env foo=x ./namadr_list !!environ:junk bar 168.100.189.3 +./namadr_list fail:1 bar 168.100.189.3 +./namadr_list !fail:1 bar 168.100.189.3 diff --git a/postfix/src/global/namadr_list.ref b/postfix/src/global/namadr_list.ref index 5c2fffbc1..a7b864619 100644 --- a/postfix/src/global/namadr_list.ref +++ b/postfix/src/global/namadr_list.ref @@ -1,12 +1,17 @@ dummy/168.100.189.2: YES +dummy/168.100.189.2: NO +dummy/168.100.189.3: YES dummy/168.100.189.16: NO -./namadr_list: fatal: bad net/mask pattern: "168.100.189.0/98" -./namadr_list: fatal: bad net/mask pattern: "168.100.589.0/28" +./namadr_list: warning: bad net/mask pattern: "168.100.189.0/98" +dummy/168.100.189.16: ERROR +./namadr_list: warning: bad net/mask pattern: "168.100.589.0/28" +dummy/168.100.189.16: ERROR dummy/168.100.989.16: NO ./namadr_list: fatal: unsupported dictionary type: 2001 dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO -./namadr_list: fatal: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead +./namadr_list: warning: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead +dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: ERROR dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: YES dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: NO dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: YES @@ -24,12 +29,18 @@ foo/168.100.189.3: YES bar/168.100.189.3: NO baz/168.100.189.3: YES x.x.x/127.0.0.1: NO -./namadr_list: fatal: bad net/mask pattern: "be/be" +./namadr_list: warning: bad net/mask pattern: "be/be" +x.x.x/127.0.0.1: ERROR x.x.x/127.0.0.1: NO -./namadr_list: fatal: bad address pattern: "be:be" +./namadr_list: warning: bad address pattern: "be:be" +x.x.x/::1: ERROR foo/168.100.189.3: YES bar/168.100.189.3: NO foo/168.100.189.3: NO bar/168.100.189.3: NO foo/168.100.189.3: YES bar/168.100.189.3: NO +./namadr_list: warning: fail:1(0,lock|fold_fix): table lookup problem +bar/168.100.189.3: ERROR +./namadr_list: warning: fail:1(0,lock|fold_fix): table lookup problem +bar/168.100.189.3: ERROR diff --git a/postfix/src/global/server_acl.c b/postfix/src/global/server_acl.c index f4a78fb6a..03b602dab 100644 --- a/postfix/src/global/server_acl.c +++ b/postfix/src/global/server_acl.c @@ -98,7 +98,8 @@ void server_acl_pre_jail_init(const char *mynetworks, const char *origin) { if (server_acl_mynetworks) addr_match_list_free(server_acl_mynetworks); - server_acl_mynetworks = addr_match_list_init(match_parent_style(origin), + server_acl_mynetworks = + addr_match_list_init(MATCH_FLAG_RETURN | match_parent_style(origin), mynetworks); } @@ -158,6 +159,7 @@ int server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl, int ret; ARGV fake_argv; const char *fake_args[2]; + int rc; for (cpp = intern_acl->argv; (acl = *cpp) != 0; cpp++) { if (msg_verbose) @@ -168,8 +170,14 @@ int server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl, } else if (STREQ(acl, SERVER_ACL_NAME_PERMIT)) { return (SERVER_ACL_ACT_PERMIT); } else if (STREQ(acl, SERVER_ACL_NAME_WL_MYNETWORKS)) { - if (addr_match_list_match(server_acl_mynetworks, client_addr)) + rc = addr_match_list_match(server_acl_mynetworks, client_addr); + if (rc > 0) return (SERVER_ACL_ACT_PERMIT); + if (rc < 0) { + msg_warn("%s: %s: mynetworks lookup error -- ignoring the " + "remainder of this access list", origin, acl); + return (SERVER_ACL_ACT_ERROR); + } } else if (strchr(acl, ':') != 0) { if ((dict = dict_handle(acl)) == 0) msg_panic("%s: unexpected dictionary: %s", myname, acl); @@ -189,8 +197,8 @@ int server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl, if (ret != SERVER_ACL_ACT_DUNNO) return (ret); } else if (dict_errno != 0) { - msg_warn("%s: table lookup error -- ignoring the remainder " - "of this access list", acl); + msg_warn("%s: %s: table lookup error -- ignoring the remainder " + "of this access list", origin, acl); return (SERVER_ACL_ACT_ERROR); } } else if (STREQ(acl, SERVER_ACL_NAME_DUNNO)) { diff --git a/postfix/src/global/server_acl.in b/postfix/src/global/server_acl.in new file mode 100644 index 000000000..a12001a1e --- /dev/null +++ b/postfix/src/global/server_acl.in @@ -0,0 +1,10 @@ +mynetworks=168.100.189.0/27 +server_acl=permit_mynetworks,reject +address=168.100.189.2 +mynetworks=!168.100.189.2,168.100.189.0/27 +address=168.100.189.2 +address=168.100.189.3 +mynetworks=fail:1 +address=168.100.189.4 +server_acl=fail:1,reject +address=168.100.189.2 diff --git a/postfix/src/global/server_acl.ref b/postfix/src/global/server_acl.ref new file mode 100644 index 000000000..7b72f76bf --- /dev/null +++ b/postfix/src/global/server_acl.ref @@ -0,0 +1,18 @@ +> mynetworks=168.100.189.0/27 +> server_acl=permit_mynetworks,reject +> address=168.100.189.2 +168.100.189.2: permit +> mynetworks=!168.100.189.2,168.100.189.0/27 +> address=168.100.189.2 +168.100.189.2: reject +> address=168.100.189.3 +168.100.189.3: permit +> mynetworks=fail:1 +> address=168.100.189.4 +unknown: warning: fail:1(0,lock|fold_fix): table lookup problem +unknown: warning: server_acl: permit_mynetworks: mynetworks lookup error -- ignoring the remainder of this access list +168.100.189.4: error +> server_acl=fail:1,reject +> address=168.100.189.2 +unknown: warning: server_acl: fail:1: table lookup error -- ignoring the remainder of this access list +168.100.189.2: error diff --git a/postfix/src/global/string_list.c b/postfix/src/global/string_list.c index bdb6fc4fb..9de5a5429 100644 --- a/postfix/src/global/string_list.c +++ b/postfix/src/global/string_list.c @@ -31,8 +31,15 @@ /* In order to reverse the result, precede a pattern with an /* exclamation point (!). /* -/* string_list_init() performs initializations. The flags argument -/* is ignored; pattern_list specifies a list of string patterns. +/* string_list_init() performs initializations. The first argument +/* is a bit-wise OR of zero or more of following: +/* .IP MATCH_FLAG_RETURN +/* Request that string_list_match() returns a negative result +/* (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a fatal +/* error. +/* .PP +/* Specify MATCH_FLAG_NONE to request none of the above. +/* The second argument specifies a list of string patterns. /* /* string_list_match() matches the specified string against the /* compiled pattern list. @@ -85,6 +92,7 @@ int main(int argc, char **argv) STRING_LIST *list; char *string; int ch; + int rc; msg_vstream_init(argv[0], VSTREAM_ERR); @@ -99,10 +107,11 @@ int main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = string_list_init(MATCH_FLAG_NONE, argv[optind]); + list = string_list_init(MATCH_FLAG_NONE | MATCH_FLAG_RETURN, argv[optind]); string = argv[optind + 1]; - vstream_printf("%s: %s\n", string, string_list_match(list, string) ? - "YES" : "NO"); + rc = string_list_match(list, string); + vstream_printf("%s: %s\n", string, + rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR"); vstream_fflush(VSTREAM_OUT); string_list_free(list); return (0); diff --git a/postfix/src/global/string_list.h b/postfix/src/global/string_list.h index daa9541d2..0a96bacfe 100644 --- a/postfix/src/global/string_list.h +++ b/postfix/src/global/string_list.h @@ -15,7 +15,6 @@ * Utility library. */ #include -#include /* * External interface. diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index eea582ac6..d742557b2 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -165,6 +165,10 @@ /* The UNIX process environment array. The lookup key is the variable /* name. Originally implemented for testing, someone may find this /* useful someday. +/* .IP \fBfail\fR +/* A table that reliably fails all requests. The lookup table +/* name provides the internal error result code. This table +/* exists to simplify Postfix error tests. /* .IP \fBhash\fR /* An indexed file type based on hashing. /* This is available on systems with support for Berkeley DB diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 4c5c6cfa8..f7145fade 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -80,8 +80,8 @@ /* .ad /* .fi /* .IP "\fBqmqpd_error_delay (1s)\fR" -/* How long the QMQP server will pause before sending a negative reply -/* to the client. +/* How long the Postfix QMQP server will pause before sending a negative +/* reply to the remote QMQP client. /* MISCELLANEOUS CONTROLS /* .ad /* .fi @@ -105,7 +105,8 @@ /* .IP "\fBprocess_name (read-only)\fR" /* The process name of a Postfix command or daemon process. /* .IP "\fBqmqpd_authorized_clients (empty)\fR" -/* What clients are allowed to connect to the QMQP server port. +/* What remote QMQP clients are allowed to connect to the Postfix QMQP +/* server port. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBsyslog_facility (mail)\fR" @@ -648,6 +649,7 @@ static void qmqpd_receive(QMQPD_STATE *state) static void qmqpd_proto(QMQPD_STATE *state) { int status; + int rc; netstring_setup(state->client, var_qmqpd_timeout); @@ -685,12 +687,17 @@ static void qmqpd_proto(QMQPD_STATE *state) /* * See if we want to talk to this client at all. */ - if (namadr_list_match(qmqpd_clients, state->name, state->addr) == 0) { + rc = namadr_list_match(qmqpd_clients, state->name, state->addr); + if (rc > 0) { + qmqpd_receive(state); + } else if (rc == 0) { qmqpd_reply(state, DONT_LOG, QMQPD_STAT_HARD, "Error: %s is not authorized to use this service", state->namaddr); - } else - qmqpd_receive(state); + } else { + qmqpd_reply(state, DONT_LOG, QMQPD_STAT_RETRY, + "Error: server configuration error"); + } break; } @@ -760,7 +767,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv) { debug_peer_init(); qmqpd_clients = - namadr_list_init(match_parent_style(VAR_QMQPD_CLIENTS), + namadr_list_init(MATCH_FLAG_RETURN + | match_parent_style(VAR_QMQPD_CLIENTS), var_qmqpd_clients); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index d42fefbf5..59415c85f 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1757,7 +1757,6 @@ static int mail_open_stream(SMTPD_STATE *state) * feature. */ if (state->proxy_mail) { - smtpd_check_rewrite(state); if (smtpd_proxy_create(state, smtpd_proxy_opts, var_smtpd_proxy_filt, var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo, state->proxy_mail) != 0) { @@ -1780,7 +1779,6 @@ static int mail_open_stream(SMTPD_STATE *state) else if (SMTPD_STAND_ALONE(state) == 0) { int cleanup_flags; - smtpd_check_rewrite(state); cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL, smtpd_input_transp_mask) | CLEANUP_FLAG_SMTP_REPLY; @@ -2297,6 +2295,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) return (-1); } } + err = smtpd_check_rewrite(state); + if (err != 0) { + /* XXX Reset access map side effects. */ + mail_reset(state); + smtpd_chat_reply(state, "%s", err); + return (-1); + } /* * Check the queue file space, if applicable. The optional before-filter diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index f53741f82..b23c3c168 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -256,6 +256,7 @@ static jmp_buf smtpd_check_buf; /* * Results of restrictions. */ +#define SMTPD_CHECK_ERROR (-1) /* server error */ #define SMTPD_CHECK_DUNNO 0 /* indifferent */ #define SMTPD_CHECK_OK 1 /* explicitly permit */ #define SMTPD_CHECK_REJECT 2 /* explicitly reject */ @@ -4101,7 +4102,7 @@ int smtpd_check_addr(const char *addr) /* smtpd_check_rewrite - choose address qualification context */ -void smtpd_check_rewrite(SMTPD_STATE *state) +char *smtpd_check_rewrite(SMTPD_STATE *state) { const char *myname = "smtpd_check_rewrite"; int status; @@ -4131,11 +4132,12 @@ void smtpd_check_rewrite(SMTPD_STATE *state) if ((dict = dict_handle(*cpp)) == 0) msg_panic("%s: dictionary not found: %s", myname, *cpp); dict_errno = 0; - /* for now, dict errors are fatal */ if (dict_get(dict, state->addr) != 0) status = SMTPD_CHECK_OK; - else if (dict_errno != 0) - msg_fatal("%s: table lookup error", *cpp); + else if (dict_errno != 0) { + msg_warn("%s: %s: lookup error", VAR_LOC_RWR_CLIENTS, *cpp); + status = SMTPD_CHECK_ERROR; + } } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) { #ifdef USE_SASL_AUTH if (smtpd_sasl_is_active(state)) @@ -4144,29 +4146,32 @@ void smtpd_check_rewrite(SMTPD_STATE *state) #endif } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) { status = permit_tls_clientcerts(state, 1); - /* for now, dict errors are fatal */ #ifdef USE_TLS if (dict_errno != 0) - msg_fatal("%s: table lookup error", var_smtpd_relay_ccerts); + status = SMTPD_CHECK_ERROR; #endif } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) { status = permit_tls_clientcerts(state, 0); - /* for now, dict errors are fatal */ #ifdef USE_TLS if (dict_errno != 0) - msg_fatal("%s: table lookup error", var_smtpd_relay_ccerts); + status = SMTPD_CHECK_ERROR; #endif } else { msg_warn("parameter %s: invalid request: %s", VAR_LOC_RWR_CLIENTS, name); continue; } + if (status < 0) { + state->error_mask |= MAIL_ERROR_RESOURCE; + return ("451 4.3.5 Server configuration error"); + } if (status == SMTPD_CHECK_OK) { state->rewrite_context = MAIL_ATTR_RWR_LOCAL; - return; + return (0); } } state->rewrite_context = MAIL_ATTR_RWR_REMOTE; + return (0); } /* smtpd_check_client - validate client name or address */ @@ -5170,6 +5175,15 @@ int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot) return (ifnot); } +/* smtpd_sasl_state_init - the real deal */ + +void smtpd_sasl_state_init(SMTPD_STATE *state) +{ + state->sasl_username = 0; + state->sasl_method = 0; + state->sasl_sender = 0; +} + #endif /* verify_clnt_query - stub */ diff --git a/postfix/src/smtpd/smtpd_check.h b/postfix/src/smtpd/smtpd_check.h index 9bdd255c7..b76a4990f 100644 --- a/postfix/src/smtpd/smtpd_check.h +++ b/postfix/src/smtpd/smtpd_check.h @@ -14,7 +14,7 @@ */ extern void smtpd_check_init(void); extern int smtpd_check_addr(const char *); -extern void smtpd_check_rewrite(SMTPD_STATE *); +extern char *smtpd_check_rewrite(SMTPD_STATE *); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); extern char *smtpd_check_mail(SMTPD_STATE *, char *); diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index f9d29a86e..2ed395561 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -155,6 +155,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, const char *relay; const char *xport; const char *sender_key; + int rc; *flags = 0; vstring_strcpy(channel, "CHANNEL NOT UPDATED"); @@ -431,15 +432,15 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, * Virtual alias domain. */ if (virt_alias_doms - && string_list_match(virt_alias_doms, rcpt_domain)) { + && (rc = string_list_match(virt_alias_doms, rcpt_domain)) > 0) { if (var_helpful_warnings) { if (virt_mailbox_doms - && string_list_match(virt_mailbox_doms, rcpt_domain)) + && string_list_match(virt_mailbox_doms, rcpt_domain) > 0) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_VIRT_ALIAS_DOMS, VAR_VIRT_MAILBOX_DOMS); if (relay_domains - && domain_list_match(relay_domains, rcpt_domain)) + && domain_list_match(relay_domains, rcpt_domain) > 0) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_VIRT_ALIAS_DOMS, VAR_RELAY_DOMAINS); @@ -454,7 +455,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, var_show_unk_rcpt_table ? " in virtual alias table" : ""); *flags |= RESOLVE_CLASS_ALIAS; - } else if (dict_errno != 0) { + } else if (dict_errno != 0 || rc < 0) { msg_warn("%s lookup failure", VAR_VIRT_ALIAS_DOMS); *flags |= RESOLVE_FLAG_FAIL; FREE_MEMORY_AND_RETURN; @@ -464,10 +465,10 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, * Virtual mailbox domain. */ else if (virt_mailbox_doms - && string_list_match(virt_mailbox_doms, rcpt_domain)) { + && (rc = string_list_match(virt_mailbox_doms, rcpt_domain)) > 0) { if (var_helpful_warnings) { if (relay_domains - && domain_list_match(relay_domains, rcpt_domain)) + && domain_list_match(relay_domains, rcpt_domain) > 0) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_VIRT_MAILBOX_DOMS, VAR_RELAY_DOMAINS); @@ -476,7 +477,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, vstring_strcpy(nexthop, rcpt_domain); blame = rp->virt_transport_name; *flags |= RESOLVE_CLASS_VIRTUAL; - } else if (dict_errno != 0) { + } else if (dict_errno != 0 || rc < 0) { msg_warn("%s lookup failure", VAR_VIRT_MAILBOX_DOMS); *flags |= RESOLVE_FLAG_FAIL; FREE_MEMORY_AND_RETURN; @@ -486,11 +487,11 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, * Off-host relay destination. */ if (relay_domains - && domain_list_match(relay_domains, rcpt_domain)) { + && (rc = domain_list_match(relay_domains, rcpt_domain)) > 0) { vstring_strcpy(channel, RES_PARAM_VALUE(rp->relay_transport)); blame = rp->relay_transport_name; *flags |= RESOLVE_CLASS_RELAY; - } else if (dict_errno != 0) { + } else if (dict_errno != 0 || rc < 0) { msg_warn("%s lookup failure", VAR_RELAY_DOMAINS); *flags |= RESOLVE_FLAG_FAIL; FREE_MEMORY_AND_RETURN; @@ -560,11 +561,11 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, else { if (var_helpful_warnings) { if (virt_alias_doms - && string_list_match(virt_alias_doms, rcpt_domain)) + && string_list_match(virt_alias_doms, rcpt_domain) > 0) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_MYDEST, VAR_VIRT_ALIAS_DOMS); if (virt_mailbox_doms - && string_list_match(virt_mailbox_doms, rcpt_domain)) + && string_list_match(virt_mailbox_doms, rcpt_domain) > 0) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS); } @@ -739,15 +740,16 @@ void resolve_init(void) if (*var_virt_alias_doms) virt_alias_doms = - string_list_init(MATCH_FLAG_NONE, var_virt_alias_doms); + string_list_init(MATCH_FLAG_RETURN, var_virt_alias_doms); if (*var_virt_mailbox_doms) virt_mailbox_doms = - string_list_init(MATCH_FLAG_NONE, var_virt_mailbox_doms); + string_list_init(MATCH_FLAG_RETURN, var_virt_mailbox_doms); if (*var_relay_domains) relay_domains = - domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + domain_list_init(MATCH_FLAG_RETURN + | match_parent_style(VAR_RELAY_DOMAINS), var_relay_domains); if (*var_relocated_maps) diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 7ecf8b319..3687fe12d 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -33,7 +33,8 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ allascii.c load_file.c killme_after.c vstream_tweak.c \ unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \ unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \ - ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.c + ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.c \ + dict_fail.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ @@ -68,7 +69,8 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ allascii.o load_file.o killme_after.o vstream_tweak.o \ unix_pass_listen.o unix_pass_trigger.o edit_file.o inet_windowsize.o \ unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \ - ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o + ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o \ + dict_fail.o HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \ dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \ @@ -88,8 +90,8 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \ username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \ vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \ - edit_file.h dict_cache.h dict_thash.h \ - ip_match.h nbbio.h base32_code.h + edit_file.h dict_cache.h dict_thash.h ip_match.h nbbio.h base32_code.h \ + dict_fail.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c DEFS = -I. -D$(SYSTYPE) @@ -908,6 +910,16 @@ dict_env.o: sys_defs.h dict_env.o: vbuf.h dict_env.o: vstream.h dict_env.o: vstring.h +dict_fail.o: argv.h +dict_fail.o: dict.h +dict_fail.o: dict_fail.c +dict_fail.o: dict_fail.h +dict_fail.o: msg.h +dict_fail.o: mymalloc.h +dict_fail.o: sys_defs.h +dict_fail.o: vbuf.h +dict_fail.o: vstream.h +dict_fail.o: vstring.h dict_ht.o: argv.h dict_ht.o: dict.h dict_ht.o: dict_ht.c @@ -950,6 +962,7 @@ dict_open.o: dict_cidr.h dict_open.o: dict_db.h dict_open.o: dict_dbm.h dict_open.o: dict_env.h +dict_open.o: dict_fail.h dict_open.o: dict_ht.h dict_open.o: dict_ni.h dict_open.o: dict_nis.h diff --git a/postfix/src/util/dict_fail.c b/postfix/src/util/dict_fail.c new file mode 100644 index 000000000..197f61ed5 --- /dev/null +++ b/postfix/src/util/dict_fail.c @@ -0,0 +1,114 @@ +/*++ +/* NAME +/* dict_fail 3 +/* SUMMARY +/* dictionary manager interface to 'always fail' table +/* SYNOPSIS +/* #include +/* +/* DICT *dict_fail_open(name, name, dict_flags) +/* const char *name; +/* int dummy; +/* int dict_flags; +/* DESCRIPTION +/* dict_fail_open() implements a dummy dictionary that fails +/* all operations. The name specifies the dict_errno value. +/* SEE ALSO +/* dict(3) generic dictionary manager +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include + +/* Application-specific. */ + +typedef struct { + DICT dict; /* generic members */ + int dict_errno; /* fixed error result */ +} DICT_FAIL; + +/* dict_fail_sequence - fail lookup */ + +static int dict_fail_sequence(DICT *dict, int unused_func, + const char **key, const char **value) +{ + DICT_FAIL *dp = (DICT_FAIL *) dict; + + dict_errno = dp->dict_errno; + return (1); +} + +/* dict_fail_update - fail lookup */ + +static void dict_fail_update(DICT *dict, const char *unused_name, + const char *unused_value) +{ + DICT_FAIL *dp = (DICT_FAIL *) dict; + + dict_errno = dp->dict_errno; +} + +/* dict_fail_lookup - fail lookup */ + +static const char *dict_fail_lookup(DICT *dict, const char *unused_name) +{ + DICT_FAIL *dp = (DICT_FAIL *) dict; + + dict_errno = dp->dict_errno; + return (0); +} + +/* dict_fail_delete - fail delete */ + +static int dict_fail_delete(DICT *dict, const char *unused_name) +{ + DICT_FAIL *dp = (DICT_FAIL *) dict; + + dict_errno = dp->dict_errno; + return (-1); +} + +/* dict_fail_close - close fail dictionary */ + +static void dict_fail_close(DICT *dict) +{ + dict_free(dict); +} + +/* dict_fail_open - make association with fail variable */ + +DICT *dict_fail_open(const char *name, int open_flags, int dict_flags) +{ + DICT_FAIL *dp; + + dp = (DICT_FAIL *) dict_alloc(DICT_TYPE_FAIL, name, sizeof(*dp)); + dp->dict.lookup = dict_fail_lookup; + if (open_flags & O_RDWR) { + dp->dict.update = dict_fail_update; + dp->dict.delete = dict_fail_delete; + } + dp->dict.sequence = dict_fail_sequence; + dp->dict.close = dict_fail_close; + dp->dict.flags = dict_flags | DICT_FLAG_PATTERN; + dp->dict_errno = atoi(name); + dp->dict.owner.status = DICT_OWNER_TRUSTED; + return (DICT_DEBUG (&dp->dict)); +} diff --git a/postfix/src/util/dict_fail.h b/postfix/src/util/dict_fail.h new file mode 100644 index 000000000..b42a31bcd --- /dev/null +++ b/postfix/src/util/dict_fail.h @@ -0,0 +1,35 @@ +#ifndef _DICT_FAIL_H_INCLUDED_ +#define _DICT_FAIL_H_INCLUDED_ + +/*++ +/* NAME +/* dict_fail 3h +/* SUMMARY +/* dictionary manager interface to 'always fail' table +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +#define DICT_TYPE_FAIL "fail" + +extern DICT *dict_fail_open(const char *, int, int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* jeffm +/* ghostgun.com +/*--*/ + +#endif diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c index d5ae3d5a0..76d946be4 100644 --- a/postfix/src/util/dict_open.c +++ b/postfix/src/util/dict_open.c @@ -211,6 +211,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,7 @@ static const DICT_OPEN_INFO dict_open_info[] = { DICT_TYPE_STATIC, dict_static_open, DICT_TYPE_CIDR, dict_cidr_open, DICT_TYPE_THASH, dict_thash_open, + DICT_TYPE_FAIL, dict_fail_open, 0, }; diff --git a/postfix/src/util/dict_regexp.ref b/postfix/src/util/dict_regexp.ref index 62d05f8d6..589300dc2 100644 --- a/postfix/src/util/dict_regexp.ref +++ b/postfix/src/util/dict_regexp.ref @@ -1,4 +1,5 @@ -./dict_open: warning: regexp map dict_regexp.map, line 1: ignoring extra text after IF +./dict_open: warning: regexp map dict_regexp.map, line 1: ignoring extra text after IF statement: "fodder" +./dict_open: warning: regexp map dict_regexp.map, line 1: do not prepend whitespace to statements between IF and ENDIF ./dict_open: warning: regexp map dict_regexp.map, line 5: ignoring extra text after ENDIF ./dict_open: warning: regexp map dict_regexp.map, line 9: using empty replacement string ./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule diff --git a/postfix/src/util/dict_static.c b/postfix/src/util/dict_static.c index 7c9cabcb6..723a24dcf 100644 --- a/postfix/src/util/dict_static.c +++ b/postfix/src/util/dict_static.c @@ -6,7 +6,7 @@ /* SYNOPSIS /* #include /* -/* DICT *dict_static_open(name, dummy, dict_flags) +/* DICT *dict_static_open(name, name, dict_flags) /* const char *name; /* int dummy; /* int dict_flags; @@ -14,8 +14,6 @@ /* dict_static_open() implements a dummy dictionary that returns /* as lookup result the dictionary name, regardless of the lookup /* key value. -/* -/* The \fIdummy\fR argument is ignored. /* SEE ALSO /* dict(3) generic dictionary manager /* LICENSE diff --git a/postfix/src/util/dict_test.c b/postfix/src/util/dict_test.c index eb8d2cb59..b2f57dfa9 100644 --- a/postfix/src/util/dict_test.c +++ b/postfix/src/util/dict_test.c @@ -43,6 +43,7 @@ void dict_test(int argc, char **argv) int ch; int dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE; int n; + int rc; signal(SIGPIPE, SIG_IGN); @@ -98,15 +99,16 @@ void dict_test(int argc, char **argv) if (strcmp(cmd, "verbose") == 0 && !key) { msg_verbose++; } else if (strcmp(cmd, "del") == 0 && key && !value) { - if (dict_del(dict, key)) + if ((rc = dict_del(dict, key)) > 0) vstream_printf("%s: not found\n", key); + else if (rc < 0) + vstream_printf("%s: error\n", key); else vstream_printf("%s: deleted\n", key); } else if (strcmp(cmd, "get") == 0 && key && !value) { if ((value = dict_get(dict, key)) == 0) { - vstream_printf("%s: %s\n", key, - dict_errno == DICT_ERR_RETRY ? - "soft error" : "not found"); + vstream_printf("%s: %s\n", key, dict_errno ? + "error" : "not found"); } else { vstream_printf("%s=%s\n", key, value); } @@ -115,23 +117,21 @@ void dict_test(int argc, char **argv) dict_errno = 0; dict_put(dict, key, value); if (dict_errno) - vstream_printf("%s: soft error\n", key); + vstream_printf("%s: error\n", key); else vstream_printf("%s=%s\n", key, value); } else if (strcmp(cmd, "first") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else - vstream_printf("%s\n", - dict_errno == DICT_ERR_RETRY ? - "soft error" : "not found"); + vstream_printf("%s\n", dict_errno ? + "error" : "not found"); } else if (strcmp(cmd, "next") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else - vstream_printf("%s\n", - dict_errno == DICT_ERR_RETRY ? - "soft error" : "not found"); + vstream_printf("%s\n", dict_errno ? + "error" : "not found"); } else if (strcmp(cmd, "flags") == 0 && !key && !value) { vstream_printf("dict flags %s\n", dict_flags_str(dict->flags)); diff --git a/postfix/src/util/match_list.c b/postfix/src/util/match_list.c index 7832e95ea..b63ac5ccf 100644 --- a/postfix/src/util/match_list.c +++ b/postfix/src/util/match_list.c @@ -35,6 +35,9 @@ /* The hostname pattern foo.com matches any name within the domain /* foo.com. If this flag is cleared, foo.com matches itself /* only, and .foo.com matches any name below the domain foo.com. +/* .IP MATCH_FLAG_RETURN +/* Return a negative result (MATCH_ERR_TEMP or MATCH_ERR_FAIL) +/* instead of raising a fatal run-time error. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. /* The pattern_list argument specifies a list of patterns. The third @@ -118,7 +121,7 @@ static ARGV *match_list_parse(ARGV *list, char *string, int init_match) while ((start = mystrtok(&bp, delim)) != 0) { if (*start == '#') { msg_warn("%s: comment at end of line is not supported: %s %s", - myname, start, bp); + myname, start, bp); break; } for (match = init_match, item = start; *item == '!'; item++) @@ -188,7 +191,7 @@ MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,... /* match_list_match - match strings against pattern list */ -int match_list_match(MATCH_LIST * list,...) +int match_list_match(MATCH_LIST *list,...) { const char *myname = "match_list_match"; char **cpp; @@ -196,6 +199,7 @@ int match_list_match(MATCH_LIST * list,...) int match; int i; va_list ap; + int rc; /* * Iterate over all patterns in the list, stop at the first match. @@ -209,8 +213,11 @@ int match_list_match(MATCH_LIST * list,...) for (match = 1; *pat == '!'; pat++) match = !match; for (i = 0; i < list->match_count; i++) - if (list->match_func[i] (list->flags, list->match_args[i], pat)) + if ((rc = list->match_func[i] (list->flags, + list->match_args[i], pat)) > 0) return (match); + else if (rc < 0) + return (rc); } if (msg_verbose) for (i = 0; i < list->match_count; i++) @@ -220,7 +227,7 @@ int match_list_match(MATCH_LIST * list,...) /* match_list_free - release storage */ -void match_list_free(MATCH_LIST * list) +void match_list_free(MATCH_LIST *list) { argv_free(list->patterns); myfree((char *) list->match_func); diff --git a/postfix/src/util/match_list.h b/postfix/src/util/match_list.h index 910ae713b..cbbc71a36 100644 --- a/postfix/src/util/match_list.h +++ b/postfix/src/util/match_list.h @@ -11,6 +11,11 @@ /* DESCRIPTION /* .nf + /* + * Utility library. + */ +#include + /* * External interface. */ diff --git a/postfix/src/util/match_ops.c b/postfix/src/util/match_ops.c index 5832266b1..d1cf85053 100644 --- a/postfix/src/util/match_ops.c +++ b/postfix/src/util/match_ops.c @@ -37,6 +37,9 @@ /* The hostname pattern foo.com matches itself and any name below /* the domain foo.com. If this flag is cleared, foo.com matches itself /* only, and .foo.com matches any name below the domain foo.com. +/* .IP MATCH_FLAG_RETURN +/* Return MATCH_ERR_TEMP or MATCH_ERR_PERM, instead of raising +/* a fatal run-time error. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. /* @@ -81,9 +84,37 @@ #define MATCH_DICTIONARY(pattern) \ ((pattern)[0] != '[' && strchr((pattern), ':') != 0) +/* match_error - return or raise fatal error */ + +static int match_error(int flags, int err_val, const char *fmt,...) +{ + VSTRING *buf = vstring_alloc(100); + va_list ap; + + /* + * In case arguments get swapped after some code change. + */ + if (err_val >= 0) + msg_panic("match_error: bad error value: %d", err_val); + + /* + * Report, and maybe return. + */ + va_start(ap, fmt); + vstring_vsprintf(buf, fmt, ap); + va_end(ap); + if (flags & MATCH_FLAG_RETURN) { + msg_warn("%s", vstring_str(buf)); + } else { + msg_fatal("%s", vstring_str(buf)); + } + vstring_free(buf); + return (err_val); +} + /* match_string - match a string literal */ -int match_string(int unused_flags, const char *string, const char *pattern) +int match_string(int flags, const char *string, const char *pattern) { const char *myname = "match_string"; int match; @@ -99,7 +130,8 @@ int match_string(int unused_flags, const char *string, const char *pattern) if (match != 0) return (1); if (dict_errno != 0) - msg_fatal("%s: table lookup problem", pattern); + return (match_error(flags, MATCH_ERR_TEMP, + "%s: table lookup problem", pattern)); return (0); } @@ -149,7 +181,8 @@ int match_hostname(int flags, const char *name, const char *pattern) if (match != 0) break; if (dict_errno != 0) - msg_fatal("%s: table lookup problem", pattern); + return (match_error(flags, MATCH_ERR_TEMP, + "%s: table lookup problem", pattern)); } if ((next = strchr(entry + 1, '.')) == 0) break; @@ -185,7 +218,7 @@ int match_hostname(int flags, const char *name, const char *pattern) /* match_hostaddr - match host by address */ -int match_hostaddr(int unused_flags, const char *addr, const char *pattern) +int match_hostaddr(int flags, const char *addr, const char *pattern) { const char *myname = "match_hostaddr"; char *saved_patt; @@ -208,7 +241,8 @@ int match_hostaddr(int unused_flags, const char *addr, const char *pattern) if (dict_lookup(pattern, addr) != 0) return (1); if (dict_errno != 0) - msg_fatal("%s: table lookup problem", pattern); + return (match_error(flags, MATCH_ERR_TEMP, + "%s: table lookup problem", pattern)); return (0); } @@ -260,8 +294,9 @@ int match_hostaddr(int unused_flags, const char *addr, const char *pattern) * everything into to binary form, and to do the comparison there. */ saved_patt = mystrdup(pattern); - if ((err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0)) != 0) - msg_fatal("%s", vstring_str(err)); + err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0); myfree(saved_patt); + if (err != 0) + return (match_error(flags, MATCH_ERR_PERM, "%s", vstring_str(err))); return (cidr_match_execute(&match_info, addr) != 0); } diff --git a/postfix/src/util/match_ops.h b/postfix/src/util/match_ops.h index e147f7b50..e8c8142f5 100644 --- a/postfix/src/util/match_ops.h +++ b/postfix/src/util/match_ops.h @@ -15,7 +15,11 @@ #define MATCH_FLAG_NONE 0 #define MATCH_FLAG_PARENT (1<<0) -#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT) +#define MATCH_FLAG_RETURN (1<<1) +#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT | MATCH_FLAG_RETURN) + +#define MATCH_ERR_TEMP (-1) /* temporary error, e.g., database */ +#define MATCH_ERR_PERM (-2) /* permanent error, e.g., syntax */ extern int match_string(int, const char *, const char *); extern int match_hostname(int, const char *, const char *); diff --git a/postfix/src/util/myaddrinfo.ref b/postfix/src/util/myaddrinfo.ref index bc7360101..f0da580cb 100644 --- a/postfix/src/util/myaddrinfo.ref +++ b/postfix/src/util/myaddrinfo.ref @@ -1,6 +1,6 @@ ./myaddrinfo: === hostname belly.porcupine.org === -./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2001:240:587:0:250:56ff:fe10:bd03 -./myaddrinfo: 2001:240:587:0:250:56ff:fe10:bd03 -> belly.porcupine.org +./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2604:8d00:189::6 +./myaddrinfo: 2604:8d00:189::6 -> belly.porcupine.org ./myaddrinfo: belly.porcupine.org -> family=2 sock=1 proto=6 168.100.189.6 ./myaddrinfo: 168.100.189.6 -> belly.porcupine.org ./myaddrinfo: === host address 168.100.189.2 ===