]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-19990910
authorWietse Venema <wietse@porcupine.org>
Fri, 10 Sep 1999 05:00:00 +0000 (00:00 -0500)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:09:45 +0000 (18:09 -0500)
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/sample-smtpd.cf
postfix/global/mail_params.h
postfix/global/mail_version.h
postfix/global/maps.c
postfix/global/maps.h
postfix/html/uce.html
postfix/smtpd/smtpd_check.c

index 99f4fa1d79de206ea305574eba1dd11e9827cdf2..3aba22e8385814d2af4c88df8a6126ca0e4a7a6b 100644 (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.
index 8e45a440133223a2d6c2a93fc7c0932d9e0582ea..b4eae12becff6dec48e917d5d6f565b2b9eb60e7 100644 (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
 ==========================================
index 7e622453888db7f7fc660d77845a5ee1b4ce8776..1e2fd83a9cb758b999211d3926901776b5494887 100644 (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.
index 32a95a91af4440c0ab07339098869b67a1d84e7b..1bdc983be383f034714320fd003db7eec32abdf5 100644 (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.
index f96a226a381ee9f9a867d1ea4f25caa2e01abd7a..fb5098d38eb2dda8d81cfb37f232e293244a340a 100644 (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
index e6fd5ecc7a0a5065b47a41e23fe87eef4b7c6b96..9c13958b4323b98f560fee0db4544cf06aae21be 100644 (file)
 /*     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;
 /*     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.
 
 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);
 }
index 015811f699ebc7e1363b9f8e86ef38e77d111103..d6be6b1aab076b555a367e2a470efff6bb62a890 100644 (file)
 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 *);
 
index 1ccc8558c3838e0da28779d75863618b1bae5f42..84abddfbcf33daca847141261629d3b38a24ad49 100644 (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
index 1cdd34ba5f2c5ee91cda4ac039a6a698df8c4400..5eb0d4d981bac839c36abe86aea31252301eb44c 100644 (file)
 /*     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 
+/*     table. Lookups are done in the same way as with virtual and
 /*     canonical maps.
 /* .IP restriction_classes
 /*     Defines a list of parameter names, each parameter being a list
@@ -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;
            }