2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 14:17:41 +00:00

snapshot-19990910

This commit is contained in:
Wietse Venema
1999-09-10 00:00:00 -05:00
parent f90b3d19a4
commit 8d980f39f7
9 changed files with 148 additions and 83 deletions

View File

@@ -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.

View File

@@ -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
==========================================

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 *);

View File

@@ -597,7 +597,7 @@ response code to rejected requests (default: <b>504</b>).
<p>
<dt> <b>permit_address_map</b> <i>maptype</i>:<i>mapname</i> <dd>
<dt> <b>permit_recipient_map</b> <i>maptype</i>:<i>mapname</i> <dd>
Permit the request when the recipient address matches the named
table. Table lookup is done as with the <a
href="virtual.5.html">virtual</a> and <a

View File

@@ -135,7 +135,7 @@
/* Allow the request when the local mail system is mail exchanger
/* for the recipient domain (this includes the case where the local
/* system is the final destination).
/* .IP permit_address_map maptype:mapname
/* .IP permit_recipient_map maptype:mapname
/* Permit the request when the recipient address matches the named
/* table. Lookups are done in the same way as with virtual and
/* canonical maps.
@@ -315,7 +315,7 @@ static ARGV *etrn_restrctions;
static HTABLE *smtpd_rest_classes;
static HTABLE *smtpd_addr_maps;
static HTABLE *smtpd_rcpt_maps;
/*
* The routine that recursively applies restrictions.
@@ -413,8 +413,8 @@ void smtpd_check_init(void)
}
/*
* This is the place to specify definitions for complex restrictions
* such as check_relay_domains in terms of more elementary restrictions.
* This is the place to specify definitions for complex restrictions such
* as check_relay_domains in terms of more elementary restrictions.
*/
#if 0
htable_enter("check_relay_domains",
@@ -424,7 +424,7 @@ void smtpd_check_init(void)
/*
* Other one-off initializations.
*/
smtpd_addr_maps = htable_create(1);
smtpd_rcpt_maps = htable_create(1);
}
/* smtpd_check_reject - do the boring things that must be done */
@@ -999,14 +999,14 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr,
return (reject_unknown_mailhost(state, domain, reply_name, reply_class));
}
/* permit_addr_map - permit if address matches rewriting table */
/* permit_rcpt_map - permit if recipient address matches rewriting table */
static int permit_addr_map(SMTPD_STATE *state, char *table,
char *reply_name, char *reply_class)
static int permit_rcpt_map(char *table, char *reply_name)
{
char *myname = "permit_addr_map";
char *myname = "permit_rcpt_map";
char *domain;
MAPS *map;
DICT *dict;
if (msg_verbose)
msg_info("%s: %s %s", myname, table, reply_name);
@@ -1029,11 +1029,16 @@ static int permit_addr_map(SMTPD_STATE *state, char *table,
/*
* Look up the name in the specified table, using the usual magic of
* canonical and virtual maps.
* canonical and virtual maps. Be sure this map was declared in a main.cf
* restriction or restriction class. The maps must be opened before the
* process enters a chroot jail.
*/
if ((map = (MAPS *) htable_find(smtpd_addr_maps, table)) == 0) {
map = maps_create("addr_map", table, DICT_FLAG_LOCK);
htable_enter(smtpd_addr_maps, table, (char *) map);
if ((map = (MAPS *) htable_find(smtpd_rcpt_maps, table)) == 0) {
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
map = maps_create("rcpt_map", "", DICT_FLAG_LOCK);
maps_append(map, table, dict);
htable_enter(smtpd_rcpt_maps, table, (char *) map);
}
#define TOSS_THE_EXTENSION ((char **) 0)
@@ -1092,8 +1097,20 @@ static int check_table_result(SMTPD_STATE *state, char *table,
return (SMTPD_CHECK_OK);
/*
* Unfortunately, maps must be declared ahead of time so they can be
* opened before we go to jail. We could insist that the RHS can only
* contain a pre-defined restriction class name, but that would be too
* restrictive. Instead we warn if an access table references any map.
*
* XXX Don't use passwd files or address rewriting maps as access tables.
*/
if (strchr(value, ':') != 0) {
msg_warn("SMTPD access map %s has entry with lookup table: %s",
table, value);
msg_warn("do not specify lookup tables inside SMTPD access maps");
msg_warn("define a restriction class and specify its name instead");
longjmp(smtpd_check_buf, -1);
}
restrictions = argv_split(value, " \t\r\n,");
status = generic_checks(state, restrictions, reply_name,
reply_class, def_acl);
@@ -1149,13 +1166,13 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
msg_info("%s: %s", myname, domain);
/*
* Try the name and its parent domains. Don't try top-level domains.
* Try the name and its parent domains. Including top-level domains.
*/
#define CHK_DOMAIN_RETURN(x) { myfree(low_domain); return(x); }
for (name = low_domain; (next = strchr(name, '.')) != 0; name = next + 1) {
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
for (name = low_domain; /* void */ ; name = next + 1) {
if (flags == 0 || (flags & dict->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;
}