diff --git a/postfix/HISTORY b/postfix/HISTORY index 99f4fa1d7..3aba22e83 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -3060,19 +3060,32 @@ Apologies for any names omitted. Performance: added one-entry cache to the address rewriting client and to the address resolving client. This is because UCE restrictions tend to produce the same query repeatedly. + Files: global/rewrite_clnt.c, global/resolve_clnt.c. Feature: the UCE restrictions are now fully recursive so you can have per-client/helo/sender/recipient restrictions. Instead of OK, REJECT or [45]xx, you can specify a sequence of restrictions on the right-hand side of an SMTPD access table. This means you can no longer use canonical/virtual/alias - maps as SMTPD access tables. But the loss is compensated for. + maps as SMTPD access tables. But the loss is compensated + for. File: smtpd/smtpd_access.c. Feature: restriction classes, essentially a short-hand for restriction lists. These short hands are useful mostly on - the right-hand side of SMTPD access tables. + the right-hand side of SMTPD access tables. You must use + restriction classes in order to have lookup tables on the + right-hand side of an SMTPD access table. File: + smtpd/smtpd_access.c. - Feature: "permit_address_map maptype:mapname" permits a + Feature: "permit_recipient_map maptype:mapname" permits a recipient address when it matches the specified table. Lookups are done just as with canonical/virtual maps. With this, you can also use passwd/aliases as SMTPD access maps. + File: smtpd/smtpd_access.c. + +19990910 + + Changed "permit_address_map" into "permit_recipient_map" + and added a test for the case that they specify a lookup + table on the right-hand side of an SMTPD access map. + File: smtpd/smtpd_access.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 8e45a4401..b4eae12be 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,17 +1,19 @@ -Incompatible changes with snapshot 19990909 +Incompatible changes with snapshot 19990910 =========================================== - You can not longer use virtual, canonical or aliases tables as -SMTPD access control tables. Use the permit_address_map feature +SMTPD access control tables. Use the permit_recipient_map feature instead. The loss is compensated for. -Major changes with snapshot 19990909 +Major changes with snapshot 19990910 ==================================== - Per-client/helo/sender/recipient UCE restrictions: you can now specify arbitrary restrictions on the right-hand side of SMTPD -access tables. The only anomaly in this scheme is that header -checks are the same for every message. +access tables. The only anomalies in this scheme are (1) header +checks are the same for every message, and (2) you must use a +restriction class (see below) in order to specify a lookup table +on the right-hand side of an access table. - Restriction classes allow you to conveniently group restrictions under one name. This is great for per-client/helo/sender/recipient @@ -26,25 +28,30 @@ your per-client/helo/sender/recipient SMTPD access tables. - Reject mail for non-existent local accounts. You can now use passwd/canonical/virtual/aliases tables for SMTPD access control. -For example, specify in main.cf: - relay_domains = $mydestination other domains... +For example, a non-relaying site would specify in main.cf: + smtpd_recipient_restrictions = - reject_unauth_destination - permit_address_map unix:passwd.byname - permit_address_map hash:/etc/canonical - permit_address_map hash:/etc/postfix/virtual - permit_address_map hash:/etc/aliases + permit_recipient_map unix:passwd.byname + permit_recipient_map hash:/etc/canonical + permit_recipient_map hash:/etc/postfix/virtual + permit_recipient_map hash:/etc/aliases reject That should stop a lot of the mail to non-existent recipients. It won't stop mail to broken aliases or to users with broken .forward files, though. -Unfortunately, permit_address_map does not combine well with -check_relay_domains, because that restriction ALWAYS permits mail -for local destinations. Instead of check_relay_domains, use some -combination of permit_mynetworks and reject_unauth_destination. +All this is great for non-relaying sites. A good example with +permit_recipient_map for relaying sites still needs to be found. + +Unfortunately, permit_recipient_map does not combine well with +permit_mynetworks, because permit_mynetworks accepts mail for ALL +destinations, including ALL LOCAL destinations. + +Unfortunately, permit_recipient_map does not combine well with +check_relay_domains, because check_relay_domains permits mail for +ALL LOCAL destinations. Incompatible changes with postfix-19990906 ========================================== diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index 7e6224538..1e2fd83a9 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -203,7 +203,7 @@ smtpd_sender_restrictions = # reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form # reject_non_fqdn_sender: reject sender address that is not in FQDN form # reject_non_fqdn_recipient: reject recipient address that is not in FQDN form -# permit_address_map maptype:mapname: permit if the recipient address matches +# permit_recipient_map maptype:mapname: permit if the recipient matches # the table. Matching is as with virtual/canonical tables. # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index 32a95a91a..1bdc983be 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -799,7 +799,7 @@ extern int var_smtpd_delay_reject; #define REJECT_UNAUTH_PIPE "reject_unauth_pipelining" -#define PERMIT_ADDR_MAP "permit_address_map" +#define PERMIT_RCPT_MAP "permit_recipient_map" /* * Other. diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index f96a226a3..fb5098d38 100644 --- a/postfix/global/mail_version.h +++ b/postfix/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-19990909" +#define DEF_MAIL_VERSION "Snapshot-19990910" extern char *var_mail_version; /* LICENSE diff --git a/postfix/global/maps.c b/postfix/global/maps.c index e6fd5ecc7..9c13958b4 100644 --- a/postfix/global/maps.c +++ b/postfix/global/maps.c @@ -11,6 +11,11 @@ /* const char *map_names; /* int flags; /* +/* MAPS *maps_append(maps, map_name, dict_handle) +/* MAPS *maps; +/* const char *map_name; +/* DICT *dict_handle; +/* /* const char *maps_find(maps, key, flags) /* MAPS *maps; /* const char *key; @@ -30,6 +35,10 @@ /* other maps_xxx() operations. /* See dict_open(3) for a description of flags. /* +/* maps_append() appends a dictionary to an existing handle +/* under the given name. If dict_handle is a null pointer, +/* the named dictionary is opened on the fly. +/* /* maps_find() searches the specified list of dictionaries /* in the specified order for the named key. The result is in /* memory that is overwritten upon each call. @@ -104,12 +113,10 @@ MAPS *maps_create(const char *title, const char *map_names, int flags) { - char *myname = "maps_create"; - char *temp = mystrdup(map_names); - char *bufp = temp; + char *temp; + char *bufp; static char sep[] = " \t,\r\n"; MAPS *maps; - DICT *dict; char *map_type_name; /* @@ -118,23 +125,36 @@ MAPS *maps_create(const char *title, const char *map_names, int flags) maps = (MAPS *) mymalloc(sizeof(*maps)); maps->title = mystrdup(title); maps->argv = argv_alloc(2); + maps->flags = flags; /* * For each specified type:name pair, either register a new dictionary, * or increment the reference count of an existing one. */ - while ((map_type_name = mystrtok(&bufp, sep)) != 0) { - if (msg_verbose) - msg_info("%s: %s", myname, map_type_name); - if ((dict = dict_handle(map_type_name)) == 0) - dict = dict_open(map_type_name, O_RDONLY, flags); - else if ((dict->flags & flags) != flags) - msg_warn("%s: map %s has flags 0%o, want flags 0%o", - myname, map_type_name, dict->flags, flags); - dict_register(map_type_name, dict); - argv_add(maps->argv, map_type_name, ARGV_END); + if (*map_names) { + bufp = temp = mystrdup(map_names); + while ((map_type_name = mystrtok(&bufp, sep)) != 0) + maps_append(maps, map_type_name, dict_handle(map_type_name)); + myfree(temp); } - myfree(temp); + return (maps); +} + +/* maps_append - append dictionary */ + +MAPS *maps_append(MAPS *maps, const char *map_type_name, DICT *dict) +{ + char *myname = "maps_append"; + + if (msg_verbose) + msg_info("%s: %s", myname, map_type_name); + if (dict == 0) + dict = dict_open(map_type_name, O_RDONLY, maps->flags); + if ((dict->flags & maps->flags) != maps->flags) + msg_warn("%s: map %s has flags 0%o, want flags 0%o", + myname, map_type_name, dict->flags, maps->flags); + dict_register(map_type_name, dict); + argv_add(maps->argv, map_type_name, ARGV_END); argv_terminate(maps->argv); return (maps); } diff --git a/postfix/global/maps.h b/postfix/global/maps.h index 015811f69..d6be6b1aa 100644 --- a/postfix/global/maps.h +++ b/postfix/global/maps.h @@ -22,9 +22,11 @@ typedef struct MAPS { char *title; struct ARGV *argv; + int flags; } MAPS; extern MAPS *maps_create(const char *, const char *, int); +extern MAPS *maps_append(MAPS *, const char *, DICT *); extern const char *maps_find(MAPS *, const char *, int); extern MAPS *maps_free(MAPS *); diff --git a/postfix/html/uce.html b/postfix/html/uce.html index 1ccc8558c..84abddfbc 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -597,7 +597,7 @@ response code to rejected requests (default: 504).

-

permit_address_map maptype:mapname
+
permit_recipient_map maptype:mapname
Permit the request when the recipient address matches the named table. Table lookup is done as with the virtual and flags) != 0) { if ((value = dict_get(dict, name)) != 0) CHK_DOMAIN_RETURN(check_table_result(state, table, value, @@ -1164,6 +1181,8 @@ static int check_domain_access(SMTPD_STATE *state, char *table, if (dict_errno != 0) msg_fatal("%s: table lookup problem", table); } + if ((next = strchr(name, '.')) == 0) + break; flags = PARTIAL; } CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO); @@ -1189,9 +1208,9 @@ static int check_addr_access(SMTPD_STATE *state, char *table, */ addr = STR(vstring_strcpy(error_text, address)); + if ((dict = dict_handle(table)) == 0) + msg_panic("%s: dictionary not found: %s", myname, table); do { - if ((dict = dict_handle(table)) == 0) - msg_panic("%s: dictionary not found: %s", myname, table); if (flags == 0 || (flags & dict->flags) != 0) { if ((value = dict_get(dict, addr)) != 0) return (check_table_result(state, table, value, address, @@ -1392,13 +1411,9 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, char *myname = "generic_checks"; char **cpp; char *name; - int status; + int status = 0; ARGV *list; - status = setjmp(smtpd_check_buf); - if (status != 0) - return (0); - if (msg_verbose) msg_info("%s: START", myname); @@ -1545,10 +1560,9 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, if (state->recipient) status = reject_non_fqdn_address(state, state->recipient, state->recipient, SMTPD_NAME_RECIPIENT); - } else if (is_map_command(name, PERMIT_ADDR_MAP, &cpp)) { + } else if (is_map_command(name, PERMIT_RCPT_MAP, &cpp)) { if (state->recipient) - status = permit_addr_map(state, *cpp, - state->recipient, SMTPD_NAME_RECIPIENT); + status = permit_rcpt_map(*cpp, state->recipient); } /* @@ -1603,8 +1617,10 @@ char *smtpd_check_client(SMTPD_STATE *state) /* * Apply restrictions in the order as specified. */ - status = generic_checks(state, client_restrctions, state->namaddr, - SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL); + status = setjmp(smtpd_check_buf); + if (status == 0 && client_restrctions->argc) + status = generic_checks(state, client_restrctions, state->namaddr, + SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL); return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } @@ -1646,8 +1662,10 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost) /* * Apply restrictions in the order as specified. */ - status = generic_checks(state, helo_restrctions, state->helo_name, - SMTPD_NAME_HELO, CHECK_HELO_ACL); + status = setjmp(smtpd_check_buf); + if (status == 0 && helo_restrctions->argc) + status = generic_checks(state, helo_restrctions, state->helo_name, + SMTPD_NAME_HELO, CHECK_HELO_ACL); SMTPD_CHECK_HELO_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } @@ -1679,8 +1697,10 @@ char *smtpd_check_mail(SMTPD_STATE *state, char *sender) /* * Apply restrictions in the order as specified. */ - status = generic_checks(state, mail_restrctions, sender, - SMTPD_NAME_SENDER, CHECK_SENDER_ACL); + status = setjmp(smtpd_check_buf); + if (status == 0 && mail_restrctions->argc) + status = generic_checks(state, mail_restrctions, sender, + SMTPD_NAME_SENDER, CHECK_SENDER_ACL); SMTPD_CHECK_MAIL_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } @@ -1722,7 +1742,9 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) /* * Apply restrictions in the order as specified. */ - status = generic_checks(state, rcpt_restrctions, + status = setjmp(smtpd_check_buf); + if (status == 0 && rcpt_restrctions->argc) + status = generic_checks(state, rcpt_restrctions, recipient, SMTPD_NAME_RECIPIENT, CHECK_RECIP_ACL); SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); @@ -1764,8 +1786,10 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) /* * Apply restrictions in the order as specified. */ - status = generic_checks(state, etrn_restrctions, domain, - SMTPD_NAME_ETRN, CHECK_ETRN_ACL); + status = setjmp(smtpd_check_buf); + if (status == 0 && etrn_restrctions->argc) + status = generic_checks(state, etrn_restrctions, domain, + SMTPD_NAME_ETRN, CHECK_ETRN_ACL); SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } @@ -1789,7 +1813,6 @@ char *smtpd_check_size(SMTPD_STATE *state, off_t size) return (STR(error_text)); } fsspace(".", &fsbuf); - if (msg_verbose) msg_info("%s: blocks %lu avail %lu min_free %lu size %lu", myname, @@ -1953,9 +1976,9 @@ static int int_update(char **argv) typedef struct { char *name; ARGV **target; -} SMTPD_REST_TABLE; +} REST_TABLE; -static SMTPD_REST_TABLE smtpd_rest_table[] = { +static REST_TABLE rest_table[] = { "client_restrictions", &client_restrctions, "helo_restrictions", &helo_restrctions, "sender_restrictions", &mail_restrctions, @@ -1964,13 +1987,13 @@ static SMTPD_REST_TABLE smtpd_rest_table[] = { 0, }; -/* smtpd_rest_update - update restriction */ +/* rest_update - update restriction */ -static int smtpd_rest_update(char **argv) +static int rest_update(char **argv) { - SMTPD_REST_TABLE *rp; + REST_TABLE *rp; - for (rp = smtpd_rest_table; rp->name; rp++) { + for (rp = rest_table; rp->name; rp++) { if (strcasecmp(rp->name, argv[0]) == 0) { argv_free(rp->target[0]); rp->target[0] = smtpd_check_parse(argv[1]); @@ -2111,7 +2134,7 @@ main(int argc, char **argv) } if (int_update(args->argv) || string_update(args->argv) - || smtpd_rest_update(args->argv)) { + || rest_update(args->argv)) { resp = 0; break; }