]> git.pld-linux.org Git - packages/postfix.git/commitdiff
- ``unofficial patch for Postfix 2.0 to black-list domain names
authoreothane <eothane@pld-linux.org>
Fri, 19 Sep 2003 22:20:22 +0000 (22:20 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
  by their mail server (such as Verisign's mail server for
  non-existent .com or .net domain names) or by their DNS servers.''

Changed files:
    postfix-ns-mx-acl.patch -> 1.1

postfix-ns-mx-acl.patch [new file with mode: 0644]

diff --git a/postfix-ns-mx-acl.patch b/postfix-ns-mx-acl.patch
new file mode 100644 (file)
index 0000000..6c29adc
--- /dev/null
@@ -0,0 +1,478 @@
+This is an unofficial patch for Postfix stable release 2.0 that
+back-ports a new feature from the after-2.0 snapshot releases.
+
+This feature can be used to block mail from so-called spammer
+havens, from sender addresses that resolve to Verisign's wild-card
+mail responder, or from domains that claim to have mail servers in
+reserved networks such as 127.0.0.1.
+
+This patch is a revised version; the first implementation of the
+check_{helo,sender,recipient}_ns_access feature did not correctly
+look up name server records and caused mail to be deferred with a
+450 status code; the second revision no longer defers mail when
+some NS or MX host lookup fails.
+
+-----------------
+
+The check_{helo,sender,recipient}_{ns,mx}_access maptype:mapname
+restriction applies the specified access table to the NS or MX
+hosts of the host/domain given in HELO, EHLO, MAIL FROM or RCPT TO
+commands.
+
+    /etc/postfix/main.cf:
+        smtpd_mumble_restrictions =
+            ...
+            reject_unknown_sender_domain
+            check_sender_mx_access hash:/etc/postfix/mx_access
+            ...
+
+    /etc/postfix/mx_access:
+        spammer.haven.tld reject spammer mx host
+        64.94.110.11      reject mail server in verisign wild-card domain
+        127               reject mail server in loopback network
+        0                 reject mail server in broadcast network
+
+The following entries block mail from domains that claim to have
+have mail servers or domain servers in reserved networks.
+
+        10                reject mail server in RFC 1918 private network
+        169.254           reject mail server in link local network
+        172.16            reject mail server in RFC 1918 private network
+        ...similar entries for 172.17...172.31
+        192.0.2           reject mail server in TEST-NET network
+        192.168           reject mail server in RFC 1918 private network
+        224               reject mail server in class D multicast network
+        ...similar entries for 225...239
+        240               reject mail server in class E reserved network
+        ...similar entries for 241...247
+        248               reject mail server in reserved network
+        ...similar entries for 249...255
+
+diff -cr /tmp/postfix-2.0.16/conf/sample-smtpd.cf ./conf/sample-smtpd.cf
+*** /tmp/postfix-2.0.16/conf/sample-smtpd.cf   Tue Aug 12 12:28:46 2003
+--- ./conf/sample-smtpd.cf     Fri Sep 19 11:17:34 2003
+***************
+*** 311,316 ****
+--- 311,321 ----
+  #   check_helo_access maptype:mapname
+  #    look up HELO hostname or parent domains.
+  #    see access(5) for possible lookup results.
++ #   check_helo_mx_access maptype:mapname
++ #   check_helo_ns_access maptype:mapname
++ #    look up the helo hostname MX hosts (or name servers) and apply the
++ #    specified access table to those hosts.
++ #    Note: the OK result is not allowed here for security reasons.
+  #   reject: reject the request. Place this at the end of a restriction.
+  #   permit: permit the request. Place this at the end of a restriction.
+  #   warn_if_reject: next restriction logs a warning instead of rejecting.
+***************
+*** 343,348 ****
+--- 348,358 ----
+  #   check_sender_access maptype:mapname
+  #    look up sender address, parent domain, or localpart@.
+  #    see access(5) for possible lookup results.
++ #   check_sender_mx_access maptype:mapname
++ #   check_sender_ns_access maptype:mapname
++ #    look up sender address MX hosts (or name servers) and apply the
++ #    specified access table to those hosts.
++ #    Note: the OK result is not allowed here for security reasons.
+  #   reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies
+  #    a MAIL FROM address owner, but the client is not (SASL) logged in as
+  #    that MAIL FROM address owner; or if the client is (SASL) logged in, but
+***************
+*** 409,414 ****
+--- 419,429 ----
+  #   check_recipient_access maptype:mapname
+  #    look up recipient address, parent domain, or localpart@.
+  #    see access(5) for possible lookup results.
++ #   check_recipient_mx_access maptype:mapname
++ #   check_recipient_ns_access maptype:mapname
++ #    look up the recipient address MX hosts (or name servers) and apply the
++ #    specified access table to those hosts.
++ #    Note: the OK result is not allowed here for security reasons.
+  #   reject_non_fqdn_recipient: reject recipient address that is not in FQDN form
+  #   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 -cr /tmp/postfix-2.0.16/html/uce.html ./html/uce.html
+*** /tmp/postfix-2.0.16/html/uce.html  Mon Aug 25 09:54:11 2003
+--- ./html/uce.html    Fri Sep 19 11:17:34 2003
+***************
+*** 567,572 ****
+--- 567,588 ----
+  
+  <p>
+  
++ <a name="check_helo_ns_access">
++ 
++ <dt> <b>check_helo_ns_access</b> <i>maptype</i>:<i>mapname</i>
++ 
++ <a name="check_helo_mx_access">
++ 
++ <dt> <b>check_helo_mx_access</b> <i>maptype</i>:<i>mapname</i>
++ 
++ <dd> Apply the specified <a href="access.5.html">access database</a>
++ to the DNS (or MX) servers for the host or domain name given with
++ the HELO (or EHLO) command.
++ 
++ <dd> Note: an OK result is not allowed for safety reasons.
++ 
++ <p>
++ 
+  <dt> <b><a href="#permit">permit</a></b>
+  
+  <dt> <b><a href="#defer">defer</a></b>
+***************
+*** 714,719 ****
+--- 730,751 ----
+  
+  <p>
+  
++ <a name="check_sender_ns_access">
++ 
++ <dt> <b>check_sender_ns_access</b> <i>maptype</i>:<i>mapname</i>
++ 
++ <a name="check_sender_mx_access">
++ 
++ <dt> <b>check_sender_mx_access</b> <i>maptype</i>:<i>mapname</i>
++ 
++ <dd> Apply the specified <a href="access.5.html">access database</a>
++ to the DNS (or MX) servers for the host or domain name given with
++ the MAIL FROM command.
++ 
++ <dd> Note: an OK result is not allowed for safety reasons.
++ 
++ <p>
++ 
+  <a name="reject_non_fqdn_sender">
+  
+  <dt> <b>reject_non_fqdn_sender</b> <dd> Reject the request when
+***************
+*** 921,926 ****
+--- 953,974 ----
+  <dt> <i>maptype</i>:<i>mapname</i> <dd> Search the named <a
+  href="access.5.html">access database</a> for the resolved destination
+  address, recipient domain or parent domain, or <i>localpart</i>@. 
++ 
++ <p>
++ 
++ <a name="check_recipient_ns_access">
++ 
++ <dt> <b>check_recipient_ns_access</b> <i>maptype</i>:<i>mapname</i>
++ 
++ <a name="check_recipient_mx_access">
++ 
++ <dt> <b>check_recipient_mx_access</b> <i>maptype</i>:<i>mapname</i>
++ 
++ <dd> Apply the specified <a href="access.5.html">access database</a>
++ to the DNS servers (or MX hosts) for the host or domain name given
++ with the RCPT TO command.
++ 
++ <dd> Note: an OK result is not allowed for safety reasons.
+  
+  <p>
+  
+diff -cr /tmp/postfix-2.0.16/src/dns/dns_lookup.c ./src/dns/dns_lookup.c
+*** /tmp/postfix-2.0.16/src/dns/dns_lookup.c   Sun Dec  8 09:09:11 2002
+--- ./src/dns/dns_lookup.c     Fri Sep 19 11:17:34 2003
+***************
+*** 509,514 ****
+--- 509,515 ----
+           vstring_sprintf(why,
+                  "Name service error for %s: invalid host or domain name",
+                           name);
++      h_errno = HOST_NOT_FOUND;
+       return (DNS_NOTFOUND);
+      }
+  
+***************
+*** 520,525 ****
+--- 521,527 ----
+           vstring_sprintf(why,
+                  "Name service error for %s: invalid host or domain name",
+                           name);
++      h_errno = HOST_NOT_FOUND;
+       return (DNS_NOTFOUND);
+      }
+  
+diff -cr /tmp/postfix-2.0.16/src/global/mail_params.h ./src/global/mail_params.h
+*** /tmp/postfix-2.0.16/src/global/mail_params.h       Mon Mar  3 17:07:03 2003
+--- ./src/global/mail_params.h Fri Sep 19 11:17:35 2003
+***************
+*** 1249,1254 ****
+--- 1249,1261 ----
+  #define CHECK_RECIP_ACL              "check_recipient_access"
+  #define CHECK_ETRN_ACL               "check_etrn_access"
+  
++ #define CHECK_HELO_MX_ACL    "check_helo_mx_access"
++ #define CHECK_SENDER_MX_ACL  "check_sender_mx_access"
++ #define CHECK_RECIP_MX_ACL   "check_recipient_mx_access"
++ #define CHECK_HELO_NS_ACL    "check_helo_ns_access"
++ #define CHECK_SENDER_NS_ACL  "check_sender_ns_access"
++ #define CHECK_RECIP_NS_ACL   "check_recipient_ns_access"
++ 
+  #define WARN_IF_REJECT               "warn_if_reject"
+  
+  #define REJECT_RBL           "reject_rbl"    /* LaMont compatibility */
+diff -cr /tmp/postfix-2.0.16/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c
+*** /tmp/postfix-2.0.16/src/smtpd/smtpd_check.c        Tue Aug 12 10:53:25 2003
+--- ./src/smtpd/smtpd_check.c  Fri Sep 19 11:17:52 2003
+***************
+*** 86,91 ****
+--- 86,103 ----
+  /* .IP "check_recipient_access maptype:mapname"
+  /*   Look up the resolved recipient address in the named access table,
+  /*   any parent domains of the recipient domain, and the localpart@.
++ /* .IP "check_helo_mx_access maptype:mapname"
++ /* .IP "check_sender_mx_access maptype:mapname"
++ /* .IP "check_recipient_mx_access maptype:mapname"
++ /*   Apply the specified access table to the MX server host name and IP
++ /*   addresses for the helo hostname, sender, or recipient, respectively.
++ /*   If no MX record is found the A record is used instead.
++ /* .IP "check_helo_ns_access maptype:mapname"
++ /* .IP "check_sender_ns_access maptype:mapname"
++ /* .IP "check_recipient_ns_access maptype:mapname"
++ /*   Apply the specified access table to the DNS server host name and IP
++ /*   addresses for the helo hostname, sender, or recipient, respectively.
++ /*   If no NS record is found, the parent domain is used instead.
+  /* .IP "check_recipient_maps"
+  /*   Reject recipients not listed as valid local, virtual or relay
+  /*   recipients.
+***************
+*** 455,460 ****
+--- 467,484 ----
+      else \
+       (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2)); \
+      } while (0)
++ #define DEFER_IF_PERMIT3(state, class, fmt, a1, a2, a3) do { \
++     if ((state)->warn_if_reject == 0) \
++      defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3)); \
++     else \
++      (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3)); \
++     } while (0)
++ #define DEFER_IF_PERMIT4(state, class, fmt, a1, a2, a3, a4) do { \
++     if ((state)->warn_if_reject == 0) \
++      defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \
++     else \
++      (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3), (a4)); \
++     } while (0)
+  
+   /*
+    * Cached RBL lookup state.
+***************
+*** 2005,2010 ****
+--- 2029,2151 ----
+      return (SMTPD_CHECK_DUNNO);
+  }
+  
++ /* check_server_access - access control by server host name or address */
++ 
++ static int check_server_access(SMTPD_STATE *state, const char *table,
++                                     const char *name,
++                                     int type,
++                                     const char *reply_name,
++                                     const char *reply_class,
++                                     const char *def_acl)
++ {
++     const char *myname = "check_server_access";
++     const char *domain;
++     int     dns_status;
++     DNS_RR *server_list;
++     DNS_RR *server;
++     int     found = 0;
++     struct in_addr addr;
++     struct hostent *hp;
++     char   *addr_string;
++     int     status;
++     char  **cpp;
++     static DNS_FIXED fixed;
++ 
++     /*
++      * Sanity check.
++      */
++     if (type != T_MX && type != T_NS)
++      msg_panic("%s: unexpected resource type \"%s\" in request",
++                myname, dns_strtype(type));
++ 
++     if (msg_verbose)
++      msg_info("%s: %s %s", myname, dns_strtype(type), name);
++ 
++     /*
++      * Skip over local-part.
++      */
++     if ((domain = strrchr(name, '@')) != 0)
++      domain += 1;
++     else
++      domain = name;
++ 
++     /*
++      * If the domain name does not exist then we apply no restriction.
++      * 
++      * If the domain name exists but no MX record exists, fabricate an MX record
++      * that points to the domain name itself.
++      * 
++      * If the domain name exists but no NS record exists, look up parent domain
++      * NS records.
++      */
++     dns_status = dns_lookup(domain, type, 0, &server_list,
++                          (VSTRING *) 0, (VSTRING *) 0);
++     if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) {
++      if (type == T_MX) {
++          server_list = dns_rr_create(domain, &fixed, 0,
++                                      domain, strlen(domain) + 1);
++          dns_status = DNS_OK;
++      } else if (type == T_NS) {
++          while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
++              domain += 1;
++              dns_status = dns_lookup(domain, type, 0, &server_list,
++                                      (VSTRING *) 0, (VSTRING *) 0);
++              if (dns_status != DNS_NOTFOUND || h_errno != NO_DATA)
++                  break;
++          }
++      }
++     }
++     if (dns_status != DNS_OK) {
++      msg_warn("Unable to look up %s host for %s", dns_strtype(type),
++               domain && domain[1] ? domain : reply_name);
++      return (SMTPD_CHECK_DUNNO);
++     }
++ 
++     /*
++      * No bare returns after this point or we have a memory leak.
++      */
++ #define CHECK_SERVER_RETURN(x) { dns_rr_free(server_list); return(x); }
++ 
++     /*
++      * Check the hostnames first, then the addresses.
++      */
++     for (server = server_list; server != 0; server = server->next) {
++      if ((hp = gethostbyname((char *) server->data)) == 0) {
++          msg_warn("Unable to look up %s host %s for %s %s",
++                   dns_strtype(type), (char *) server->data,
++                   reply_class, reply_name);
++          continue;
++      }
++      if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
++          if (msg_verbose)
++              msg_warn("address type %d length %d for %s",
++                     hp->h_addrtype, hp->h_length, (char *) server->data);
++          continue;                           /* XXX */
++      }
++      if (msg_verbose)
++          msg_info("%s: %s hostname check: %s",
++                   myname, dns_strtype(type), (char *) server->data);
++      if ((status = check_domain_access(state, table, (char *) server->data,
++                                    FULL, &found, reply_name, reply_class,
++                                        def_acl)) != 0 || found)
++          CHECK_SERVER_RETURN(status);
++      if (msg_verbose)
++          msg_info("%s: %s host address check: %s",
++                   myname, dns_strtype(type), (char *) server->data);
++      for (cpp = hp->h_addr_list; *cpp; cpp++) {
++          memcpy((char *) &addr, *cpp, sizeof(addr));
++          addr_string = mystrdup(inet_ntoa(addr));
++          status = check_addr_access(state, table, addr_string, FULL,
++                                     &found, reply_name, reply_class,
++                                     def_acl);
++          myfree(addr_string);
++          if (status != 0 || found)
++              CHECK_SERVER_RETURN(status);
++      }
++     }
++     CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
++ }
++ 
+  /* check_mail_access - OK/FAIL based on mail address lookup */
+  
+  static int check_mail_access(SMTPD_STATE *state, const char *table,
+***************
+*** 2568,2573 ****
+--- 2709,2728 ----
+      }
+  }
+  
++ /* forbid_whitelist - disallow whitelisting */
++ 
++ static void forbid_whitelist(SMTPD_STATE *state, const char *name,
++                                   int status, const char *target)
++ {
++     if (status == SMTPD_CHECK_OK) {
++      msg_warn("restriction %s returns OK for %s", name, target);
++      msg_warn("this is not allowed for security reasons");
++      msg_warn("use DUNNO instead of OK if you want to make an exception");
++      longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_SOFTWARE,
++                                       "451 Server configuration error"));
++     }
++ }
++ 
+  /* generic_checks - generic restrictions */
+  
+  static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
+***************
+*** 2722,2727 ****
+--- 2877,2896 ----
+                                  state->helo_name, SMTPD_NAME_HELO)) == 0)
+                   status = SMTPD_CHECK_OK;
+           }
++      } else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
++          if (state->helo_name) {
++              status = check_server_access(state, *cpp, state->helo_name,
++                                           T_NS, state->helo_name,
++                                           SMTPD_NAME_HELO, def_acl);
++              forbid_whitelist(state, name, status, state->helo_name);
++          }
++      } else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) {
++          if (state->helo_name) {
++              status = check_server_access(state, *cpp, state->helo_name,
++                                           T_MX, state->helo_name,
++                                           SMTPD_NAME_HELO, def_acl);
++              forbid_whitelist(state, name, status, state->helo_name);
++          }
+       } else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
+           if (state->helo_name) {
+               if (*state->helo_name != '[')
+***************
+*** 2760,2765 ****
+--- 2929,2948 ----
+       } else if (strcasecmp(name, REJECT_SENDER_LOGIN_MISMATCH) == 0) {
+           if (state->sender && *state->sender)
+               status = reject_sender_login_mismatch(state, state->sender);
++      } else if (is_map_command(state, name, CHECK_SENDER_NS_ACL, &cpp)) {
++          if (state->sender && *state->sender) {
++              status = check_server_access(state, *cpp, state->sender,
++                                           T_NS, state->sender,
++                                           SMTPD_NAME_SENDER, def_acl);
++              forbid_whitelist(state, name, status, state->sender);
++          }
++      } else if (is_map_command(state, name, CHECK_SENDER_MX_ACL, &cpp)) {
++          if (state->sender && *state->sender) {
++              status = check_server_access(state, *cpp, state->sender,
++                                           T_MX, state->sender,
++                                           SMTPD_NAME_SENDER, def_acl);
++              forbid_whitelist(state, name, status, state->sender);
++          }
+       } else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) {
+           if (cpp[1] == 0)
+               msg_warn("restriction %s requires domain name argument", name);
+***************
+*** 2812,2817 ****
+--- 2995,3014 ----
+           if (state->recipient)
+               status = reject_non_fqdn_address(state, state->recipient,
+                                   state->recipient, SMTPD_NAME_RECIPIENT);
++      } else if (is_map_command(state, name, CHECK_RECIP_NS_ACL, &cpp)) {
++          if (state->recipient && *state->recipient) {
++              status = check_server_access(state, *cpp, state->recipient,
++                                           T_NS, state->recipient,
++                                           SMTPD_NAME_RECIPIENT, def_acl);
++              forbid_whitelist(state, name, status, state->recipient);
++          }
++      } else if (is_map_command(state, name, CHECK_RECIP_MX_ACL, &cpp)) {
++          if (state->recipient && *state->recipient) {
++              status = check_server_access(state, *cpp, state->recipient,
++                                           T_MX, state->recipient,
++                                           SMTPD_NAME_RECIPIENT, def_acl);
++              forbid_whitelist(state, name, status, state->recipient);
++          }
+       } else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) {
+           if (cpp[1] == 0)
+               msg_warn("restriction %s requires domain name argument", name);
This page took 0.139063 seconds and 4 git commands to generate.