]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2-20041019
authorWietse Venema <wietse@porcupine.org>
Tue, 19 Oct 2004 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:30:01 +0000 (06:30 +0000)
84 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/BASIC_CONFIGURATION_README
postfix/README_FILES/DATABASE_README
postfix/RELEASE_NOTES
postfix/conf/postfix-files
postfix/html/BASIC_CONFIGURATION_README.html
postfix/html/DATABASE_README.html
postfix/html/Makefile.in
postfix/html/cidr_table.5.html
postfix/html/cleanup.8.html
postfix/html/nisplus_table.5.html [new file with mode: 0644]
postfix/html/postconf.5.html
postfix/html/postfix-manuals.html
postfix/html/postfix.1.html
postfix/html/smtpd.8.html
postfix/html/trivial-rewrite.8.html
postfix/man/Makefile.in
postfix/man/man1/postfix.1
postfix/man/man5/cidr_table.5
postfix/man/man5/nisplus_table.5 [new file with mode: 0644]
postfix/man/man5/postconf.5
postfix/man/man8/cleanup.8
postfix/man/man8/smtpd.8
postfix/man/man8/trivial-rewrite.8
postfix/mantools/makemanidx
postfix/mantools/postlink
postfix/proto/BASIC_CONFIGURATION_README.html
postfix/proto/DATABASE_README.html
postfix/proto/Makefile.in
postfix/proto/cidr_table
postfix/proto/nisplus_table [new file with mode: 0644]
postfix/proto/postconf.proto
postfix/src/cleanup/Makefile.in
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup.h
postfix/src/cleanup/cleanup_addr.c
postfix/src/cleanup/cleanup_envelope.c
postfix/src/cleanup/cleanup_init.c
postfix/src/cleanup/cleanup_message.c
postfix/src/cleanup/cleanup_rewrite.c
postfix/src/cleanup/cleanup_state.c
postfix/src/global/Makefile.in
postfix/src/global/deliver_pass.c
postfix/src/global/deliver_request.c
postfix/src/global/deliver_request.h
postfix/src/global/mail_params.h
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/global/match_parent_style.c
postfix/src/global/rewrite_clnt.c
postfix/src/global/rewrite_clnt.h
postfix/src/global/rewrite_clnt.in
postfix/src/global/rewrite_clnt.ref
postfix/src/lmtp/lmtp.h
postfix/src/lmtp/lmtp_proto.c
postfix/src/local/Makefile.in
postfix/src/oqmgr/Makefile.in
postfix/src/oqmgr/qmgr.h
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/oqmgr/qmgr_message.c
postfix/src/postfix/postfix.c
postfix/src/qmgr/Makefile.in
postfix/src/qmgr/qmgr.h
postfix/src/qmgr/qmgr_deliver.c
postfix/src/qmgr/qmgr_message.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_proto.c
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_check.h
postfix/src/smtpd/smtpd_proxy.c
postfix/src/smtpd/smtpd_state.c
postfix/src/trivial-rewrite/Makefile.in
postfix/src/trivial-rewrite/resolve.c
postfix/src/trivial-rewrite/rewrite.c
postfix/src/trivial-rewrite/trivial-rewrite.c
postfix/src/trivial-rewrite/trivial-rewrite.h
postfix/src/util/Makefile.in
postfix/src/util/attr_clnt.c
postfix/src/util/dict_nisplus.c
postfix/src/util/name_mask.c

index d58f4db3fffcdabd15021107f2642b15e21ad48f..42fe93c4d752aa0b5b219d809ce440a5da835882 100644 (file)
 -TRESPONSE
 -TREST_TABLE
 -TRES_CONTEXT
+-TRWR_CONTEXT
 -TSCACHE
 -TSCACHE_CLNT
 -TSCACHE_MULTI
index de4fe1935ab4867b7b20460e11b97da23fb6e081..640ded7133c7fcfdf28d83a1fa4815cc75f910ed 100644 (file)
@@ -9774,6 +9774,45 @@ Apologies for any names omitted.
 
        Portability: AIX 5.1/GCC.
 
+20041014-19
+
+       Message header address rewriting contexts, so that spam
+       from badly written software won't look like it came from
+       a local user.
+
+       The default "local" rewriting context appends "@$myorigin"
+       or ".$mydomain" to incomplete message header addresses,
+       just like Postfix has always done.
+
+       The new "invalid" address context appends "domain.invalid"
+       instead (or whatever domain name is specified with the
+       invalid_rewrite_context_domain parameter).
+
+       The new "none" address rewriting context does not modify
+       message header addresses at all.
+
+       Postfix uses the "local" rewriting context for mail from
+       the machine itself, from clients listed with the
+       local_rewrite_context_clients parameter (default:
+       $inet_interfaces $mynetworks) and from SASL authenticated
+       clients.
+
+       The context specified with remote_rewrite_context_name is
+       used for all other clients. The default setting is backwards
+       compatible to avoid surprises.
+
+       Postfix always uses the "local" rewriting context to update
+       incomplete envelope addresses.
+
+20041018
+
+       The NIS+ module by Geoff Gibbs is now part of Postfix.
+       Files: util/dict_nisplus.c, proto/nisplus_table.
+
+20041019
+
+       Support for Errors-To: is permanently removed.
+
 Open problems:
 
        Low: should the Delivered-To: test in local(8) be configurable?
index 9883e6567163a687532bce81c5e8f5724fcb8efc..d56b703d194dbc337365f8d7eed71dcbc4f02295 100644 (file)
@@ -210,10 +210,10 @@ the patterns in the main.cf file.
 W\bWh\bha\bat\bt d\bde\bes\bst\bti\bin\bna\bat\bti\bio\bon\bns\bs t\bto\bo r\bre\bel\bla\bay\by m\bma\bai\bil\bl t\bto\bo
 
 By default, Postfix will forward mail from strangers (clients outside
-authorized networks) to authorized destinations only. Authorized destinations
-are defined with the relay_domains configuration parameter. The default is to
-authorize all domains (and subdomains) of the domains listed with the
-mydestination parameter.
+authorized networks) to authorized remote destinations only. Authorized remote
+destinations are defined with the relay_domains configuration parameter. The
+default is to authorize all domains (and subdomains) of the domains listed with
+the mydestination parameter.
 
 Examples (specify only one of the following):
 
@@ -240,7 +240,8 @@ Examples (specify only one of the following):
         relayhost = [mail.isp.tld]    (deliver via provider mailhub)
 
 The form enclosed with [] eliminates DNS MX lookups. Don't worry if you don't
-know what that means.
+know what that means. Just be sure to specify the [] around the mailhub
+hostname that your ISP gave to you, otherwise mail may be mis-delivered.
 
 The STANDARD_CONFIGURATION_README file has more hints and tips for firewalled
 and/or dial-up networks.
index 3c080e5d3455330a2db9bcad4e968fed3047b5d3..5d1fb8b9c80fc1194d3be455be83935cc3e4c144 100644 (file)
@@ -201,6 +201,13 @@ To find out what database types your Postfix system supports, use the "postconf
     m\bmy\bys\bsq\bql\bl (read-only)
         Perform MySQL database lookups. Configuration details are given in
         mysql_table(5).
+    n\bne\bet\bti\bin\bnf\bfo\bo (read-only)
+        Perform Netinfo database lookups.
+    n\bni\bis\bs (read-only)
+        Perform NIS database lookups.
+    n\bni\bis\bsp\bpl\blu\bus\bs (read-only)
+        Perform NIS+ database lookups. Configuration details are given in
+        nisplus_table(5).
     p\bpc\bcr\bre\be (read-only)
         A lookup table based on Perl Compatible Regular Expressions. The file
         format is described in pcre_table(5). The lookup table name as used in
index 9b3e75a7e89dfe5e4ce90c5d14469c885ea68ede..86a10ec85e87e19a98bff04e8b8fc10d3519b77a 100644 (file)
@@ -7,6 +7,52 @@ snapshot release).  Patches are issued for the official release
 and change the patchlevel and the release date. Patches are never
 issued for snapshot releases.
 
+Incompatible changes with snapshot Postfix-2.2-20041019
+=======================================================
+
+Support for return addresses in the non-standard Errors-To: message
+headers is removed. It was already disabled by default with Postfix
+version 2.1.
+
+Major changes with snapshot Postfix-2.2-20041019
+================================================
+
+The NIS+ client by Geoff Gibbs is now part of the Postfix source
+tree. Details are given in the nisplus_table(5) manual page.
+
+Message header address rewriting contexts. These control what
+domains are appended to incomplete addresses in message headers,
+and whether headers are rewritten at all.
+
+- "local": Append the domain names in myorigin or mydomain to
+  incomplete addresses in message headers.
+
+- "invalid": append "domain.invalid" (or whatever is specified
+  with the invalid_header_rewrite_context_domain parameter) to
+  incomplete addresses in message headers,
+
+- "none": disable header address rewriting (don't even do canonical
+  mapping or address masquerading).
+
+The "local" address rewriting context is used for mail submitted
+with the Postfix sendmail command, for mail from clients that match
+$local_header_rewrite_context_clients (default: $inet_interfaces
+$mynetworks), and for mail from SASL authenticated clients.  It is
+not automatically used for pop-before-smtp clients; you'll have to
+specify their lookup table via the local_header_rewrite_context_clients
+parameter.
+
+The smtpd_remote_header_rewrite_context parameter specifies the
+address
+rewriting context for remote mail. The backwards compatible default
+is "local".  Purists will specify "none", so that Postfix does not
+modify headers (not even with canonical mappings or address
+masquerading).
+
+Postix always uses the "local" context for envelope addresses,
+because an unqualified address is effectively local when someone
+attempts to reply to it.
+
 Incompatible changes with snapshot Postfix-2.2-20041009
 =======================================================
 
index b125f4d8dbdc104295ad0e7fd72e44c910efc0b1..d477ba4743f8a2d3dceb7f2599b03b3e283aecbb 100644 (file)
@@ -144,6 +144,7 @@ $manpage_directory/man5/header_checks.5:f:root:-:644
 $manpage_directory/man5/ldap_table.5:f:root:-:644
 $manpage_directory/man5/master.5:f:root:-:644
 $manpage_directory/man5/mysql_table.5:f:root:-:644
+$manpage_directory/man5/nisplus_table.5:f:root:-:644
 $manpage_directory/man5/pcre_table.5:f:root:-:644
 $manpage_directory/man5/pgsql_table.5:f:root:-:644
 $manpage_directory/man5/postconf.5:f:root:-:644
@@ -313,6 +314,7 @@ $html_directory/mailq.1.html:f:root:-:644
 $html_directory/master.5.html:f:root:-:644
 $html_directory/master.8.html:f:root:-:644
 $html_directory/mysql_table.5.html:f:root:-:644
+$html_directory/nisplus_table.5.html:f:root:-:644
 $html_directory/newaliases.1.html:f:root:-:644
 $html_directory/oqmgr.8.html:f:root:-:644
 $html_directory/pcre_table.5.html:f:root:-:644
index cee19766287133b98074961be81699d78d58564d..c204ba66d68d7c5e245a512bc7abe14ac7e3d7a8 100644 (file)
@@ -315,7 +315,8 @@ of listing the patterns in the main.cf file. </p>
 <h2> <a name="relay_to"> What destinations to relay mail to </a> </h2>
 
 <p> By default, Postfix will forward mail from strangers (clients outside
-authorized networks) to authorized destinations only.  Authorized
+authorized networks) to authorized remote destinations only.
+Authorized remote
 destinations are defined with the <a href="postconf.5.html#relay_domains">relay_domains</a> configuration
 parameter.  The default is to authorize all domains (and subdomains)
 of the domains listed with the <a href="postconf.5.html#mydestination">mydestination</a> parameter.  </p>
@@ -355,7 +356,9 @@ via a relay host. </p>
 </blockquote>
 
 <p> The form enclosed with <tt>[]</tt> eliminates DNS MX lookups.
-Don't worry if you don't know what that means. </p>
+Don't worry if you don't know what that means. Just be sure to
+specify the <tt>[]</tt> around the mailhub hostname that your ISP
+gave to you, otherwise mail may be mis-delivered. </p>
 
 <p> The <a href="STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README</a> file has more hints and tips
 for firewalled and/or dial-up networks. </p>
index e879a983caa29bd2d4a61594e151006ccbf9bc8d..09f93d7e7d3246e484c394460a79d441f44cc7b6 100644 (file)
@@ -297,6 +297,19 @@ are given in the <a href="ldap_table.5.html">ldap_table(5)</a>. </dd>
 <dd> Perform MySQL database lookups. Configuration details are given
 in <a href="mysql_table.5.html">mysql_table(5)</a>. </dd>
 
+<dt> <b>netinfo</b> (read-only) </dt>
+
+<dd> Perform Netinfo database lookups. </dd>
+
+<dt> <b>nis</b> (read-only) </dt>
+
+<dd> Perform NIS database lookups. </dd>
+
+<dt> <b>nisplus</b> (read-only) </dt>
+
+<dd> Perform NIS+ database lookups. Configuration details are given
+in <a href="nisplus_table.5.html">nisplus_table(5)</a>. </dd>
+
 <dt> <b>pcre</b> (read-only) </dt>
 
 <dd> A lookup table based on Perl Compatible Regular Expressions.
index 1b44044bc3665d97e2fd199ca144fc122cfecebd..514370806cfda16a9b0b65947f56924ad5062f69 100644 (file)
@@ -18,7 +18,7 @@ CONFIG        = access.5.html aliases.5.html canonical.5.html relocated.5.html \
        transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html \
        cidr_table.5.html tcp_table.5.html header_checks.5.html \
        ldap_table.5.html mysql_table.5.html pgsql_table.5.html \
-       master.5.html
+       master.5.html nisplus_table.5.html
 OTHER  = postfix-manuals.html
 AWK    = awk '{ print; if (NR == 2) print ".pl 9999\n.ll 65" }'
 MAN2HTML = man2html -t "Postfix manual - `IFS=.; set \`echo $@\`; echo \"$$1($$2)\"`"
@@ -249,6 +249,10 @@ mysql_table.5.html: ../proto/mysql_table
        PATH=../mantools:$$PATH; \
        srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
 
+nisplus_table.5.html: ../proto/nisplus_table
+       PATH=../mantools:$$PATH; \
+       srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
+
 pcre_table.5.html: ../proto/pcre_table
        PATH=../mantools:$$PATH; \
        srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
index b766b892eeb28a76bec688268c0c9b7de0eb7e3c..96f701bbc31d7f1b58df7fb6d83793b5776c4a14 100644 (file)
@@ -15,10 +15,10 @@ CIDR_TABLE(5)                                       CIDR_TABLE(5)
        <b>postmap -q - <a href="cidr_table.5.html">cidr</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>
 
 <b>DESCRIPTION</b>
-       The  Postfix  mail  system  uses  optional  access control
-       tables.  These tables are usually in  <b>dbm</b>  or  <b>db</b>  format.
-       Alternatively,  access  control tables can be specified in
-       CIDR (Classless Inter-Domain Routing) form.
+       The  Postfix  mail  system  uses  optional  lookup tables.
+       These tables are usually in <b>dbm</b> or  <b>db</b>  format.   Alterna-
+       tively,  lookup tables can be specified in CIDR (Classless
+       Inter-Domain Routing) form.
 
        To find out what types of lookup tables your Postfix  sys-
        tem supports use the <b>postconf -m</b> command.
index 235967ba406593330c50f3706ba4805296480869..f45cc39ffab7bedc3296834f03ff97a8624af90f 100644 (file)
@@ -84,11 +84,6 @@ CLEANUP(8)                                             CLEANUP(8)
 
        Available in Postfix version 2.1 and later:
 
-       <b>enable_errors_to (no)</b>
-              Report mail delivery errors to the  address  speci-
-              fied   with  the  non-standard  Errors-To:  message
-              header, instead of the envelope sender address.
-
 <b>BUILT-IN CONTENT FILTERING CONTROLS</b>
        Postfix built-in content filtering  is  meant  to  stop  a
        flood  of  worms  or  viruses. It is not a general content
diff --git a/postfix/html/nisplus_table.5.html b/postfix/html/nisplus_table.5.html
new file mode 100644 (file)
index 0000000..e258e4f
--- /dev/null
@@ -0,0 +1,88 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title> Postfix manual - nisplus_table(5) </title>
+</head> <body> <pre>
+NISPLUS_TABLE(5)                                 NISPLUS_TABLE(5)
+
+<b>NAME</b>
+       nisplus_table - Postfix NIS+ client
+
+<b>SYNOPSIS</b>
+       <b>postmap -q "</b><i>string</i><b>" "<a href="nisplus_table.5.html">nisplus</a>:[</b><i>name</i><b>=%s];</b><i>name.name.</i><b>"</b>
+
+       <b>postmap -q - "<a href="nisplus_table.5.html">nisplus</a>:[</b><i>name</i><b>=%s];</b><i>name.name.</i><b>"</b> &lt;<i>inputfile</i>
+
+<b>DESCRIPTION</b>
+       The  Postfix  mail  system  uses  optional  lookup tables.
+       These tables are usually in <b>dbm</b> or  <b>db</b>  format.   Alterna-
+       tively,  lookup tables can be specified as NIS+ databases.
+
+       To find out what types of lookup tables your Postfix  sys-
+       tem supports use the "<b>postconf -m</b>" command.
+
+       To  test  Postfix NIS+ lookup tables, use the <b>postmap</b> com-
+       mand as described in the SYNOPSIS above.
+
+<b>QUERY SYNTAX</b>
+       Most of the NIS+ query is specified via the NIS+ map name.
+       The  general  format of a Postfix NIS+ map name is as fol-
+       lows:
+
+           <b><a href="nisplus_table.5.html">nisplus</a>:[</b><i>name</i><b>=%s];</b><i>name.name.name</i><b>.:</b><i>column</i>
+
+       Postfix NIS+ map names differ from what one normally would
+       use with commands such as <b>niscat</b>:
+
+       <b>o</b>      With  each NIS+ table lookup, "<b>%s</b>" is replaced by a
+              version of the lookup string.  There  can  be  only
+              one "<b>%s</b>" instance in a Postfix NIS+ map name.
+
+       <b>o</b>      Postfix  NIS+  map  names  use  "<b>;</b>" instead of "<b>,</b>",
+              because the latter  character  is  special  in  the
+              Postfix main.cf file.  Postfix replaces "<b>;</b>" charac-
+              ters in the map name  by  "<b>,</b>"  before  making  NIS+
+              queries.
+
+       <b>o</b>      The ":<i>column</i>" part in the NIS+ map name is not part
+              of the actual NIS+ query. Instead, it specifies the
+              number of the table column that provides the lookup
+              result. When no ":<i>column</i>" is  specified  the  first
+              column (1) is used.
+
+<b>EXAMPLE</b>
+       A NIS+ aliases map might be queried as follows:
+
+           <a href="postconf.5.html#alias_maps">alias_maps</a> = dbm:/etc/mail/aliases,
+                 <a href="nisplus_table.5.html">nisplus</a>:[alias=%s];mail_aliases.org_dir.$<a href="postconf.5.html#mydomain">mydomain</a>.:1
+
+       This  queries the local aliases file before the NIS+ file.
+
+<b>SEE ALSO</b>
+       <a href="postmap.1.html">postmap(1)</a>, Postfix lookup table manager
+
+<b>README FILES</b>
+       <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
+
+<b>LICENSE</b>
+       The  Secure  Mailer  license must be distributed with this
+       software.
+
+<b>AUTHOR(S)</b>
+       Geoff Gibbs
+       UK-HGMP-RC
+       Hinxton
+       Cambridge
+       CB10 1SB, UK
+
+       Based on the NIS client code:
+
+       Adopted and adapted by:
+       Wietse Venema
+       IBM T.J. Watson Research
+       P.O. Box 704
+       Yorktown Heights, NY 10598, USA
+
+                                                 NISPLUS_TABLE(5)
+</pre> </body> </html>
index 9884581f80ac7ffb36209ddf99a28d8d77606b9c..91dc67b4d3c9a6aa38b5da4b2e81245d6b04a25a 100644 (file)
@@ -670,8 +670,9 @@ The default time unit is s (seconds).
 (default: yes)</b></DT><DD>
 
 <p>
-Append the string "@$<a href="postconf.5.html#myorigin">myorigin</a>" to mail addresses without domain
-information.
+With locally submitted mail, append the string "@$<a href="postconf.5.html#myorigin">myorigin</a>" to mail
+addresses without domain information. With remotely submitted mail,
+append the string "@$invalid_domain" instead.
 </p>
 
 <p>
@@ -686,8 +687,9 @@ Postfix does not support domain-less addresses.
 (default: yes)</b></DT><DD>
 
 <p>
-Append the string ".$<a href="postconf.5.html#mydomain">mydomain</a>" to addresses that have no ".domain"
-information.
+With locally submitted mail, append the string ".$<a href="postconf.5.html#mydomain">mydomain</a>" to
+addresses that have no ".domain" information. With remotely submitted
+mail, append the string ".$invalid_domain" instead.
 </p>
 
 <p>
@@ -2569,6 +2571,17 @@ block all mail to a site.
 </p>
 
 
+</DD>
+
+<DT><b><a name="invalid_header_rewrite_context_domain">invalid_header_rewrite_context_domain</a>
+(default: domain.invalid)</b></DT><DD>
+
+<p> Append this domain to incomplete message header addresses from
+remote clients, when $<a href="postconf.5.html#remote_header_rewrite_context_name">remote_header_rewrite_context_name</a> is set to
+"invalid".  This is one way to avoid appending your own domain to
+addresses in spam from poorly written software. </p>
+
+
 </DD>
 
 <DT><b><a name="invalid_hostname_reject_code">invalid_hostname_reject_code</a>
@@ -3067,6 +3080,29 @@ the entry in the master.cf file. </p>
 into concurrency per domain.  </p>
 
 
+</DD>
+
+<DT><b><a name="local_header_rewrite_context_clients">local_header_rewrite_context_clients</a>
+(default: $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
+$<a href="postconf.5.html#mynetworks">mynetworks</a>)</b></DT><DD>
+
+<p> Append the domain names in $<a href="postconf.5.html#myorigin">myorigin</a> and $<a href="postconf.5.html#mydomain">mydomain</a> to incomplete
+message header addresses from these clients.  </p>
+
+<p> Specify a list of network addresses or network/netmask patterns,
+separated by comma or whitespace. The list is matched left to right,
+and the search stops on the first match.  Specify !address or
+!network/netmask to exclude an address or network block from the
+list.  A network mask specifies the number of bits in the network
+part of a host address. Continue long lines by starting the next
+line with whitespace. </p>
+
+<p> You can also specify "/file/name" or "<a href="DATABASE_README.html">type:table</a>" patterns.
+A "/file/name" pattern is replaced by its contents; a "<a href="DATABASE_README.html">type:table</a>"
+lookup table is matched when a client name or address matches a
+lookup key (the lookup result is ignored). </p>
+
+
 </DD>
 
 <DT><b><a name="local_recipient_maps">local_recipient_maps</a>
@@ -4579,7 +4615,7 @@ configure or operate a specific Postfix subsystem or feature.
 (default: empty)</b></DT><DD>
 
 <p> Enable or disable recipient validation, built-in content
-filtering, or address rewriting. Typically, these are specified in
+filtering, or address mapping. Typically, these are specified in
 master.cf as command-line arguments for the <a href="smtpd.8.html">smtpd(8)</a>, <a href="qmqpd.8.html">qmqpd(8)</a> or
 <a href="pickup.8.html">pickup(8)</a> daemons. </p>
 
@@ -4977,6 +5013,40 @@ Examples:
 </pre>
 
 
+</DD>
+
+<DT><b><a name="remote_header_rewrite_context_name">remote_header_rewrite_context_name</a>
+(default: local)</b></DT><DD>
+
+<p> The address rewriting context that should be used for incomplete
+mail header addresses from remote clients. </p>
+
+<ul>
+
+<li> <p> <b>local</b> Append the domains specified with $<a href="postconf.5.html#myorigin">myorigin</a>
+or $<a href="postconf.5.html#mydomain">mydomain</a> to incomplete message header addresses from remote
+clients.  </p>
+
+<li> <p> <b>invalid</b> Append the domain specified with
+$<a href="postconf.5.html#invalid_header_rewrite_context_domain">invalid_header_rewrite_context_domain</a> to incomplete message header
+addresses from remote clients. This is one way to avoid appending
+your own domain to addresses in spam from poorly written software.
+This is a safe choice for gateways that have no control over
+address rewriting by down-stream systems.
+</p>
+
+<li> <p> <b>none</b> Don't modify message headers from remote
+clients at all. This is another way to avoid appending your own
+domain to addresses in spam from poorly written software. This
+is the preferred choice for purists. </p>
+
+</ul>
+
+<p> Note: Postfix always appends the domains specified with $<a href="postconf.5.html#myorigin">myorigin</a>
+or $<a href="postconf.5.html#mydomain">mydomain</a> to incomplete envelope addresses, because those
+addresses are effectively equivalent to local addresses. </p>
+
+
 </DD>
 
 <DT><b><a name="require_home_directory">require_home_directory</a>
index e286b3f186642d7ccaab1d3743b6efe925733a18..6956125a557cba0b9c288fc1dca23da7c1252dcc 100644 (file)
@@ -49,9 +49,9 @@ overview</a>
 
 <p> Each Postfix manual page is numbered after a section of the
 UNIX manual: examples are <a href="mailq.1.html">mailq(1)</a> or <a href="access.5.html">access(5)</a>. Unfortunately,
-the organization of manual pages depends on the UNIX version being
-used.  Postfix documentation assumes the following convention:
-</p>
+there is no single universal method to organize manual pages; each
+UNIX flavor appears to be different. Postfix documentation assumes
+the following convention:  </p>
 
 <blockquote>
 
@@ -141,6 +141,8 @@ used.  Postfix documentation assumes the following convention:
 
 <li> <a href="mysql_table.5.html">mysql_table(5)</a>, Postfix MYSQL client 
 
+<li> <a href="nisplus_table.5.html">nisplus_table(5)</a>, Postfix NIS+ client 
+
 <li> <a href="pcre_table.5.html">pcre_table(5)</a>, Associate PCRE pattern with value 
 
 <li> <a href="pgsql_table.5.html">pgsql_table(5)</a>, Postfix PostgreSQL client 
index 255a872b4c47a037e96a1c5d711630c817008f08..c71d72f8a0730b5a5e0e5e017ddd8ad5d5f919bd 100644 (file)
@@ -222,6 +222,7 @@ POSTFIX(1)                                             POSTFIX(1)
        <a href="cidr_table.5.html">cidr_table(5)</a>, Associate CIDR pattern with value
        <a href="ldap_table.5.html">ldap_table(5)</a>, Postfix LDAP client
        <a href="mysql_table.5.html">mysql_table(5)</a>, Postfix MYSQL client
+       <a href="nisplus_table.5.html">nisplus_table(5)</a>, Postfix NIS+ client
        <a href="pcre_table.5.html">pcre_table(5)</a>, Associate PCRE pattern with value
        <a href="pgsql_table.5.html">pgsql_table(5)</a>, Postfix PostgreSQL client
        <a href="regexp_table.5.html">regexp_table(5)</a>, Associate POSIX regexp pattern with value
index 98026c336fec283bb69ce394a6df42389025c980..ebb5c37b4eecd10fed81b89c99ef94d666db88d1 100644 (file)
@@ -103,6 +103,32 @@ SMTPD(8)                                                 SMTPD(8)
               What SMTP clients Postfix will not offer AUTH  sup-
               port to.
 
+<b>ADDRESS REWRITING CONTROLS</b>
+       <b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
+              Enable  or  disable  recipient validation, built-in
+              content filtering, or address mapping.
+
+       Available in Postfix version 2.2 and later:
+
+       <b><a href="postconf.5.html#local_header_rewrite_context_clients">local_header_rewrite_context_clients</a>     ($<a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b>
+       <b>$<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
+              Append the domain names in $<a href="postconf.5.html#myorigin">myorigin</a> and  $<a href="postconf.5.html#mydomain">mydomain</a>
+              to  incomplete  message header addresses from these
+              clients.
+
+       <b><a href="postconf.5.html#remote_header_rewrite_context_name">remote_header_rewrite_context_name</a> (local)</b>
+              The address rewriting context that should  be  used
+              for  incomplete  mail  header addresses from remote
+              clients.
+
+       Implemented by the <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> server:
+
+       <b><a href="postconf.5.html#invalid_header_rewrite_context_domain">invalid_header_rewrite_context_domain</a> (domain.invalid)</b>
+              Append this domain  to  incomplete  message  header
+              addresses     from     remote     clients,     when
+              $<a href="postconf.5.html#remote_header_rewrite_context_name">remote_header_rewrite_context_name</a>   is   set   to
+              "invalid".
+
 <b>AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS</b>
        As  of  version 1.0, Postfix can be configured to send new
        mail to an external  content  filter  AFTER  the  mail  is
@@ -142,7 +168,7 @@ SMTPD(8)                                                 SMTPD(8)
 
        <b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
               Enable  or  disable  recipient validation, built-in
-              content filtering, or address rewriting.
+              content filtering, or address mapping.
 
 <b>EXTERNAL CONTENT INSPECTION CONTROLS</b>
        The following parameters are applicable for  both  before-
index 8b24af669758feafdce823bb78d574e61b4340f8..36022a14a5f99302c7e91122591937231dbfc204 100644 (file)
@@ -17,52 +17,71 @@ TRIVIAL-REWRITE(8)                             TRIVIAL-REWRITE(8)
        The <b>trivial-rewrite</b> daemon processes three types of client
        service requests:
 
-       <b>rewrite</b>
-              Rewrite  an  address to standard form. The <b>trivial-</b>
-              <b>rewrite</b> daemon  by  default  appends  local  domain
-              information  to  unqualified  addresses, swaps bang
-              paths to domain form,  and  strips  source  routing
-              information.  This process is under control of sev-
-              eral configuration parameters (see below).
-
-       <b>resolve</b>
+       <b>rewrite</b> <i>context address</i>
+              Rewrite  an  address to standard form, according to
+              the address rewriting context:
+
+              <b>local</b>
+
+              <b>none</b>   Append the domain names specified with <b>$<a href="postconf.5.html#myorigin">myo</a>-</b>
+                     <b><a href="postconf.5.html#myorigin">rigin</a></b>  or <b>$<a href="postconf.5.html#mydomain">mydomain</a></b> to incomplete addresses;
+                     do <b><a href="postconf.5.html#swap_bangpath">swap_bangpath</a></b> and <b><a href="postconf.5.html#allow_percent_hack">allow_percent_hack</a></b> pro-
+                     cessing as described below, and strip source
+                     routed  addresses  (<i>@site,@site:user@domain</i>)
+                     to <i>user@domain</i> form.
+
+              <b>invalid</b>
+                     Append   the   domain  name  specified  with
+                     <b>$<a href="postconf.5.html#invalid_header_rewrite_context_domain">invalid_header_rewrite_context_domain</a></b>    to
+                     incomplete  addresses.  Otherwise the result
+                     is identical to that of  the  <b>local</b>  address
+                     rewriting  context.  This  prevents  Postfix
+                     from appending the <a href="ADDRESS_CLASS_README.html#local_domain_class">local domain</a> to spam from
+                     poorly written remote clients.
+
+       <b>resolve</b> <i>address</i>
               Resolve an address to a (<i>transport</i>, <i>nexthop</i>, <i>recip-</i>
-              <i>ient</i>) triple. The meaning of the results is as fol-
-              lows:
+              <i>ient</i>, <i>flags</i>) quadruple. The meaning of the  results
+              is as follows:
 
               <i>transport</i>
                      The delivery agent to use. This is the first
                      field of an entry in the <b>master.cf</b> file.
 
               <i>nexthop</i>
-                     The  host  to  send to and optional delivery
+                     The host to send to  and  optional  delivery
                      method information.
 
               <i>recipient</i>
-                     The  envelope  recipient  address  that   is
+                     The   envelope  recipient  address  that  is
                      passed on to <i>nexthop</i>.
 
-       <b>verify</b> Resolve  an  address  for address verification pur-
+              <i>flags</i>  The  address  class,  whether  the   address
+                     requires  relaying,  whether the address has
+                     problems, and whether the request failed.
+
+       <b>verify</b> <i>address</i>
+              Resolve an address for  address  verification  pur-
               poses.
 
 <b>SERVER PROCESS MANAGEMENT</b>
        The trivial-rewrite servers run under control by the Post-
        fix master server.  Each server can handle multiple simul-
-       taneous connections.  When all servers are  busy  while  a
-       client  connects, the master creates a new server process,
-       provided that the trivial-rewrite server process limit  is
+       taneous  connections.   When  all servers are busy while a
+       client connects, the master creates a new server  process,
+       provided  that the trivial-rewrite server process limit is
        not  exceeded.   Each  trivial-rewrite  server  terminates
        after serving at least <b>$<a href="postconf.5.html#max_use">max_use</a></b> clients of after <b>$<a href="postconf.5.html#max_idle">max_idle</a></b>
        seconds of idle time.
 
 <b>STANDARDS</b>
-       None.  The  command  does  not  interact  with the outside
+       None. The command  does  not  interact  with  the  outside
        world.
 
 <b>SECURITY</b>
-       The <b>trivial-rewrite</b> daemon is not security sensitive.   By
-       default,  this  daemon  does  not  talk to remote or local
-       users.  It can run at a fixed low privilege in a  chrooted
+       The  <b>trivial-rewrite</b> daemon is not security sensitive.  By
+       default, this daemon does not  talk  to  remote  or  local
+       users.   It can run at a fixed low privilege in a chrooted
        environment.
 
 <b>DIAGNOSTICS</b>
@@ -70,15 +89,15 @@ TRIVIAL-REWRITE(8)                             TRIVIAL-REWRITE(8)
 
 <b>CONFIGURATION PARAMETERS</b>
        On busy mail systems a long time may pass before a <b>main.cf</b>
-       change affecting trivial_rewrite(8) is picked up. Use  the
+       change  affecting trivial_rewrite(8) is picked up. Use the
        command "<b>postfix reload</b>" to speed up a change.
 
-       The  text  below  provides  only  a parameter summary. See
+       The text below provides  only  a  parameter  summary.  See
        <a href="postconf.5.html">postconf(5)</a> for more details including examples.
 
 <b>COMPATIBILITY CONTROLS</b>
        <b><a href="postconf.5.html#resolve_dequoted_address">resolve_dequoted_address</a> (yes)</b>
-              Resolve a recipient address safely instead of  cor-
+              Resolve  a recipient address safely instead of cor-
               rectly, by looking inside quotes.
 
        <b><a href="postconf.5.html#resolve_null_domain">resolve_null_domain</a> (no)</b>
@@ -89,29 +108,46 @@ TRIVIAL-REWRITE(8)                             TRIVIAL-REWRITE(8)
 <b>ADDRESS REWRITING CONTROLS</b>
        <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The domain name that locally-posted mail appears to
-              come from, and that locally posted mail  is  deliv-
+              come  from,  and that locally posted mail is deliv-
               ered to.
 
        <b><a href="postconf.5.html#allow_percent_hack">allow_percent_hack</a> (yes)</b>
-              Enable  the  rewriting of the form "user%domain" to
+              Enable the rewriting of the form  "user%domain"  to
               "user@domain".
 
        <b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a> (yes)</b>
-              Append the string "@$<a href="postconf.5.html#myorigin">myorigin</a>"  to  mail  addresses
-              without domain information.
+              With  locally  submitted  mail,  append  the string
+              "@$<a href="postconf.5.html#myorigin">myorigin</a>"  to  mail  addresses  without   domain
+              information.
 
        <b><a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a> (yes)</b>
-              Append  the  string  ".$<a href="postconf.5.html#mydomain">mydomain</a>" to addresses that
-              have no ".domain" information.
+              With  locally  submitted  mail,  append  the string
+              ".$<a href="postconf.5.html#mydomain">mydomain</a>" to addresses that  have  no  ".domain"
+              information.
 
        <b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
               The separator between user names and address exten-
               sions (user+foo).
 
        <b><a href="postconf.5.html#swap_bangpath">swap_bangpath</a> (yes)</b>
-              Enable    the   rewriting   of   "site!user"   into
+              Enable   the   rewriting   of   "site!user"    into
               "user@site".
 
+       Available in Postfix 2.2 and later:
+
+       <b><a href="postconf.5.html#invalid_header_rewrite_context_domain">invalid_header_rewrite_context_domain</a> (domain.invalid)</b>
+              Append  this  domain  to  incomplete message header
+              addresses     from     remote     clients,     when
+              $<a href="postconf.5.html#remote_header_rewrite_context_name">remote_header_rewrite_context_name</a>   is   set   to
+              "invalid".
+
+       Implemented by the <a href="smtpd.8.html">smtpd(8)</a> server:
+
+       <b><a href="postconf.5.html#remote_header_rewrite_context_name">remote_header_rewrite_context_name</a> (local)</b>
+              The address rewriting context that should  be  used
+              for  incomplete  mail  header addresses from remote
+              clients.
+
 <b>ROUTING CONTROLS</b>
        The following is applicable to  Postfix  version  2.0  and
        later.   Earlier  versions  do  not have support for: <a href="postconf.5.html#virtual_transport">vir</a>-
index 64e9989715b2f086acfcb4186bdd5d594551506b..703e3db7de12930560f0ad62ebc71a0a88a32765 100644 (file)
@@ -16,7 +16,7 @@ CONFIG        = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
        man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \
        man5/cidr_table.5 man5/tcp_table.5 man5/header_checks.5 \
        man5/body_checks.5 man5/ldap_table.5 man5/mysql_table.5 \
-       man5/pgsql_table.5 man5/master.5
+       man5/pgsql_table.5 man5/master.5 man5/nisplus_table.5
 TOOLS  = man1/smtp-sink.1 man1/smtp-source.1 man1/qmqp-sink.1 \
        man1/qmqp-source.1 man1/qshape.1
 
@@ -250,6 +250,9 @@ man5/master.5: ../proto/master
 man5/mysql_table.5: ../proto/mysql_table
        ../mantools/srctoman - $? >$@
 
+man5/nisplus_table.5: ../proto/nisplus_table
+       ../mantools/srctoman - $? >$@
+
 man5/pcre_table.5: ../proto/pcre_table
        ../mantools/srctoman - $? >$@
 
index c4802261b5e560d1a63fb50fad7c0ada9af56e6b..4fa90c5ad2afc11a21b1d74efcab54529483068b 100644 (file)
@@ -187,6 +187,7 @@ Table lookup mechanisms:
 cidr_table(5), Associate CIDR pattern with value
 ldap_table(5), Postfix LDAP client
 mysql_table(5), Postfix MYSQL client
+nisplus_table(5), Postfix NIS+ client
 pcre_table(5), Associate PCRE pattern with value
 pgsql_table(5), Postfix PostgreSQL client
 regexp_table(5), Associate POSIX regexp pattern with value
index e4e54beb167a9f63a7c53edda086df618e9ad650..ae6ef06cc2c1b31bd0b849a24c21b7820faacd67 100644 (file)
@@ -14,9 +14,9 @@ format of Postfix CIDR tables
 .SH DESCRIPTION
 .ad
 .fi
-The Postfix mail system uses optional access control tables.
+The Postfix mail system uses optional lookup tables.
 These tables are usually in \fBdbm\fR or \fBdb\fR format.
-Alternatively, access control tables can be specified in CIDR
+Alternatively, lookup tables can be specified in CIDR
 (Classless Inter-Domain Routing) form.
 
 To find out what types of lookup tables your Postfix system
diff --git a/postfix/man/man5/nisplus_table.5 b/postfix/man/man5/nisplus_table.5
new file mode 100644 (file)
index 0000000..963fc92
--- /dev/null
@@ -0,0 +1,102 @@
+.TH NISPLUS_TABLE 5 
+.ad
+.fi
+.SH NAME
+nisplus_table
+\-
+Postfix NIS+ client
+.SH "SYNOPSIS"
+.na
+.nf
+\fBpostmap -q "\fIstring\fB" "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR
+
+\fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR <\fIinputfile\fR
+.SH DESCRIPTION
+.ad
+.fi
+The Postfix mail system uses optional lookup tables.
+These tables are usually in \fBdbm\fR or \fBdb\fR format.
+Alternatively, lookup tables can be specified as NIS+
+databases.
+
+To find out what types of lookup tables your Postfix system
+supports use the "\fBpostconf -m\fR" command.
+
+To test Postfix NIS+ lookup tables, use the \fBpostmap\fR
+command as described in the SYNOPSIS above.
+.SH "QUERY SYNTAX"
+.na
+.nf
+.ad
+.fi
+Most of the NIS+ query is specified via the NIS+ map name. The
+general format of a Postfix NIS+ map name is as follows:
+
+.ti +4
+\fBnisplus:[\fIname\fB=%s];\fIname.name.name\fB.:\fIcolumn\fR
+
+Postfix NIS+ map names differ from what one normally
+would use with commands such as \fBniscat\fR:
+.IP \(bu
+With each NIS+ table lookup, "\fB%s\fR" is replaced by a
+version of the lookup string.  There can be only one
+"\fB%s\fR" instance in a Postfix NIS+ map name.
+.IP \(bu
+Postfix NIS+ map names use "\fB;\fR" instead of "\fB,\fR",
+because the latter character is special in the Postfix
+main.cf file.  Postfix replaces "\fB;\fR" characters in
+the map name by "\fB,\fR" before making NIS+ queries.
+.IP \(bu
+The ":\fIcolumn\fR" part in the NIS+ map name is not part
+of the actual NIS+ query. Instead, it specifies the number
+of the table column that provides the lookup result. When
+no ":\fIcolumn\fR" is specified the first column (1) is used.
+.SH "EXAMPLE"
+.na
+.nf
+A NIS+ aliases map might be queried as follows:
+
+.ti +4
+alias_maps = dbm:/etc/mail/aliases,
+.ti +2
+        nisplus:[alias=%s];mail_aliases.org_dir.$mydomain.:1
+.ad
+.fi
+
+This queries the local aliases file before the NIS+ file.
+.SH "SEE ALSO"
+.na
+.nf
+postmap(1), Postfix lookup table manager
+.SH "README FILES"
+.na
+.nf
+.ad
+.fi
+Use "\fBpostconf readme_directory\fR" or
+"\fBpostconf html_directory\fR" to locate this information.
+.na
+.nf
+DATABASE_README, Postfix lookup table overview
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH "AUTHOR(S)"
+.na
+.nf
+Geoff Gibbs
+UK-HGMP-RC
+Hinxton
+Cambridge
+CB10 1SB, UK
+
+Based on the NIS client code:
+
+Adopted and adapted by:
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
index e54d11306640677ee34f7698b76419d347b31f88..5537e4ad48096033dc447f15aad6972141e065ac 100644 (file)
@@ -358,14 +358,16 @@ part of the stable Postfix 2.1 release.
 Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
 The default time unit is s (seconds).
 .SH append_at_myorigin (default: yes)
-Append the string "@$myorigin" to mail addresses without domain
-information.
+With locally submitted mail, append the string "@$myorigin" to mail
+addresses without domain information. With remotely submitted mail,
+append the string "@$invalid_domain" instead.
 .PP
 This feature is enabled by default and must not be turned off.
 Postfix does not support domain-less addresses.
 .SH append_dot_mydomain (default: yes)
-Append the string ".$mydomain" to addresses that have no ".domain"
-information.
+With locally submitted mail, append the string ".$mydomain" to
+addresses that have no ".domain" information. With remotely submitted
+mail, append the string ".$invalid_domain" instead.
 .PP
 This feature is enabled by default. If disabled, users will not be
 able to send mail to "user@partialdomainname" but will have to
@@ -1306,6 +1308,11 @@ and via the pipe(8) and virtual(8) delivery agents.
 .PP
 Warning: with concurrency of 1, one bad message can be enough to
 block all mail to a site.
+.SH invalid_header_rewrite_context_domain (default: domain.invalid)
+Append this domain to incomplete message header addresses from
+remote clients, when $remote_header_rewrite_context_name is set to
+"invalid".  This is one way to avoid appending your own domain to
+addresses in spam from poorly written software.
 .SH invalid_hostname_reject_code (default: 501)
 The numerical Postfix SMTP server response code when the client
 HELO or EHLO command parameter is rejected by the reject_invalid_hostname
@@ -1557,6 +1564,25 @@ the entry in the master.cf file.
 Setting this parameter to a value > 1 changes the meaning of
 local_destination_concurrency_limit from concurrency per recipient
 into concurrency per domain.
+<DT>\fBlocal_header_rewrite_context_clients
+(default: $inet_interfaces
+$mynetworks)\fR</DT><DD>
+.PP
+Append the domain names in $myorigin and $mydomain to incomplete
+message header addresses from these clients.
+.PP
+Specify a list of network addresses or network/netmask patterns,
+separated by comma or whitespace. The list is matched left to right,
+and the search stops on the first match.  Specify !address or
+!network/netmask to exclude an address or network block from the
+list.  A network mask specifies the number of bits in the network
+part of a host address. Continue long lines by starting the next
+line with whitespace.
+.PP
+You can also specify "/file/name" or "type:table" patterns.
+A "/file/name" pattern is replaced by its contents; a "type:table"
+lookup table is matched when a client name or address matches a
+lookup key (the lookup result is ignored).
 .SH local_recipient_maps (default: proxy:unix:passwd.byname $alias_maps)
 Lookup tables with all names or addresses of local recipients:
 a recipient address is local when its domain matches $mydestination,
@@ -2361,7 +2387,7 @@ The location of Postfix README files that describe how to build,
 configure or operate a specific Postfix subsystem or feature.
 .SH receive_override_options (default: empty)
 Enable or disable recipient validation, built-in content
-filtering, or address rewriting. Typically, these are specified in
+filtering, or address mapping. Typically, these are specified in
 master.cf as command-line arguments for the smtpd(8), qmqpd(8) or
 pickup(8) daemons.
 .PP
@@ -2623,6 +2649,29 @@ relocated_maps = hash:/etc/postfix/relocated
 .fi
 .ad
 .ft R
+.SH remote_header_rewrite_context_name (default: local)
+The address rewriting context that should be used for incomplete
+mail header addresses from remote clients.
+.IP \(bu
+\fBlocal\fR Append the domains specified with $myorigin
+or $mydomain to incomplete message header addresses from remote
+clients.
+.IP \(bu
+\fBinvalid\fR Append the domain specified with
+$invalid_header_rewrite_context_domain to incomplete message header
+addresses from remote clients. This is one way to avoid appending
+your own domain to addresses in spam from poorly written software.
+This is a safe choice for gateways that have no control over
+address rewriting by down-stream systems.
+.IP \(bu
+\fBnone\fR Don't modify message headers from remote
+clients at all. This is another way to avoid appending your own
+domain to addresses in spam from poorly written software. This
+is the preferred choice for purists.
+.PP
+Note: Postfix always appends the domains specified with $myorigin
+or $mydomain to incomplete envelope addresses, because those
+addresses are effectively equivalent to local addresses.
 .SH require_home_directory (default: no)
 Whether or not a local(8) recipient's home directory must exist
 before mail delivery is attempted. By default this test is disabled.
index ba4ead2b2b1c7f4dfa912b372560a258387161f1..ef5690e7b2c2c4d3d2d655c69218e9e220fcecb6 100644 (file)
@@ -84,10 +84,6 @@ Message header that the Postfix cleanup(8) server inserts when a
 message contains no To: or Cc: message header.
 .PP
 Available in Postfix version 2.1 and later:
-.IP "\fBenable_errors_to (no)\fR"
-Report mail delivery errors to the address specified with the
-non-standard Errors-To: message header, instead of the envelope
-sender address.
 .SH "BUILT-IN CONTENT FILTERING CONTROLS"
 .na
 .nf
index b44297142bf5648e66a52b7d84401183ef243407..617c75dc3deb9eee2b1955b200228dfbe0e1f01d 100644 (file)
@@ -102,6 +102,28 @@ sender addresses, even when no explicit reject_unlisted_sender
 access restriction is specified.
 .IP "\fBsmtpd_sasl_exceptions_networks (empty)\fR"
 What SMTP clients Postfix will not offer AUTH support to.
+.SH "ADDRESS REWRITING CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBreceive_override_options (empty)\fR"
+Enable or disable recipient validation, built-in content
+filtering, or address mapping.
+.PP
+Available in Postfix version 2.2 and later:
+.IP "\fBlocal_header_rewrite_context_clients ($inet_interfaces $mynetworks)\fR"
+Append the domain names in $myorigin and $mydomain to incomplete
+message header addresses from these clients.
+.IP "\fBremote_header_rewrite_context_name (local)\fR"
+The address rewriting context that should be used for incomplete
+mail header addresses from remote clients.
+.PP
+Implemented by the trivial-rewrite(8) server:
+.IP "\fBinvalid_header_rewrite_context_domain (domain.invalid)\fR"
+Append this domain to incomplete message header addresses from
+remote clients, when $remote_header_rewrite_context_name is set to
+"invalid".
 .SH "AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS"
 .na
 .nf
@@ -142,7 +164,7 @@ and external content filters.
 Available in Postfix version 2.1 and later:
 .IP "\fBreceive_override_options (empty)\fR"
 Enable or disable recipient validation, built-in content
-filtering, or address rewriting.
+filtering, or address mapping.
 .SH "EXTERNAL CONTENT INSPECTION CONTROLS"
 .na
 .nf
index f433a48b1c58e3b85d2f49908b8f6cdc378bac77..b73109e5a55e5045a0d098bf27554fd4788cc98b 100644 (file)
@@ -14,15 +14,29 @@ Postfix address rewriting and resolving daemon
 .fi
 The \fBtrivial-rewrite\fR daemon processes three types of client
 service requests:
-.IP \fBrewrite\fR
-Rewrite an address to standard form. The \fBtrivial-rewrite\fR
-daemon by default appends local domain information to unqualified
-addresses, swaps bang paths to domain form, and strips source
-routing information. This process is under control of several
-configuration parameters (see below).
-.IP \fBresolve\fR
+.IP "\fBrewrite \fIcontext address\fR"
+Rewrite an address to standard form, according to the
+address rewriting context:
+.RS
+.IP \fBlocal\fR
+.IP \fBnone\fR
+Append the domain names specified with \fB$myorigin\fR or
+\fB$mydomain\fR to incomplete addresses; do \fBswap_bangpath\fR
+and \fBallow_percent_hack\fR processing as described below, and
+strip source routed addresses (\fI@site,@site:user@domain\fR)
+to \fIuser@domain\fR form.
+.IP \fBinvalid\fR
+Append the domain name specified with
+\fB$invalid_header_rewrite_context_domain\fR to incomplete
+addresses. Otherwise the result is identical to that of
+the \fBlocal\fR address rewriting context. This prevents
+Postfix from appending the local domain to spam from poorly
+written remote clients.
+.RE
+.IP "\fBresolve \fIaddress\fR"
 Resolve an address to a (\fItransport\fR, \fInexthop\fR,
-\fIrecipient\fR) triple. The meaning of the results is as follows:
+\fIrecipient\fR, \fIflags\fR) quadruple. The meaning of
+the results is as follows:
 .RS
 .IP \fItransport\fR
 The delivery agent to use. This is the first field of an entry
@@ -31,8 +45,11 @@ in the \fBmaster.cf\fR file.
 The host to send to and optional delivery method information.
 .IP \fIrecipient\fR
 The envelope recipient address that is passed on to \fInexthop\fR.
+.IP \fIflags\fR
+The address class, whether the address requires relaying,
+whether the address has problems, and whether the request failed.
 .RE
-.IP \fBverify\fR
+.IP "\fBverify \fIaddress\fR"
 Resolve an address for address verification purposes.
 .SH "SERVER PROCESS MANAGEMENT"
 .na
@@ -99,15 +116,26 @@ from, and that locally posted mail is delivered to.
 .IP "\fBallow_percent_hack (yes)\fR"
 Enable the rewriting of the form "user%domain" to "user@domain".
 .IP "\fBappend_at_myorigin (yes)\fR"
-Append the string "@$myorigin" to mail addresses without domain
-information.
+With locally submitted mail, append the string "@$myorigin" to mail
+addresses without domain information.
 .IP "\fBappend_dot_mydomain (yes)\fR"
-Append the string ".$mydomain" to addresses that have no ".domain"
-information.
+With locally submitted mail, append the string ".$mydomain" to
+addresses that have no ".domain" information.
 .IP "\fBrecipient_delimiter (empty)\fR"
 The separator between user names and address extensions (user+foo).
 .IP "\fBswap_bangpath (yes)\fR"
 Enable the rewriting of "site!user" into "user@site".
+.PP
+Available in Postfix 2.2 and later:
+.IP "\fBinvalid_header_rewrite_context_domain (domain.invalid)\fR"
+Append this domain to incomplete message header addresses from
+remote clients, when $remote_header_rewrite_context_name is set to
+"invalid".
+.PP
+Implemented by the smtpd(8) server:
+.IP "\fBremote_header_rewrite_context_name (local)\fR"
+The address rewriting context that should be used for incomplete
+mail header addresses from remote clients.
 .SH "ROUTING CONTROLS"
 .na
 .nf
index 39afc08fbe7ece0065955b23c1338672286ab6e1..2e2725f9070a2da5d23c00291b53cc9cde45c473 100755 (executable)
@@ -52,9 +52,9 @@ overview</a>
 
 <p> Each Postfix manual page is numbered after a section of the
 UNIX manual: examples are mailq(1) or access(5). Unfortunately,
-the organization of manual pages depends on the UNIX version being
-used.  Postfix documentation assumes the following convention:
-</p>
+there is no single universal method to organize manual pages; each
+UNIX flavor appears to be different. Postfix documentation assumes
+the following convention:  </p>
 
 <blockquote>
 
index b9abb42ccfb5a9cc5fea8f29e543ce1813621ff3..e09b82ada7158eef133b9b63d6032d6e382b2683 100755 (executable)
@@ -183,6 +183,7 @@ while (<>) {
     s;\binet_interfaces\b;<a href="postconf.5.html#inet_interfaces">$&</a>;g;
     s;\binitial_destination_concurrency\b;<a href="postconf.5.html#initial_destination_concurrency">$&</a>;g;
     s;\binvalid_hostname_reject_code\b;<a href="postconf.5.html#invalid_hostname_reject_code">$&</a>;g;
+    s;\binvalid_header_rewrite_con[-</bB>]*\n* *[<bB>]*text_domain\b;<a href="postconf.5.html#invalid_header_rewrite_context_domain">$&</a>;g;
     s;\bipc_idle\b;<a href="postconf.5.html#ipc_idle">$&</a>;g;
     s;\bipc_timeout\b;<a href="postconf.5.html#ipc_timeout">$&</a>;g;
     s;\bipc_ttl\b;<a href="postconf.5.html#ipc_ttl">$&</a>;g;
@@ -210,6 +211,7 @@ while (<>) {
     s;\blocal_recip[-</bB>]*\n* *[<bB>]*ient_maps\b;<a href="postconf.5.html#local_recipient_maps">$&</a>;g;
     s;\blocal_transport\b;<a href="postconf.5.html#local_transport">$&</a>;g;
     s;\bluser_relay\b;<a href="postconf.5.html#luser_relay">$&</a>;g;
+    s;\blocal_header_rewrite_con[-</bB>]*\n* *[<bB>]*text_clients\b;<a href="postconf.5.html#local_header_rewrite_context_clients">$&</a>;g;
     s;\bmail_name\b;<a href="postconf.5.html#mail_name">$&</a>;g;
     s;\bmail_owner\b;<a href="postconf.5.html#mail_owner">$&</a>;g;
     s;\bmail_release_date\b;<a href="postconf.5.html#mail_release_date">$&</a>;g;
@@ -238,11 +240,11 @@ while (<>) {
     s;\bminimal_backoff_time\b;<a href="postconf.5.html#minimal_backoff_time">$&</a>;g;
     s;\bmulti_recip[-</bB>]*\n* *[<bB>]*ient_bounce_reject_code\b;<a href="postconf.5.html#multi_recipient_bounce_reject_code">$&</a>;g;
     s;\bmydes[-</bB>]*\n*[ <bB>]*tina[-</bB>]*\n*[ <bB>]*tion\b;<a href="postconf.5.html#mydestination">$&</a>;g;
-    s;\bmydomain\b;<a href="postconf.5.html#mydomain">$&</a>;g;
+    s;\bmydo[-</bB>]*\n* *[<bB>]*main\b;<a href="postconf.5.html#mydomain">$&</a>;g;
     s;\bmyhostname\b;<a href="postconf.5.html#myhostname">$&</a>;g;
-    s;\bmynetworks\b;<a href="postconf.5.html#mynetworks">$&</a>;g;
+    s;\bmynet[-</bB>]*\n* *[<bB>]*works\b;<a href="postconf.5.html#mynetworks">$&</a>;g;
     s;\bmynetworks_style\b;<a href="postconf.5.html#mynetworks_style">$&</a>;g;
-    s;\bmyorigin\b;<a href="postconf.5.html#myorigin">$&</a>;g;
+    s;\bmyo[-</bB>]*\n*[ <bB>]*rigin\b;<a href="postconf.5.html#myorigin">$&</a>;g;
     s;\bnested_header_checks\b;<a href="postconf.5.html#nested_header_checks">$&</a>;g;
     s;\bnewaliases_path\b;<a href="postconf.5.html#newaliases_path">$&</a>;g;
     s;\bnon_fqdn_reject_code\b;<a href="postconf.5.html#non_fqdn_reject_code">$&</a>;g;
@@ -274,6 +276,7 @@ while (<>) {
     s;\brbl_reply_maps\b;<a href="postconf.5.html#rbl_reply_maps">$&</a>;g;
     s;\breadme_directory\b;<a href="postconf.5.html#readme_directory">$&</a>;g;
     s;\breceive_override_options\b;<a href="postconf.5.html#receive_override_options">$&</a>;g;
+    s;\bremote_header_rewrite_con[-</bB>]*\n* *[<bB>]*text_name\b;<a href="postconf.5.html#remote_header_rewrite_context_name">$&</a>;g;
     s;\bno_unknown_recip[-</bB>]*\n* *[<bB>]*ient_checks\b;<a href="postconf.5.html#no_unknown_recipient_checks">$&</a>;g;
     s;\bno_address_mappings\b;<a href="postconf.5.html#no_address_mappings">$&</a>;g;
     s;\bno_header_body_checks\b;<a href="postconf.5.html#no_header_body_checks">$&</a>;g;
@@ -494,6 +497,7 @@ while (<>) {
     s/[<bB>]*ldap[<\/bBiI>]*_[<\/iIbB>]*table[<\/bB>]*\(5\)/<a href="ldap_table.5.html">$&<\/a>/g;
     s/[<bB>]*mas[-<\/bB>]*\n* *[<bB>]*ter[<\/bB>]*\(5\)/<a href="master.5.html">$&<\/a>/g;
     s/[<bB>]*mysql[<\/bBiI>]*_[<\/iIbB>]*table[<\/bB>]*\(5\)/<a href="mysql_table.5.html">$&<\/a>/g;
+    s/[<bB>]*nisplus[<\/bBiI>]*_[<\/iIbB>]*table[<\/bB>]*\(5\)/<a href="nisplus_table.5.html">$&<\/a>/g;
     s/[<bB>]*pcre[<\/bBiI>]*_[<\/iIbB>]*table[<\/bB>]*\(5\)/<a href="pcre_table.5.html">$&<\/a>/g;
     s/[<bB>]*pgsql[<\/bBiI>]*_[<\/iIbB>]*table[<\/bB>]*\(5\)/<a href="pgsql_table.5.html">$&<\/a>/g;
     s/[<bB>]*postconf[<\/bB>]*\(5\)/<a href="postconf.5.html">$&<\/a>/g;
@@ -628,6 +632,7 @@ while (<>) {
     s/\b(proxy):/<a href="proxymap.8.html">$1<\/a>:/g;
     s/\b(pgsql):/<a href="pgsql_table.5.html">$1<\/a>:/g;
     s/\b(mysql):/<a href="mysql_table.5.html">$1<\/a>:/g;
+    s/\b(nisplus):/<a href="nisplus_table.5.html">$1<\/a>:/g;
     s/\b(ldap):/<a href="ldap_table.5.html">$1<\/a>:/g;
     s/\b(regexp):/<a href="regexp_table.5.html">$1<\/a>:/g;
     s/\b(tcp):/<a href="tcp_table.5.html">$1<\/a>:/g;
index 24576b87f59ea6274e0b8fd7cacc4e67f909c836..46e422fa8a944e6096160870b4e48b78102560bc 100644 (file)
@@ -315,7 +315,8 @@ of listing the patterns in the main.cf file. </p>
 <h2> <a name="relay_to"> What destinations to relay mail to </a> </h2>
 
 <p> By default, Postfix will forward mail from strangers (clients outside
-authorized networks) to authorized destinations only.  Authorized
+authorized networks) to authorized remote destinations only.
+Authorized remote
 destinations are defined with the relay_domains configuration
 parameter.  The default is to authorize all domains (and subdomains)
 of the domains listed with the mydestination parameter.  </p>
@@ -355,7 +356,9 @@ via a relay host. </p>
 </blockquote>
 
 <p> The form enclosed with <tt>[]</tt> eliminates DNS MX lookups.
-Don't worry if you don't know what that means. </p>
+Don't worry if you don't know what that means. Just be sure to
+specify the <tt>[]</tt> around the mailhub hostname that your ISP
+gave to you, otherwise mail may be mis-delivered. </p>
 
 <p> The STANDARD_CONFIGURATION_README file has more hints and tips
 for firewalled and/or dial-up networks. </p>
index 85f03e621c9c9f3a13472a4f8c9921ecbe2afef8..5fbd1d8ceb53f6c561764cbc45307add78d28029 100644 (file)
@@ -297,6 +297,19 @@ are given in the ldap_table(5). </dd>
 <dd> Perform MySQL database lookups. Configuration details are given
 in mysql_table(5). </dd>
 
+<dt> <b>netinfo</b> (read-only) </dt>
+
+<dd> Perform Netinfo database lookups. </dd>
+
+<dt> <b>nis</b> (read-only) </dt>
+
+<dd> Perform NIS database lookups. </dd>
+
+<dt> <b>nisplus</b> (read-only) </dt>
+
+<dd> Perform NIS+ database lookups. Configuration details are given
+in nisplus_table(5). </dd>
+
 <dt> <b>pcre</b> (read-only) </dt>
 
 <dd> A lookup table based on Perl Compatible Regular Expressions.
index 8bb58cac94313e3a766d164706e2369d69a4893b..743dc83b0d3d4ba44572ed4362f57091b107d760 100644 (file)
@@ -98,33 +98,12 @@ clobber:
 ../conf/canonical: canonical
        $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
 
-../conf/cidr_table: cidr_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
 ../conf/header_checks: header_checks
        $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
 
-../conf/ldap_table: ldap_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
-../conf/mysql_table: mysql_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
-../conf/pcre_table: pcre_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
-../conf/pgsql_table: pgsql_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
-../conf/regexp_table: regexp_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
 ../conf/relocated: relocated
        $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
 
-../conf/tcp_table: tcp_table
-       $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
-
 ../conf/transport: transport
        $(SRCTOMAN) - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
 
index 2c505849804d818ea157e28d8531b1eeec265461..5a8df4c546d8e085e668629e3cd366eb17ca537f 100644 (file)
@@ -8,9 +8,9 @@
 #
 #      \fBpostmap -q - cidr:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
 # DESCRIPTION
-#      The Postfix mail system uses optional access control tables.
+#      The Postfix mail system uses optional lookup tables.
 #      These tables are usually in \fBdbm\fR or \fBdb\fR format. 
-#      Alternatively, access control tables can be specified in CIDR 
+#      Alternatively, lookup tables can be specified in CIDR 
 #      (Classless Inter-Domain Routing) form.
 #
 #      To find out what types of lookup tables your Postfix system
diff --git a/postfix/proto/nisplus_table b/postfix/proto/nisplus_table
new file mode 100644 (file)
index 0000000..9ae2196
--- /dev/null
@@ -0,0 +1,85 @@
+#++
+# NAME
+#      nisplus_table 5
+# SUMMARY
+#      Postfix NIS+ client
+# SYNOPSIS
+#      \fBpostmap -q "\fIstring\fB" "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR
+#
+#      \fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR <\fIinputfile\fR
+# DESCRIPTION
+#      The Postfix mail system uses optional lookup tables.
+#      These tables are usually in \fBdbm\fR or \fBdb\fR format.
+#      Alternatively, lookup tables can be specified as NIS+
+#      databases.
+#
+#      To find out what types of lookup tables your Postfix system
+#      supports use the "\fBpostconf -m\fR" command.
+#
+#      To test Postfix NIS+ lookup tables, use the \fBpostmap\fR
+#      command as described in the SYNOPSIS above.
+# QUERY SYNTAX
+# .ad
+# .fi
+#      Most of the NIS+ query is specified via the NIS+ map name. The
+#      general format of a Postfix NIS+ map name is as follows:
+#
+# .ti +4
+#      \fBnisplus:[\fIname\fB=%s];\fIname.name.name\fB.:\fIcolumn\fR
+#
+#      Postfix NIS+ map names differ from what one normally
+#      would use with commands such as \fBniscat\fR:
+# .IP \(bu
+#      With each NIS+ table lookup, "\fB%s\fR" is replaced by a
+#      version of the lookup string.  There can be only one
+#      "\fB%s\fR" instance in a Postfix NIS+ map name.
+# .IP \(bu
+#      Postfix NIS+ map names use "\fB;\fR" instead of "\fB,\fR",
+#      because the latter character is special in the Postfix
+#      main.cf file.  Postfix replaces "\fB;\fR" characters in
+#      the map name by "\fB,\fR" before making NIS+ queries.
+# .IP \(bu
+#      The ":\fIcolumn\fR" part in the NIS+ map name is not part
+#      of the actual NIS+ query. Instead, it specifies the number
+#      of the table column that provides the lookup result. When
+#      no ":\fIcolumn\fR" is specified the first column (1) is used.
+# EXAMPLE
+#      A NIS+ aliases map might be queried as follows:
+#
+# .ti +4
+#      alias_maps = dbm:/etc/mail/aliases,
+# .ti +2
+#              nisplus:[alias=%s];mail_aliases.org_dir.$mydomain.:1
+# .ad
+# .fi
+#
+#      This queries the local aliases file before the NIS+ file.
+# SEE ALSO
+#      postmap(1), Postfix lookup table manager
+# README FILES
+# .ad
+# .fi
+#      Use "\fBpostconf readme_directory\fR" or
+#      "\fBpostconf html_directory\fR" to locate this information.
+# .na
+# .nf
+#      DATABASE_README, Postfix lookup table overview
+# LICENSE
+# .ad
+# .fi
+#      The Secure Mailer license must be distributed with this software.
+# AUTHOR(S)
+#      Geoff Gibbs
+#      UK-HGMP-RC
+#      Hinxton
+#      Cambridge
+#      CB10 1SB, UK
+#
+#      Based on the NIS client code:
+#
+#      Adopted and adapted by:
+#      Wietse Venema
+#      IBM T.J. Watson Research
+#      P.O. Box 704
+#      Yorktown Heights, NY 10598, USA
+#--
index 2c0388fad139a8549b9999e58087af99392cecf3..f0d306f12ee2d58b7c17331dcf8690a00292d998 100644 (file)
@@ -2794,7 +2794,7 @@ This feature is available in Postfix 2.0 and later.
 %PARAM receive_override_options 
 
 <p> Enable or disable recipient validation, built-in content
-filtering, or address rewriting. Typically, these are specified in
+filtering, or address mapping. Typically, these are specified in
 master.cf as command-line arguments for the smtpd(8), qmqpd(8) or
 pickup(8) daemons. </p>
 
@@ -5546,8 +5546,9 @@ and postdrop(1).
 %PARAM append_at_myorigin yes
 
 <p>
-Append the string "@$myorigin" to mail addresses without domain
-information.
+With locally submitted mail, append the string "@$myorigin" to mail
+addresses without domain information. With remotely submitted mail,
+append the string "@$invalid_domain" instead.
 </p>
 
 <p>
@@ -5558,8 +5559,9 @@ Postfix does not support domain-less addresses.
 %PARAM append_dot_mydomain yes
 
 <p>
-Append the string ".$mydomain" to addresses that have no ".domain"
-information.
+With locally submitted mail, append the string ".$mydomain" to
+addresses that have no ".domain" information. With remotely submitted
+mail, append the string ".$invalid_domain" instead.
 </p>
 
 <p>
@@ -7205,3 +7207,59 @@ is already bounded by $max_idle.  </p>
 <p> How frequently the scache(8) server logs usage statistics with
 session cache hit and miss rates for logical destinations and for
 physical endpoints. </p>
+
+%PARAM invalid_header_rewrite_context_domain domain.invalid
+
+<p> Append this domain to incomplete message header addresses from
+remote clients, when $remote_header_rewrite_context_name is set to
+"invalid".  This is one way to avoid appending your own domain to
+addresses in spam from poorly written software. </p>
+
+%PARAM local_header_rewrite_context_clients $inet_interfaces
+$mynetworks
+
+<p> Append the domain names in $myorigin and $mydomain to incomplete
+message header addresses from these clients.  </p>
+
+<p> Specify a list of network addresses or network/netmask patterns,
+separated by comma or whitespace. The list is matched left to right,
+and the search stops on the first match.  Specify !address or
+!network/netmask to exclude an address or network block from the
+list.  A network mask specifies the number of bits in the network
+part of a host address. Continue long lines by starting the next
+line with whitespace. </p>
+
+<p> You can also specify "/file/name" or "type:table" patterns.
+A "/file/name" pattern is replaced by its contents; a "type:table"
+lookup table is matched when a client name or address matches a
+lookup key (the lookup result is ignored). </p>
+
+%PARAM remote_header_rewrite_context_name local
+
+<p> The address rewriting context that should be used for incomplete
+mail header addresses from remote clients. </p>
+
+<ul>
+
+<li> <p> <b>local</b> Append the domains specified with $myorigin
+or $mydomain to incomplete message header addresses from remote
+clients.  </p>
+
+<li> <p> <b>invalid</b> Append the domain specified with
+$invalid_header_rewrite_context_domain to incomplete message header
+addresses from remote clients. This is one way to avoid appending
+your own domain to addresses in spam from poorly written software.
+This is a safe choice for gateways that have no control over
+address rewriting by down-stream systems.
+</p>
+
+<li> <p> <b>none</b> Don't modify message headers from remote
+clients at all. This is another way to avoid appending your own
+domain to addresses in spam from poorly written software. This
+is the preferred choice for purists. </p>
+
+</ul>
+
+<p> Note: Postfix always appends the domains specified with $myorigin
+or $mydomain to incomplete envelope addresses, because those
+addresses are effectively equivalent to local addresses. </p>
index b1a884c5826f84d0b9aa7626ad8d959991750a9a..ba2aea0863ab8856ecf2569da2b0a70a5783962a 100644 (file)
@@ -186,12 +186,16 @@ cleanup_envelope.o: ../../include/mymalloc.h
 cleanup_envelope.o: ../../include/stringops.h
 cleanup_envelope.o: ../../include/nvtable.h
 cleanup_envelope.o: ../../include/htable.h
+cleanup_envelope.o: ../../include/name_code.h
 cleanup_envelope.o: ../../include/record.h
 cleanup_envelope.o: ../../include/rec_type.h
 cleanup_envelope.o: ../../include/cleanup_user.h
 cleanup_envelope.o: ../../include/qmgr_user.h
 cleanup_envelope.o: ../../include/mail_params.h
 cleanup_envelope.o: ../../include/verp_sender.h
+cleanup_envelope.o: ../../include/mail_proto.h
+cleanup_envelope.o: ../../include/iostuff.h
+cleanup_envelope.o: ../../include/attr.h
 cleanup_envelope.o: cleanup.h
 cleanup_envelope.o: ../../include/argv.h
 cleanup_envelope.o: ../../include/maps.h
@@ -447,9 +451,10 @@ cleanup_rewrite.o: ../../include/vstring.h
 cleanup_rewrite.o: ../../include/vbuf.h
 cleanup_rewrite.o: ../../include/tok822.h
 cleanup_rewrite.o: ../../include/resolve_clnt.h
-cleanup_rewrite.o: ../../include/rewrite_clnt.h
 cleanup_rewrite.o: ../../include/quote_822_local.h
 cleanup_rewrite.o: ../../include/quote_flags.h
+cleanup_rewrite.o: ../../include/rewrite_clnt.h
+cleanup_rewrite.o: ../../include/mail_params.h
 cleanup_rewrite.o: cleanup.h
 cleanup_rewrite.o: ../../include/vstream.h
 cleanup_rewrite.o: ../../include/argv.h
index ec57f6c5ad5dd9845c771948484ad586805f6889..ebb34a07bc9fafade80d934ff91cf6dae97ce154 100644 (file)
 /*     message contains no To: or Cc: message header.
 /* .PP
 /*     Available in Postfix version 2.1 and later:
-/* .IP "\fBenable_errors_to (no)\fR"
-/*     Report mail delivery errors to the address specified with the
-/*     non-standard Errors-To: message header, instead of the envelope
-/*     sender address.
 /* BUILT-IN CONTENT FILTERING CONTROLS
 /* .ad
 /* .fi
index 65ff8bc46a4e46ee8e5bf04edc88a16ccd828bb9..8ec055ec2b421a5385d86e0f2dbd595f8b1bac02 100644 (file)
@@ -41,8 +41,6 @@ typedef struct CLEANUP_STATE {
     time_t  time;                      /* posting time */
     char   *fullname;                  /* envelope sender full name */
     char   *sender;                    /* envelope sender address */
-    char   *from;                      /* From: address */
-    char   *resent_from;               /* Resent-From: address */
     char   *recip;                     /* envelope recipient address */
     char   *orig_rcpt;                 /* original recipient address */
     char   *return_receipt;            /* return-receipt address */
@@ -63,6 +61,7 @@ typedef struct CLEANUP_STATE {
     NVTABLE *attr;                     /* queue file attribute list */
     MIME_STATE *mime_state;            /* MIME state engine */
     int     mime_errs;                 /* MIME error flags */
+    char   *rewrite_context_name;      /* address rewrite context */
     char   *filter;                    /* from header/body patterns */
     char   *redirect;                  /* from header/body patterns */
 } CLEANUP_STATE;
@@ -175,9 +174,9 @@ extern void cleanup_extracted(CLEANUP_STATE *, int, const char *, int);
  /*
   * cleanup_rewrite.c
   */
-extern void cleanup_rewrite_external(VSTRING *, const char *);
-extern void cleanup_rewrite_internal(VSTRING *, const char *);
-extern void cleanup_rewrite_tree(TOK822 *);
+extern void cleanup_rewrite_external(const char *, VSTRING *, const char *);
+extern void cleanup_rewrite_internal(const char *, VSTRING *, const char *);
+extern void cleanup_rewrite_tree(const char *, TOK822 *);
 
  /*
   * cleanup_map11.c
index fc00523c76bfe02dd067751bf6be10f9365d37d1..dab7dbf4b0431d223ef87fef14fcbf1494019b99 100644 (file)
@@ -83,6 +83,7 @@
 
 #define STR                    vstring_str
 #define IGNORE_EXTENSION       (char **) 0
+#define STREQ(x,y)             (strcmp((x), (y)) == 0)
 
 /* cleanup_addr_sender - process envelope sender record */
 
@@ -91,7 +92,7 @@ void    cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
     VSTRING *clean_addr = vstring_alloc(100);
     const char *bcc;
 
-    cleanup_rewrite_internal(clean_addr, buf);
+    cleanup_rewrite_internal(REWRITE_LOCAL, clean_addr, buf);
     if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
                    sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
        canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
@@ -130,7 +131,8 @@ void    cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
     VSTRING *clean_addr = vstring_alloc(100);
     const char *bcc;
 
-    cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr);
+    cleanup_rewrite_internal(REWRITE_LOCAL,
+                            clean_addr, *buf ? buf : var_empty_addr);
     if (state->flags & CLEANUP_FLAG_MAP_OK) {
        if (cleanup_rcpt_canon_maps
            && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
@@ -162,7 +164,7 @@ void    cleanup_addr_bcc(CLEANUP_STATE *state, const char *bcc)
 {
     VSTRING *clean_addr = vstring_alloc(100);
 
-    cleanup_rewrite_internal(clean_addr, bcc);
+    cleanup_rewrite_internal(REWRITE_LOCAL, clean_addr, bcc);
     if (state->flags & CLEANUP_FLAG_MAP_OK) {
        if (cleanup_rcpt_canon_maps
            && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
index 68587e180c1bcf5aeea32a6c0435e6b9210e82f5..56d36c8eb0a658d28a45f49a7e71145ae9ad5b55 100644 (file)
@@ -57,6 +57,7 @@
 #include <mymalloc.h>
 #include <stringops.h>
 #include <nvtable.h>
+#include <name_code.h>
 
 /* Global library. */
 
@@ -66,6 +67,7 @@
 #include <qmgr_user.h>
 #include <mail_params.h>
 #include <verp_sender.h>
+#include <mail_proto.h>
 
 /* Application-specific. */
 
@@ -109,6 +111,12 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
     char   *attr_value;
     const char *error_text;
     int     extra_opts;
+    NAME_CODE rewrite_context_names[] = {
+       REWRITE_LOCAL, 1,
+       REWRITE_INVALID, 1,
+       REWRITE_NONE, 1,
+       0, 0,
+    };
 
     if (msg_verbose)
        msg_info("initial envelope %c %.*s", type, len, buf);
@@ -278,6 +286,18 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
            myfree(sbuf);
            return;
        }
+       if (strcmp(attr_name, MAIL_ATTR_RWR_CTXT_NAME) == 0) {
+           if (name_code(rewrite_context_names, NAME_CODE_FLAG_STRICT_CASE,
+                         attr_value) == 0) {
+               msg_warn("%s: message rejected: bad rewriting context: %.100s",
+                        state->queue_id, attr_value);
+               state->errs |= CLEANUP_STAT_BAD;
+               return;
+           } else {
+               myfree(state->rewrite_context_name);
+               state->rewrite_context_name = mystrdup(attr_value);
+           }
+       }
        nvtable_update(state->attr, attr_name, attr_value);
        myfree(sbuf);
        cleanup_out(state, type, buf, len);
index ef51ae29930d6280464c528177b404a18b916d65..c3b8459cba58baa46f88ef2c75224eba0e1493c3 100644 (file)
@@ -121,7 +121,6 @@ int     var_virt_expan_limit;               /* maximum virtual alias expansion */
 int     var_body_check_len;            /* when to stop body scan */
 char   *var_send_bcc_maps;             /* sender auto-bcc maps */
 char   *var_rcpt_bcc_maps;             /* recipient auto-bcc maps */
-bool    var_enable_errors_to;          /* extract Errors-To: address. */
 
 CONFIG_INT_TABLE cleanup_int_table[] = {
     VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
@@ -135,7 +134,6 @@ CONFIG_INT_TABLE cleanup_int_table[] = {
 
 CONFIG_BOOL_TABLE cleanup_bool_table[] = {
     VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt,
-    VAR_ENABLE_ERRORS_TO, DEF_ENABLE_ERRORS_TO, &var_enable_errors_to,
     0,
 };
 
index 8a5965a06d4b91e027bbec1f93e0404e9ee9c9a0..ddbc793a992c4241b73b71be4fb62ac716943a40 100644 (file)
@@ -166,16 +166,16 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
        msg_info("rewrite_sender: %s", hdr_opts->name);
 
     /*
-     * Parse the header line, rewrite each address found, save copies of
-     * sender addresses, and regenerate the header line. Finally, pipe the
-     * result through the header line folding routine.
+     * Parse the header line, rewrite each address found, and regenerate the
+     * header line. Finally, pipe the result through the header line folding
+     * routine.
      */
     tree = tok822_parse_limit(vstring_str(header_buf)
                              + strlen(hdr_opts->name) + 1,
                              var_token_limit);
     addr_list = tok822_grep(tree, TOK822_ADDR);
     for (tpp = addr_list; *tpp; tpp++) {
-       cleanup_rewrite_tree(*tpp);
+       cleanup_rewrite_tree(state->rewrite_context_name, *tpp);
        if (state->flags & CLEANUP_FLAG_MAP_OK) {
            if (cleanup_send_canon_maps
                && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
@@ -189,20 +189,6 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
                && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
                cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
        }
-       if (hdr_opts->type == HDR_FROM && state->from == 0)
-           state->from = cleanup_extract_internal(header_buf, *tpp);
-       if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0)
-           state->resent_from =
-               cleanup_extract_internal(header_buf, *tpp);
-#if 0
-       if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
-           state->return_receipt =
-               cleanup_extract_internal(header_buf, *tpp);
-#endif
-       if (var_enable_errors_to)
-           if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
-               state->errors_to =
-                   cleanup_extract_internal(header_buf, *tpp);
     }
     vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
     tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
@@ -225,16 +211,16 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
        msg_info("rewrite_recip: %s", hdr_opts->name);
 
     /*
-     * Parse the header line, rewrite each address found, save copies of
-     * recipient addresses, and regenerate the header line. Finally, pipe the
-     * result through the header line folding routine.
+     * Parse the header line, rewrite each address found, and regenerate the
+     * header line. Finally, pipe the result through the header line folding
+     * routine.
      */
     tree = tok822_parse_limit(vstring_str(header_buf)
                              + strlen(hdr_opts->name) + 1,
                              var_token_limit);
     addr_list = tok822_grep(tree, TOK822_ADDR);
     for (tpp = addr_list; *tpp; tpp++) {
-       cleanup_rewrite_tree(*tpp);
+       cleanup_rewrite_tree(state->rewrite_context_name, *tpp);
        if (state->flags & CLEANUP_FLAG_MAP_OK) {
            if (cleanup_rcpt_canon_maps
                && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
@@ -511,9 +497,11 @@ static void cleanup_header_callback(void *context, int header_class,
        if (CLEANUP_OUT_OK(state)) {
            if (hdr_opts->flags & HDR_OPT_RR)
                state->resent = "Resent-";
-           if (hdr_opts->flags & HDR_OPT_SENDER) {
+           if ((hdr_opts->flags & HDR_OPT_SENDER)
+               && strcmp(state->rewrite_context_name, REWRITE_NONE) != 0) {
                cleanup_rewrite_sender(state, hdr_opts, header_buf);
-           } else if (hdr_opts->flags & HDR_OPT_RECIP) {
+           } else if ((hdr_opts->flags & HDR_OPT_RECIP)
+               && strcmp(state->rewrite_context_name, REWRITE_NONE) != 0) {
                cleanup_rewrite_recip(state, hdr_opts, header_buf);
            } else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
                cleanup_out_header(state, header_buf);
index 1ae6871d8bf9f9ef42fa1580d2494384a809acd0..6bc57f0e19b820084982097368072a9baf8f624d 100644 (file)
@@ -6,15 +6,18 @@
 /* SYNOPSIS
 /*     #include <cleanup.h>
 /*
-/*     void    cleanup_rewrite_external(result, addr)
+/*     void    cleanup_rewrite_external(context_name, result, addr)
+/*     const char *context;
 /*     VSTRING *result;
 /*     const char *addr;
 /*
-/*     void    cleanup_rewrite_internal(result, addr)
+/*     void    cleanup_rewrite_internal(context_name, result, addr)
+/*     const char *context;
 /*     VSTRING *result;
 /*     const char *addr;
 /*
-/*     void    cleanup_rewrite_tree(tree)
+/*     void    cleanup_rewrite_tree(context_name, tree)
+/*     const char *context;
 /*     TOK822  *tree;
 /* DESCRIPTION
 /*     This module rewrites addresses to canonical form, adding missing
 /*     cleanup_rewrite_tree() is a wrapper around the
 /*     cleanup_rewrite_external() routine that transforms from
 /*     internal parse tree form to external form and back.
+/*
+/*     Arguments:
+/* .IP context_name
+/*     The name of an address rewriting context that supplies
+/*     the equivalents of myorigin and mydomain.
+/* .IP result
+/*     Result buffer.
+/* .IP addr
+/*     Input buffer.
 /* DIAGNOSTICS
 /* LICENSE
 /* .ad
@@ -57,8 +69,8 @@
 /* Global library. */
 
 #include <tok822.h>
-#include <rewrite_clnt.h>
 #include <quote_822_local.h>
+#include <rewrite_clnt.h>
 
 /* Application-specific. */
 
 
 /* cleanup_rewrite_external - rewrite address external form */
 
-void    cleanup_rewrite_external(VSTRING *result, const char *addr)
+void    cleanup_rewrite_external(const char *context_name, VSTRING *result,
+                                        const char *addr)
 {
-    rewrite_clnt(REWRITE_CANON, addr, result);
+    rewrite_clnt(context_name, addr, result);
 }
 
 /* cleanup_rewrite_tree - rewrite address node */
 
-void    cleanup_rewrite_tree(TOK822 *tree)
+void    cleanup_rewrite_tree(const char *context_name, TOK822 *tree)
 {
     VSTRING *dst = vstring_alloc(100);
     VSTRING *src = vstring_alloc(100);
 
     tok822_externalize(src, tree->head, TOK822_STR_DEFL);
-    cleanup_rewrite_external(dst, STR(src));
+    cleanup_rewrite_external(context_name, dst, STR(src));
     tok822_free_tree(tree->head);
     tree->head = tok822_scan(STR(dst), &tree->tail);
     vstring_free(dst);
@@ -90,13 +103,14 @@ void    cleanup_rewrite_tree(TOK822 *tree)
 
 /* cleanup_rewrite_internal - rewrite address internal form */
 
-void    cleanup_rewrite_internal(VSTRING *result, const char *addr)
+void    cleanup_rewrite_internal(const char *context_name,
+                                        VSTRING *result, const char *addr)
 {
     VSTRING *dst = vstring_alloc(100);
     VSTRING *src = vstring_alloc(100);
 
     quote_822_local(src, addr);
-    cleanup_rewrite_external(dst, STR(src));
+    cleanup_rewrite_external(context_name, dst, STR(src));
     unquote_822_local(result, STR(dst));
     vstring_free(dst);
     vstring_free(src);
index a22a32d6f0984b018747fa163cf1bb127af3e3db..161bccbe9d1d47cf729b24f487dcecc6b4db9eac 100644 (file)
@@ -64,8 +64,6 @@ CLEANUP_STATE *cleanup_state_alloc(void)
     state->time = 0;
     state->fullname = 0;
     state->sender = 0;
-    state->from = 0;
-    state->resent_from = 0;
     state->recip = 0;
     state->orig_rcpt = 0;
     state->return_receipt = 0;
@@ -86,6 +84,7 @@ CLEANUP_STATE *cleanup_state_alloc(void)
     state->attr = nvtable_create(10);
     state->mime_state = 0;
     state->mime_errs = 0;
+    state->rewrite_context_name = mystrdup(REWRITE_LOCAL);
     state->filter = 0;
     state->redirect = 0;
     return (state);
@@ -101,10 +100,6 @@ void    cleanup_state_free(CLEANUP_STATE *state)
        myfree(state->fullname);
     if (state->sender)
        myfree(state->sender);
-    if (state->from)
-       myfree(state->from);
-    if (state->resent_from)
-       myfree(state->resent_from);
     if (state->recip)
        myfree(state->recip);
     if (state->orig_rcpt)
@@ -127,5 +122,7 @@ void    cleanup_state_free(CLEANUP_STATE *state)
        myfree(state->filter);
     if (state->redirect)
        myfree(state->redirect);
+    if (state->rewrite_context_name)
+       myfree(state->rewrite_context_name);
     myfree((char *) state);
 }
index 1dd4f6c0a0828d1f1b51586833f3a22efc4ff2f0..a281c7f2d085fec919e50fd632654154f0610d7d 100644 (file)
@@ -455,6 +455,7 @@ canon_addr.o: ../../include/vstring.h
 canon_addr.o: ../../include/vbuf.h
 canon_addr.o: ../../include/mymalloc.h
 canon_addr.o: rewrite_clnt.h
+canon_addr.o: mail_params.h
 canon_addr.o: canon_addr.h
 cfg_parser.o: cfg_parser.c
 cfg_parser.o: ../../include/sys_defs.h
@@ -1381,6 +1382,7 @@ tok822_rewrite.o: ../../include/vstring.h
 tok822_rewrite.o: ../../include/vbuf.h
 tok822_rewrite.o: ../../include/msg.h
 tok822_rewrite.o: rewrite_clnt.h
+tok822_rewrite.o: mail_params.h
 tok822_rewrite.o: tok822.h
 tok822_rewrite.o: resolve_clnt.h
 tok822_tree.o: tok822_tree.c
index 7a87b9d5565a1b8376b28c70e9a67167c41f1bb7..c93aef1434e57e4cac05a1724276f8a0d88f3e0c 100644 (file)
@@ -114,6 +114,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, request->sasl_method,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, request->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, request->sasl_sender,
+              ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, request->rewrite_context,
               ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offs,
               ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orcpt,
               ATTR_TYPE_STR, MAIL_ATTR_RECIP, addr,
index 7ec7968995e7909a151da56a9ccb3868e43a844b..39c835848aa2433e9e9e353f1d8a1018c1709252 100644 (file)
@@ -29,6 +29,7 @@
 /*             char    *sasl_method;
 /*             char    *sasl_username;
 /*             char    *sasl_sender;
+/*             char    *rewrite_context;
 /* .in -5
 /*     } DELIVER_REQUEST;
 /*
@@ -189,6 +190,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     static VSTRING *sasl_method;
     static VSTRING *sasl_username;
     static VSTRING *sasl_sender;
+    static VSTRING *rewrite_context;
     long    offset;
 
     /*
@@ -212,6 +214,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
        sasl_method = vstring_alloc(10);
        sasl_username = vstring_alloc(10);
        sasl_sender = vstring_alloc(10);
+       rewrite_context = vstring_alloc(10);
     }
 
     /*
@@ -237,7 +240,8 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, sasl_method,
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username,
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
-                 ATTR_TYPE_END) != 18) {
+                 ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, rewrite_context,
+                 ATTR_TYPE_END) != 19) {
        msg_warn("%s: error receiving common attributes", myname);
        return (-1);
     }
@@ -259,6 +263,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     request->sasl_method = mystrdup(vstring_str(sasl_method));
     request->sasl_username = mystrdup(vstring_str(sasl_username));
     request->sasl_sender = mystrdup(vstring_str(sasl_sender));
+    request->rewrite_context = mystrdup(vstring_str(rewrite_context));
 
     /*
      * Extract the recipient offset and address list. Skip over any
index badeba9658b70a43164e160ffb109c4329f4333e..33f37afac3c5de7c92da55768f70ec786cc4eb3f 100644 (file)
@@ -47,6 +47,7 @@ typedef struct DELIVER_REQUEST {
     char   *sasl_method;               /* SASL method */
     char   *sasl_username;             /* SASL user name */
     char   *sasl_sender;               /* SASL sender */
+    char   *rewrite_context;           /* header rewrite context */
 } DELIVER_REQUEST;
 
  /*
index 30811aa64570272046f5a15f4bff58af7953b9f1..1c59cc3be7e74e18ec6f7889e3b22c1d7c57aa62 100644 (file)
@@ -551,10 +551,6 @@ extern char *var_deliver_hdr;
 #define DEF_ENABLE_ORCPT       1
 extern bool var_enable_orcpt;
 
-#define VAR_ENABLE_ERRORS_TO   "enable_errors_to"
-#define DEF_ENABLE_ERRORS_TO   0
-extern bool var_enable_errors_to;
-
 #define VAR_EXP_OWN_ALIAS      "expand_owner_alias"
 #define DEF_EXP_OWN_ALIAS      0
 extern bool var_exp_own_alias;
@@ -2092,6 +2088,26 @@ extern char *var_anvil_service;
 
 #endif
 
+ /*
+  * What domain names to assume when no valid domain context exists.
+  */
+#define VAR_INV_RWR_DOMAIN             "invalid_header_rewrite_context_domain"
+#define DEF_INV_RWR_DOMAIN             "domain.invalid"
+extern char *var_inv_rwr_domain;
+
+#define VAR_REM_RWR_NAME               "remote_header_rewrite_context_name"
+#define DEF_REM_RWR_NAME               REWRITE_LOCAL
+extern char *var_remote_rwr_name;
+
+#define REWRITE_LOCAL  "local"
+#define REWRITE_INVALID        "invalid"
+#define REWRITE_NONE   "none"
+
+#define VAR_LOC_RWR_CLIENTS            "local_header_rewrite_context_clients"
+#define DEF_LOC_RWR_CLIENTS            "$" VAR_INET_INTERFACES \
+                                       " $" VAR_MYNETWORKS
+extern char *var_local_rwr_clients;
+
 /* LICENSE
 /* .ad
 /* .fi
index baa5aa54f3fa5bad44d9a7811280ab91036533b5..222e51e08c8d105698a547ab00738a48fc6c5795 100644 (file)
@@ -122,6 +122,7 @@ extern char *mail_pathname(const char *, const char *);
 #define MAIL_ATTR_SASL_USERNAME        "sasl_username"
 #define MAIL_ATTR_SASL_SENDER  "sasl_sender"
 #define MAIL_ATTR_DUMMY                "dummy"
+#define MAIL_ATTR_RWR_CTXT_NAME        "rewrite_context_name"
 
 #define MAIL_ATTR_TTL          "ttl"
 #define MAIL_ATTR_LABEL                "label"
@@ -179,6 +180,9 @@ extern char *mail_pathname(const char *, const char *);
 #define XFORWARD_PROTO         "PROTO"         /* client protocol */
 #define XFORWARD_HELO          "HELO"          /* client helo */
 #define XFORWARD_IDENT         "IDENT"         /* message identifier */
+#define XFORWARD_DOMAIN                "DOMAIN"        /* origin type */
+#define XFORWARD_DOM_LOCAL     "LOCAL"         /* local origin */
+#define XFORWARD_DOM_REMOTE    "REMOTE"        /* remote origin */
 
 #define XFORWARD_UNAVAILABLE   "[UNAVAILABLE]" /* attribute unavailable */
 
index f5946af921653165698a389fc65a6e6990c64cdb..98f0e70924afec7aa6972477ab5f947c88d1895d 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20041013"
+#define MAIL_RELEASE_DATE      "20041019"
 #define MAIL_VERSION_NUMBER    "2.2"
 
 #define VAR_MAIL_VERSION       "mail_version"
index a914f616fbe6edc7c883e2c9e6c9160c51b962ff..d366437714512eeeb6e1422237ecbd6d4e6b4b40 100644 (file)
@@ -15,7 +15,8 @@
 /*
 /*     match_parent_style() looks up "name" in the
 /*      parent_domain_matches_subdomain configuration parameter
-/*     and returns either MATCH_FLAG_PARENT or MATCH_PARENT_NONE.
+/*     and returns either MATCH_FLAG_PARENT (parent domain matches
+/*     subdomains) or MATCH_FLAG_NONE.
 /* DIAGNOSTICS
 /*     Fatal error: out of memory, name listed under both parent wild card
 /*     matching policies.
index ac28d25463c2129ac07cb9002b8e5748cbc0afad..db4545ea44b4d9116fe9a063491c18f02e34d870 100644 (file)
@@ -82,6 +82,12 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
 {
     VSTREAM *stream;
 
+    /*
+     * Sanity check.
+     */
+    if (strcmp(rule, REWRITE_NONE) == 0)
+       msg_panic("rewrite_clnt: bad rewrite context: \"%s\"", rule);
+
     /*
      * One-entry cache.
      */
index 8e22301802a2d3dec84b787a697862748a14c9c0..0910b812e5b44f3b350b3b890ec7d8f826fe2114 100644 (file)
   * Utility library.
   */
 #include <vstring.h>
+#include <mail_params.h>
 
  /*
   * External interface.
   */
 #define REWRITE_ADDR   "rewrite"
-#define REWRITE_CANON  "canonicalize"
+#define REWRITE_CANON  REWRITE_LOCAL   /* backwards compatibility */
 
 extern VSTRING *rewrite_clnt(const char *, const char *, VSTRING *);
 extern VSTRING *rewrite_clnt_internal(const char *, const char *, VSTRING *);
index 4f79ebc276ab6890298fa76787dc8ad54ec88f95..a66fc206410aab65f4016f488f54c51a0a2082b8 100644 (file)
@@ -1,13 +1,26 @@
-x !
-x a!
-x !b
-x a!b
-x %
-x a%
-x %b
-x a%b
-x @
-x a@
-x a@.
-x a@b
-x a@b.
+canonical !
+canonical a!
+canonical !b
+canonical a!b
+canonical %
+canonical a%
+canonical %b
+canonical a%b
+canonical @
+canonical a@
+canonical a@.
+canonical a@b
+canonical a@b.
+invalid !
+invalid a!
+invalid !b
+invalid a!b
+invalid %
+invalid a%
+invalid %b
+invalid a%b
+invalid @
+invalid a@
+invalid a@.
+invalid a@b
+invalid a@b.
index b1df129865c13f3eec953ef777c75027805afcf2..328d0e1a189a1eb126492849f4d188c681b9769c 100644 (file)
-rule       x
+rule       canonical
 address    !
 result     ""@
 
-rule       x
+rule       canonical
 address    a!
 result     ""@a.MYDOMAIN
 
-rule       x
+rule       canonical
 address    !b
 result     b@
 
-rule       x
+rule       canonical
 address    a!b
 result     b@a.MYDOMAIN
 
-rule       x
+rule       canonical
 address    %
 result     ""@
 
-rule       x
+rule       canonical
 address    a%
 result     a@
 
-rule       x
+rule       canonical
 address    %b
 result     ""@b.MYDOMAIN
 
-rule       x
+rule       canonical
 address    a%b
 result     a@b.MYDOMAIN
 
-rule       x
+rule       canonical
 address    @
 result     ""
 
-rule       x
+rule       canonical
 address    a@
 result     a@
 
-rule       x
+rule       canonical
 address    a@.
 result     a@.
 
-rule       x
+rule       canonical
 address    a@b
 result     a@b.MYDOMAIN
 
-rule       x
+rule       canonical
+address    a@b.
+result     a@b
+
+rule       invalid
+address    !
+result     ""@
+
+rule       invalid
+address    a!
+result     ""@a.domain.invalid
+
+rule       invalid
+address    !b
+result     b@
+
+rule       invalid
+address    a!b
+result     b@a.domain.invalid
+
+rule       invalid
+address    %
+result     ""@
+
+rule       invalid
+address    a%
+result     a@
+
+rule       invalid
+address    %b
+result     ""@b.domain.invalid
+
+rule       invalid
+address    a%b
+result     a@b.domain.invalid
+
+rule       invalid
+address    @
+result     ""
+
+rule       invalid
+address    a@
+result     a@
+
+rule       invalid
+address    a@.
+result     a@.
+
+rule       invalid
+address    a@b
+result     a@b.domain.invalid
+
+rule       invalid
 address    a@b.
 result     a@b
 
index 40f687c490e0d469be8896af6849a0b6e7ad2a0a..2c30226c489d2907c111194fdaaa12085ae06400 100644 (file)
@@ -65,6 +65,7 @@ typedef struct LMTP_STATE {
 #define LMTP_FEATURE_XFORWARD_ADDR (1<<7)
 #define LMTP_FEATURE_XFORWARD_PROTO (1<<8)
 #define LMTP_FEATURE_XFORWARD_HELO (1<<9)
+#define LMTP_FEATURE_XFORWARD_DOMAIN (1<<10)
 
  /*
   * lmtp.c
index 8251d6edcfc08dc45a5d44d22ff14f8c1949b193..b45543ed8566672f7ae4f26e6080e84886c3dcb4 100644 (file)
@@ -209,6 +209,7 @@ int     lmtp_lhlo(LMTP_STATE *state)
        XFORWARD_ADDR, LMTP_FEATURE_XFORWARD_ADDR,
        XFORWARD_PROTO, LMTP_FEATURE_XFORWARD_PROTO,
        XFORWARD_HELO, LMTP_FEATURE_XFORWARD_HELO,
+       XFORWARD_DOMAIN, LMTP_FEATURE_XFORWARD_DOMAIN,
        0, 0,
     };
 
@@ -418,6 +419,12 @@ static int lmtp_loop(LMTP_STATE *state, NOCLOBBER int send_state,
                vstring_sprintf_append(next_command, " %s=%s",
                   XFORWARD_HELO, DEL_REQ_ATTR_AVAIL(request->client_helo) ?
                               request->client_helo : XFORWARD_UNAVAILABLE);
+            if (state->features & LMTP_FEATURE_XFORWARD_DOMAIN)
+                vstring_sprintf_append(next_command, " %s=%s", XFORWARD_DOMAIN,
+                         DEL_REQ_ATTR_AVAIL(request->rewrite_context) == 0 ?
+                                       XFORWARD_UNAVAILABLE :
+                           strcmp(request->rewrite_context, REWRITE_LOCAL) ?
+                                  XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE);
            next_state = LMTP_STATE_MAIL;
            break;
 
index 60b4c78dc6d08e90c732b01f87d57b13a068ceb9..6987e83d34b48493dcfe2cd1880ba46c86526f6a 100644 (file)
@@ -438,8 +438,8 @@ resolve.o: ../../include/iostuff.h
 resolve.o: ../../include/attr.h
 resolve.o: ../../include/resolve_clnt.h
 resolve.o: ../../include/rewrite_clnt.h
-resolve.o: ../../include/tok822.h
 resolve.o: ../../include/mail_params.h
+resolve.o: ../../include/tok822.h
 resolve.o: ../../include/defer.h
 resolve.o: ../../include/bounce.h
 resolve.o: ../../include/deliver_request.h
index 37a7e44bc4d782a7926366ab78cca78258024039..4451a2d44e387dae3f66333c9a341188d13c1927 100644 (file)
@@ -188,6 +188,7 @@ qmgr_message.o: ../../include/mail_proto.h
 qmgr_message.o: ../../include/iostuff.h
 qmgr_message.o: ../../include/attr.h
 qmgr_message.o: ../../include/qmgr_user.h
+qmgr_message.o: ../../include/split_addr.h
 qmgr_message.o: ../../include/rewrite_clnt.h
 qmgr_message.o: ../../include/resolve_clnt.h
 qmgr_message.o: qmgr.h
index b1141836668fc496a02073cbc11ffe78e68baff3..0cac1664d6155ed2409738a2c9cb9e9f2a163460 100644 (file)
@@ -246,6 +246,7 @@ struct QMGR_MESSAGE {
     char   *sasl_method;               /* SASL method */
     char   *sasl_username;             /* SASL user name */
     char   *sasl_sender;               /* SASL sender */
+    char   *rewrite_context;           /* address qualification */
     QMGR_RCPT_LIST rcpt_list;          /* complete addresses */
 };
 
index f9556efd54b88dce8bda3e131bc7a3a22989dcb8..0c55ab300d1a81b14a861ddaa3e794c89707e932 100644 (file)
@@ -162,8 +162,9 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
               ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
-              ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
+            ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
+          ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, message->rewrite_context,
               ATTR_TYPE_END);
     if (sender_buf != 0)
        vstring_free(sender_buf);
index fbe0606c8cc952e2b8d0b767ab2d827f9c57156a..b015d9ee624a1134a58588e825f72c18b50421bf 100644 (file)
 #include <verp_sender.h>
 #include <mail_proto.h>
 #include <qmgr_user.h>
+#include <split_addr.h>
 
 /* Client stubs. */
 
@@ -175,6 +176,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->sasl_method = 0;
     message->sasl_username = 0;
     message->sasl_sender = 0;
+    message->rewrite_context = 0;
     qmgr_rcpt_list_init(&message->rcpt_list);
     return (message);
 }
@@ -549,6 +551,13 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    msg_warn("%s: ignoring multiple %s attribute: %s",
                        message->queue_id, MAIL_ATTR_SASL_SENDER, value);
            }
+           if (strcmp(name, MAIL_ATTR_RWR_CTXT_NAME) == 0) {
+               if (message->rewrite_context == 0)
+                   message->rewrite_context = mystrdup(value);
+               else
+                   msg_warn("%s: ignoring multiple %s attribute: %s",
+                       message->queue_id, MAIL_ATTR_RWR_CTXT_NAME, value);
+           }
            /* Optional tracing flags. */
            else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
                message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@@ -628,6 +637,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        message->sasl_username = mystrdup("");
     if (message->sasl_sender == 0)
        message->sasl_sender = mystrdup("");
+    if (message->rewrite_context == 0)
+       message->rewrite_context = mystrdup("");
 
     /*
      * Clean up.
index 24ed673a3597772be29d187762d7afccd8dfc290..c5ad8e643cc5debd21e7681162c7d8dfc76fcecb 100644 (file)
 /*     cidr_table(5), Associate CIDR pattern with value
 /*     ldap_table(5), Postfix LDAP client
 /*     mysql_table(5), Postfix MYSQL client
+/*     nisplus_table(5), Postfix NIS+ client
 /*     pcre_table(5), Associate PCRE pattern with value
 /*     pgsql_table(5), Postfix PostgreSQL client
 /*     regexp_table(5), Associate POSIX regexp pattern with value
index 368bd255c30d2ed57dab2d56a66de52a42e63dbd..e069952ae5fe79923642fb3b99771c1b9723bd5c 100644 (file)
@@ -201,6 +201,7 @@ qmgr_message.o: ../../include/mail_proto.h
 qmgr_message.o: ../../include/iostuff.h
 qmgr_message.o: ../../include/attr.h
 qmgr_message.o: ../../include/qmgr_user.h
+qmgr_message.o: ../../include/split_addr.h
 qmgr_message.o: ../../include/rewrite_clnt.h
 qmgr_message.o: ../../include/resolve_clnt.h
 qmgr_message.o: qmgr.h
index 612625bcf1cd0ffde55dd1a42bf7e3578b089183..9765206361e0da0e3ae0069b38e8c34dc06855e9 100644 (file)
@@ -286,6 +286,7 @@ struct QMGR_MESSAGE {
     char   *sasl_method;               /* SASL method */
     char   *sasl_username;             /* SASL user name */
     char   *sasl_sender;               /* SASL sender */
+    char   *rewrite_context;           /* address qualification */
     QMGR_RCPT_LIST rcpt_list;          /* complete addresses */
     int     rcpt_count;                        /* used recipient slots */
     int     rcpt_limit;                        /* maximum read in-core */
index 3064e540ab3c5236b0fd170ac81dd9f66a21e233..9616735fcb18d165c66f1e1ae656105340ed1fbb 100644 (file)
@@ -167,8 +167,9 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
               ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
-              ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
+            ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
+          ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, message->rewrite_context,
               ATTR_TYPE_END);
     if (sender_buf != 0)
        vstring_free(sender_buf);
index 132a738a26266bc80019481363b1b3b2e9987282..52ddfcdb097651dbee4597e0a9103a757dec27fd 100644 (file)
 #include <verp_sender.h>
 #include <mail_proto.h>
 #include <qmgr_user.h>
+#include <split_addr.h>
 
 /* Client stubs. */
 
@@ -185,6 +186,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->sasl_method = 0;
     message->sasl_username = 0;
     message->sasl_sender = 0;
+    message->rewrite_context = 0;
     qmgr_rcpt_list_init(&message->rcpt_list);
     message->rcpt_count = 0;
     message->rcpt_limit = var_qmgr_msg_rcpt_limit;
@@ -584,6 +586,13 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    msg_warn("%s: ignoring multiple %s attribute: %s",
                        message->queue_id, MAIL_ATTR_SASL_SENDER, value);
            }
+           if (strcmp(name, MAIL_ATTR_RWR_CTXT_NAME) == 0) {
+               if (message->rewrite_context == 0)
+                   message->rewrite_context = mystrdup(value);
+               else
+                   msg_warn("%s: ignoring multiple %s attribute: %s",
+                       message->queue_id, MAIL_ATTR_RWR_CTXT_NAME, value);
+           }
            /* Optional tracing flags. */
            else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
                message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@@ -663,6 +672,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        message->sasl_username = mystrdup("");
     if (message->sasl_sender == 0)
        message->sasl_sender = mystrdup("");
+    if (message->rewrite_context == 0)
+       message->rewrite_context = mystrdup("");
 
     /*
      * Clean up.
index bb061a966a1ff8d9ecec90feb319af4629a70925..25d631c884271e1109170ddbf5423e24b59e8bbb 100644 (file)
@@ -101,7 +101,7 @@ typedef struct SMTP_STATE {
 #define SMTP_FEATURE_XFORWARD_ADDR     (1<<8)
 #define SMTP_FEATURE_XFORWARD_PROTO    (1<<9)
 #define SMTP_FEATURE_XFORWARD_HELO     (1<<10)
-
+#define SMTP_FEATURE_XFORWARD_DOMAIN   (1<<11)
 #define SMTP_FEATURE_BEST_MX           (1<<12) /* for next-hop or fall-back */
 #define SMTP_FEATURE_RSET_REJECTED     (1<<13) /* RSET probe rejected */
 #define SMTP_FEATURE_FROM_CACHE                (1<<14) /* cached session */
index a56c9aa85ddfe3dccc2fc00986bd9bd250ecf410..4e13a1432eb5cfe2a9a1420f2257a7daa84d6568 100644 (file)
@@ -223,6 +223,7 @@ int     smtp_helo(SMTP_STATE *state, int misc_flags)
        XFORWARD_ADDR, SMTP_FEATURE_XFORWARD_ADDR,
        XFORWARD_PROTO, SMTP_FEATURE_XFORWARD_PROTO,
        XFORWARD_HELO, SMTP_FEATURE_XFORWARD_HELO,
+       XFORWARD_DOMAIN, SMTP_FEATURE_XFORWARD_DOMAIN,
        0, 0,
     };
     SOCKOPT_SIZE optlen;
@@ -639,6 +640,12 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
                vstring_sprintf_append(next_command, " %s=%s",
                   XFORWARD_HELO, DEL_REQ_ATTR_AVAIL(request->client_helo) ?
                               request->client_helo : XFORWARD_UNAVAILABLE);
+           if (session->features & SMTP_FEATURE_XFORWARD_DOMAIN)
+               vstring_sprintf_append(next_command, " %s=%s", XFORWARD_DOMAIN,
+                        DEL_REQ_ATTR_AVAIL(request->rewrite_context) == 0 ?
+                                      XFORWARD_UNAVAILABLE :
+                          strcmp(request->rewrite_context, REWRITE_LOCAL) ?
+                                 XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE);
            next_state = SMTP_STATE_MAIL;
            break;
 
index 254f39e2147b65affef82c4dd6f1d2448f0f5ff8..d29e4c49fc5d0d5eb8bba2bcfbd2673f04ec939c 100644 (file)
@@ -210,7 +210,7 @@ smtpd_check.o: ../../include/match_ops.h
 smtpd_check.o: ../../include/namadr_list.h
 smtpd_check.o: ../../include/domain_list.h
 smtpd_check.o: ../../include/mail_params.h
-smtpd_check.o: ../../include/canon_addr.h
+smtpd_check.o: ../../include/rewrite_clnt.h
 smtpd_check.o: ../../include/resolve_clnt.h
 smtpd_check.o: ../../include/mail_error.h
 smtpd_check.o: ../../include/name_mask.h
index 8ade47c83f662c85c51d91850ea4508c3ca54530..041e65512f21ce81e20370a8ea5b51e502f9347e 100644 (file)
 /*     access restriction is specified.
 /* .IP "\fBsmtpd_sasl_exceptions_networks (empty)\fR"
 /*     What SMTP clients Postfix will not offer AUTH support to.
+/* ADDRESS REWRITING CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBreceive_override_options (empty)\fR"
+/*     Enable or disable recipient validation, built-in content
+/*     filtering, or address mapping.
+/* .PP
+/*     Available in Postfix version 2.2 and later:
+/* .IP "\fBlocal_header_rewrite_context_clients ($inet_interfaces $mynetworks)\fR"
+/*     Append the domain names in $myorigin and $mydomain to incomplete
+/*     message header addresses from these clients.
+/* .IP "\fBremote_header_rewrite_context_name (local)\fR"
+/*     The address rewriting context that should be used for incomplete
+/*     mail header addresses from remote clients.
+/* .PP
+/*     Implemented by the trivial-rewrite(8) server:
+/* .IP "\fBinvalid_header_rewrite_context_domain (domain.invalid)\fR"
+/*     Append this domain to incomplete message header addresses from
+/*     remote clients, when $remote_header_rewrite_context_name is set to
+/*     "invalid".
 /* AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS
 /* .ad
 /* .fi
 /*     Available in Postfix version 2.1 and later:
 /* .IP "\fBreceive_override_options (empty)\fR"
 /*     Enable or disable recipient validation, built-in content
-/*     filtering, or address rewriting.
+/*     filtering, or address mapping.
 /* EXTERNAL CONTENT INSPECTION CONTROLS
 /* .ad
 /* .fi
@@ -775,6 +795,9 @@ char   *var_smtpd_hoggers;
 
 #endif
 
+char   *var_remote_rwr_name;
+char   *var_local_rwr_clients;
+
  /*
   * Silly little macros.
   */
@@ -794,13 +817,11 @@ static NAMADR_LIST *verp_clients;
   * its own access control.
   */
 static NAMADR_LIST *xclient_hosts;
-static int xclient_allowed;
 
  /*
   * XFORWARD command. Access control is cached.
   */
 static NAMADR_LIST *xforward_hosts;
-static int xforward_allowed;
 
  /*
   * Client connection and rate limiting.
@@ -966,14 +987,15 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     if (namadr_list_match(verp_clients, state->name, state->addr))
        smtpd_chat_reply(state, "250-%s", VERP_CMD);
     /* XCLIENT must not override its own access control. */
-    if (xclient_allowed)
+    if (state->xclient_allowed)
        smtpd_chat_reply(state, "250-" XCLIENT_CMD
                         " " XCLIENT_NAME " " XCLIENT_ADDR
                         " " XCLIENT_PROTO " " XCLIENT_HELO);
-    if (xforward_allowed)
+    if (state->xforward_allowed)
        smtpd_chat_reply(state, "250-" XFORWARD_CMD
                         " " XFORWARD_NAME " " XFORWARD_ADDR
-                        " " XFORWARD_PROTO " " XFORWARD_HELO);
+                        " " XFORWARD_PROTO " " XFORWARD_HELO
+                        " " XFORWARD_DOMAIN);
     smtpd_chat_reply(state, "250 8BITMIME");
     return (0);
 }
@@ -1051,6 +1073,8 @@ static void mail_open_stream(SMTPD_STATE *state)
        rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld", (long) state->time);
        if (*var_filter_xport)
            rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
+       rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                   MAIL_ATTR_RWR_CTXT_NAME, state->rewrite_context_name);
     }
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable) {
@@ -1253,7 +1277,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      */
 #ifdef SNAPSHOT
     if (SMTPD_STAND_ALONE(state) == 0
-       && !xclient_allowed
+       && !state->xclient_allowed
        && anvil_clnt
        && var_smtpd_cmail_limit > 0
        && !namadr_list_match(hogger_list, state->name, state->addr)
@@ -1463,7 +1487,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      */
 #ifdef SNAPSHOT
     if (SMTPD_STAND_ALONE(state) == 0
-       && !xclient_allowed
+       && !state->xclient_allowed
        && anvil_clnt
        && var_smtpd_crcpt_limit > 0
        && !namadr_list_match(hogger_list, state->name, state->addr)
@@ -1514,6 +1538,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      * we have a valid recipient address.
      */
     if (state->proxy == 0 && state->cleanup == 0) {
+       smtpd_check_rewrite(state);
        if (state->proxy_mail) {
            if (smtpd_proxy_open(state, var_smtpd_proxy_filt,
                                 var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
@@ -2080,7 +2105,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
                         XCLIENT_CMD);
        return (-1);
     }
-    if (!xclient_allowed) {
+    if (!state->xclient_allowed) {
        state->error_mask |= MAIL_ERROR_POLICY;
        smtpd_chat_reply(state, "554 Error: insufficient authorization");
        return (-1);
@@ -2217,9 +2242,20 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        XFORWARD_ADDR, SMTPD_STATE_XFORWARD_ADDR,
        XFORWARD_PROTO, SMTPD_STATE_XFORWARD_PROTO,
        XFORWARD_HELO, SMTPD_STATE_XFORWARD_HELO,
+       XFORWARD_DOMAIN, SMTPD_STATE_XFORWARD_DOMAIN,
        0, 0,
     };
+    static char *context_name[] = {
+       REWRITE_LOCAL,                  /* Postfix internal form */
+       0,                              /* filled in on the fly */
+    };
+    static NAME_CODE xforward_to_context[] = {
+       XFORWARD_DOM_LOCAL, 0,          /* XFORWARD representation */
+       XFORWARD_DOM_REMOTE, 1,         /* XFORWARD representation */
+       0, -1,
+    };
     int     flag;
+    int     context_code;
 
     /*
      * Sanity checks.
@@ -2235,7 +2271,7 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
                         XFORWARD_CMD);
        return (-1);
     }
-    if (!xforward_allowed) {
+    if (!state->xforward_allowed) {
        state->error_mask |= MAIL_ERROR_POLICY;
        smtpd_chat_reply(state, "554 Error: insufficient authorization");
        return (-1);
@@ -2332,6 +2368,28 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            UPDATE_STR(state->xforward.protocol, attr_value);
            break;
 
+           /*
+            * DOMAIN=local or remote.
+            */
+       case SMTPD_STATE_XFORWARD_DOMAIN:
+           context_name[1] = var_remote_rwr_name;
+           if ((context_code = name_code(xforward_to_context,
+                                         NAME_CODE_FLAG_NONE,
+                                         attr_value)) < 0) {
+               state->error_mask |= MAIL_ERROR_PROTOCOL;
+               smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                XFORWARD_DOMAIN, attr_value);
+               return (-1);
+           }
+           if (state->rewrite_context_name
+               && strcmp(state->rewrite_context_name,
+                         context_name[context_code])) {
+               myfree(state->rewrite_context_name);
+               state->rewrite_context_name =
+                   mystrdup(context_name[context_code]);
+           }
+           break;
+
            /*
             * Unknown attribute name. Complain.
             */
@@ -2490,7 +2548,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
         */
 #ifdef SNAPSHOT
        if (SMTPD_STAND_ALONE(state) == 0
-           && !xclient_allowed
+           && !state->xclient_allowed
            && anvil_clnt
            && !namadr_list_match(hogger_list, state->name, state->addr)
            && anvil_clnt_connect(anvil_clnt, service, state->addr,
@@ -2591,7 +2649,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
      */
 #ifdef SNAPSHOT
     if (SMTPD_STAND_ALONE(state) == 0
-       && !xclient_allowed
+       && !state->xclient_allowed
        && anvil_clnt
        && !namadr_list_match(hogger_list, state->name, state->addr))
        anvil_clnt_disconnect(anvil_clnt, service, state->addr);
@@ -2650,15 +2708,21 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
     /*
      * XCLIENT must not override its own access control.
      */
-    xclient_allowed =
+    state.xclient_allowed =
        namadr_list_match(xclient_hosts, state.name, state.addr);
 
     /*
      * Overriding XFORWARD access control makes no sense, either.
      */
-    xforward_allowed =
+    state.xforward_allowed =
        namadr_list_match(xforward_hosts, state.name, state.addr);
 
+    /*
+     * Choose a default address rewriting context. This should be made more
+     * configurable.
+     */
+    smtpd_check_rewrite(&state);
+
     /*
      * See if we need to turn on verbose logging for this client.
      */
@@ -2733,13 +2797,19 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
 
 static void post_jail_init(char *unused_name, char **unused_argv)
 {
+    NAME_CODE rewrite_context_names[] = {
+       REWRITE_LOCAL, 1,
+       REWRITE_INVALID, 1,
+       REWRITE_NONE, 1,
+       0, 0,
+    };
 
     /*
      * Initialize the receive transparency options: do we want unknown
      * recipient checks, address mapping, header_body_checks?.
      */
     smtpd_input_transp_mask =
-    input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
+       input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
 
     /*
      * Sanity checks. The queue_minfree value should be at least as large as
@@ -2761,6 +2831,14 @@ static void post_jail_init(char *unused_name, char **unused_argv)
        || var_smtpd_cmail_limit || var_smtpd_crcpt_limit)
        anvil_clnt = anvil_clnt_create();
 #endif
+
+    /*
+     * Sanity check.
+     */
+    if (name_code(rewrite_context_names, NAME_CODE_FLAG_STRICT_CASE,
+                 var_remote_rwr_name) == 0)
+       msg_fatal("parameter %s: invalid value: %s",
+                 VAR_REM_RWR_NAME, var_remote_rwr_name);
 }
 
 /* main - the main program */
@@ -2863,6 +2941,8 @@ int     main(int argc, char **argv)
 #ifdef SNAPSHOT
        VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0,
 #endif
+       VAR_REM_RWR_NAME, DEF_REM_RWR_NAME, &var_remote_rwr_name, 1, 0,
+       VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 1, 0,
        0,
     };
     static CONFIG_RAW_TABLE raw_table[] = {
index ffe0c9c7030fb5d0d80efd2ebefbe3c788b754b4..54ae936d4c6b481e34dbb8f8d5cc4009066eb6e0 100644 (file)
@@ -87,6 +87,9 @@ typedef struct SMTPD_STATE {
     off_t   msg_size;                  /* MAIL FROM message size */
     int     junk_cmds;                 /* counter */
     int     rcpt_overshoot;            /* counter */
+    char   *rewrite_context_name;      /* address rewriting context */
+    int     xclient_allowed;           /* permission to use XCLIENT */
+    int     xforward_allowed;          /* permission to use XFORWARD */
 
     /*
      * SASL specific.
@@ -145,6 +148,7 @@ typedef struct SMTPD_STATE {
 #define SMTPD_STATE_XFORWARD_PROTO (1<<3)      /* protocol received */
 #define SMTPD_STATE_XFORWARD_HELO  (1<<4)      /* client helo received */
 #define SMTPD_STATE_XFORWARD_IDENT (1<<5)      /* message identifier */
+#define SMTPD_STATE_XFORWARD_DOMAIN (1<<6)     /* message identifier */
 
 #define SMTPD_STATE_XFORWARD_CLIENT_MASK \
        (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR \
index 3bc8534901f0879257db2e8a1a24c234b6ef6efb..bcd65f1663192b78e0d19096b84a62a175f3086d 100644 (file)
@@ -12,6 +12,9 @@
 /*     int     smtpd_check_addr(address)
 /*     const char *address;
 /*
+/*     char    *smtpd_check_rewrite(state)
+/*     SMTPD_STATE *state;
+/*
 /*     char    *smtpd_check_client(state)
 /*     SMTPD_STATE *state;
 /*
 /*     smtpd_check_addr() sanity checks an email address and returns
 /*     non-zero in case of badness.
 /*
+/*     smtpd_check_rewrite() shuod be called before opening a queue
+/*     file or proxy connection, in order to establish the proper
+/*     header address rewriting context.
+/*
 /*     Each of the following routines scrutinizes the argument passed to
 /*     an SMTP command such as HELO, MAIL FROM, RCPT TO, or scrutinizes
 /*     the initial client connection request.  The administrator can
 #include <namadr_list.h>
 #include <domain_list.h>
 #include <mail_params.h>
-#include <canon_addr.h>
+#include <rewrite_clnt.h>
 #include <resolve_clnt.h>
 #include <mail_error.h>
 #include <resolve_local.h>
@@ -269,6 +276,7 @@ static MAPS *smtpd_sender_login_maps;
 static DOMAIN_LIST *relay_domains;
 static NAMADR_LIST *mynetworks;
 static NAMADR_LIST *perm_mx_networks;
+static NAMADR_LIST *local_rewrite_clients;
 
  /*
   * How to do parent domain wildcard matching, if any.
@@ -415,7 +423,7 @@ static void *resolve_pagein(const char *addr, void *unused_context)
     /*
      * Resolve the address.
      */
-    canon_addr_internal(query, addr);
+    rewrite_clnt_internal(REWRITE_LOCAL, addr, query);
     resolve_clnt_query(STR(query), reply);
     lowercase(STR(reply->recipient));
 
@@ -563,6 +571,8 @@ void    smtpd_check_init(void)
     perm_mx_networks =
        namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
                         var_perm_mx_networks);
+    local_rewrite_clients =
+       namadr_list_init(MATCH_FLAG_NONE, var_local_rwr_clients);
 
     /*
      * Pre-parse and pre-open the recipient maps.
@@ -1646,8 +1656,8 @@ static int not_in_client_helo(SMTPD_STATE *state, const char *table,
      * Thus, if delay_reject=no, client and helo actions such as FILTER or
      * HOLD also should not affect subsequent mail deliveries. Hmm...
      * 
-     * XXX If the MAIL FROM command is rejected then we have to reset access
-     * map side effects such as FILTER.
+     * XXX If the MAIL FROM command is rejected then we have to reset access map
+     * side effects such as FILTER.
      */
     if (state->sender == 0) {
        msg_warn("access table %s: with %s=%s, "
@@ -2240,8 +2250,8 @@ static int check_mail_access(SMTPD_STATE *state, const char *table,
        reject_dict_retry(state, addr);
 
     /*
-     * Garbage in, garbage out. Every address from canon_addr_internal() and
-     * from resolve_clnt_query() must be fully qualified.
+     * Garbage in, garbage out. Every address from rewrite_clnt_internal()
+     * and from resolve_clnt_query() must be fully qualified.
      */
     if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) {
        msg_warn("%s: no @domain in address: %s", myname,
@@ -3356,6 +3366,33 @@ int     smtpd_check_addr(const char *addr)
     return (0);
 }
 
+/* smtpd_check_rewrite - choose address qualification context */
+
+void    smtpd_check_rewrite(SMTPD_STATE *state)
+{
+
+    /*
+     * This should be made more configurable.
+     */
+#define SASL_AUTHENTICATED     1
+#define NOT_SASL_AUTHENTICATED 0
+
+    /*
+     * XXX We want to be able to use !pattern to make exceptions, but then we
+     * should not confuse matters by mixing names with addresses.
+     */
+    if (SMTPD_STAND_ALONE(state)
+       || namadr_list_match(local_rewrite_clients, " ", state->addr)
+#ifdef USE_SASL_AUTH
+       || permit_sasl_auth(state, SASL_AUTHENTICATED,
+                           NOT_SASL_AUTHENTICATED)
+#endif
+       )
+       state->rewrite_context_name = mystrdup(REWRITE_LOCAL);
+    else
+       state->rewrite_context_name = mystrdup(var_remote_rwr_name);
+}
+
 /* smtpd_check_client - validate client name or address */
 
 char   *smtpd_check_client(SMTPD_STATE *state)
@@ -3532,7 +3569,9 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
     if (*recipient) {
        if (canon_verify_sender == 0) {
            canon_verify_sender = vstring_alloc(10);
-           canon_addr_internal(canon_verify_sender, var_verify_sender);
+           rewrite_clnt_internal(REWRITE_LOCAL,
+                                 var_verify_sender,
+                                 canon_verify_sender);
        }
        if (strcasecmp(STR(canon_verify_sender), recipient) == 0)
            return (0);
@@ -3875,7 +3914,7 @@ char   *smtpd_check_size(SMTPD_STATE *state, off_t size)
 char   *smtpd_check_data(SMTPD_STATE *state)
 {
     int     status;
-    char *NOCLOBBER saved_recipient;
+    char   *NOCLOBBER saved_recipient;
 
     /*
      * Minor kluge so that we can delegate work to the generic routine. We
@@ -3979,6 +4018,8 @@ char   *var_def_rbl_reply;
 char   *var_relay_rcpt_maps;
 char   *var_verify_sender;
 char   *var_smtpd_sasl_opts;
+char   *var_remote_rwr_name;
+char   *var_local_rwr_clients;
 
 typedef struct {
     char   *name;
@@ -4019,6 +4060,8 @@ static STRING_TABLE string_table[] = {
     VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender,
     VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name,
     VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts,
+    VAR_REM_RWR_NAME, DEF_REM_RWR_NAME, &var_remote_rwr_name,
+    VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients,
     0,
 };
 
@@ -4243,12 +4286,13 @@ int     verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
     return (VRFY_STAT_OK);
 }
 
-/* canon_addr_internal - stub */
+/* rewrite_clnt_internal - stub */
 
-VSTRING *canon_addr_internal(VSTRING *result, const char *addr)
+VSTRING *rewrite_clnt_internal(const char *context, const char *addr,
+                                      VSTRING *result)
 {
     if (addr == STR(result))
-       msg_panic("canon_addr_internal: result clobbers input");
+       msg_panic("rewrite_clnt_internal: result clobbers input");
     if (*addr && strchr(addr, '@') == 0)
        msg_fatal("%s: address rewriting is disabled", addr);
     vstring_strcpy(result, addr);
index 101673f16bef9d18a2dbfd8455c9a031ad08e916..8d706bb9a9a60d20113d3e09e19371cfec151336 100644 (file)
@@ -14,6 +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_client(SMTPD_STATE *);
 extern char *smtpd_check_helo(SMTPD_STATE *, char *);
 extern char *smtpd_check_mail(SMTPD_STATE *, char *);
index cc06db98e67ba674ab31ec78fbe75630db1b29c1..282743b92477f42ceea9489aa164a11233e8fb79 100644 (file)
 #define SMTPD_PROXY_XFORWARD_PROTO (1<<2)      /* protocol */
 #define SMTPD_PROXY_XFORWARD_HELO  (1<<3)      /* client helo */
 #define SMTPD_PROXY_XFORWARD_IDENT (1<<4)      /* message identifier */
+#define SMTPD_PROXY_XFORWARD_DOMAIN (1<<5)     /* origin type */
 
  /*
   * SLMs.
 #define STR(x) vstring_str(x)
 #define LEN(x) VSTRING_LEN(x)
 #define SMTPD_PROXY_CONNECT ((char *) 0)
+#define STREQ(x, y)    (strcmp((x), (y)) == 0)
 
 /* smtpd_xforward_flush - flush forwarding information */
 
@@ -243,6 +245,7 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
        XFORWARD_ADDR, SMTPD_PROXY_XFORWARD_ADDR,
        XFORWARD_PROTO, SMTPD_PROXY_XFORWARD_PROTO,
        XFORWARD_HELO, SMTPD_PROXY_XFORWARD_HELO,
+       XFORWARD_DOMAIN, SMTPD_PROXY_XFORWARD_DOMAIN,
        0, 0,
     };
 
@@ -318,22 +321,26 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     if (state->proxy_xforward_features) {
        buf = vstring_alloc(100);
        bad = 0;
-       if ((state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_NAME)
-           && !(bad = smtpd_xforward(state, buf, XFORWARD_NAME,
+       if ((!(state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_NAME)
+            || !(bad = smtpd_xforward(state, buf, XFORWARD_NAME,
                                  IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state)),
-                                     FORWARD_NAME(state)))
-           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_ADDR)
-           && !(bad = smtpd_xforward(state, buf, XFORWARD_ADDR,
+                                      FORWARD_NAME(state))))
+           && (!(state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_ADDR)
+               || !(bad = smtpd_xforward(state, buf, XFORWARD_ADDR,
                                  IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)),
-                                     FORWARD_ADDR(state)))
-           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_HELO)
-           && !(bad = smtpd_xforward(state, buf, XFORWARD_HELO,
+                                         FORWARD_ADDR(state))))
+           && (!(state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_HELO)
+               || !(bad = smtpd_xforward(state, buf, XFORWARD_HELO,
                                  IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state)),
-                                     FORWARD_HELO(state)))
-           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_PROTO)
-           && !(bad = smtpd_xforward(state, buf, XFORWARD_PROTO,
+                                         FORWARD_HELO(state))))
+         && (!(state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_PROTO)
+             || !(bad = smtpd_xforward(state, buf, XFORWARD_PROTO,
                                IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state)),
-                                     FORWARD_PROTO(state))))
+                                       FORWARD_PROTO(state))))
+        && (!(state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_DOMAIN)
+            || !(bad = smtpd_xforward(state, buf, XFORWARD_DOMAIN, 1,
+                        STREQ(state->rewrite_context_name, REWRITE_LOCAL) ?
+                               XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE))))
            bad = smtpd_xforward_flush(state, buf);
        vstring_free(buf);
        if (bad) {
index 5989df75ea879c6bb6fcf9855d3081242e1657ed..f8d8e1e20510cfb4faf934cb081839c3bfe769fc 100644 (file)
@@ -114,6 +114,9 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->saved_flags = 0;
     state->instance = vstring_alloc(10);
     state->seqno = 0;
+    state->rewrite_context_name = 0;
+    state->xclient_allowed = 0;
+    state->xforward_allowed = 0;
 
 #ifdef USE_SASL_AUTH
     if (SMTPD_STAND_ALONE(state))
@@ -170,6 +173,8 @@ void    smtpd_state_reset(SMTPD_STATE *state)
        vstring_free(state->proxy_buffer);
     if (state->instance)
        vstring_free(state->instance);
+    if (state->rewrite_context_name)
+       myfree(state->rewrite_context_name);
 
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable)
index 0b734b3481465ab93e379199e24ff62ce2d43db3..ecfa05cf75aae95d2abc508fc5263a338a901b32 100644 (file)
@@ -146,7 +146,6 @@ trivial-rewrite.o: ../../include/attr.h
 trivial-rewrite.o: ../../include/resolve_local.h
 trivial-rewrite.o: ../../include/mail_conf.h
 trivial-rewrite.o: ../../include/resolve_clnt.h
-trivial-rewrite.o: ../../include/rewrite_clnt.h
 trivial-rewrite.o: ../../include/tok822.h
 trivial-rewrite.o: ../../include/mail_addr.h
 trivial-rewrite.o: ../../include/mail_server.h
index 56ac4f5f6f59298540bdf44bb960ce8c338d1aec..924b51e6a037b002b52c36edb703d997079611dc 100644 (file)
@@ -279,7 +279,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *addr,
        if (tok822_rfind_type(tree->tail, '@')
            || (var_swap_bangpath && tok822_rfind_type(tree->tail, '!'))
            || (var_percent_hack && tok822_rfind_type(tree->tail, '%'))) {
-           rewrite_tree(REWRITE_CANON, tree);
+           rewrite_tree(&local_context, tree);
            continue;
        }
 
@@ -306,7 +306,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *addr,
            }
            tok822_free(tree->head);
            tree->head = tok822_scan(STR(addr_buf), &tree->tail);
-           rewrite_tree(REWRITE_CANON, tree);
+           rewrite_tree(&local_context, tree);
            continue;
        }
 
index 8bd6e8409a8a0e5c60bb9e4a144ddbef4fa88ef4..a0eca67bfb7092e7b73488e39a80d0919a59f2e3 100644 (file)
 /*     void    rewrite_proto(stream)
 /*     VSTREAM *stream;
 /*
-/*     void    rewrite_addr(rule, addr, result)
-/*     char    *rule;
+/*     void    rewrite_addr(context, addr, result)
+/*     RWR_CONTEXT *context;
 /*     char    *addr;
 /*     VSTRING *result;
 /*
-/*     void    rewrite_tree(rule, tree)
-/*     char    *rule;
+/*     void    rewrite_tree(context, tree)
+/*     RWR_CONTEXT *context;
 /*     TOK822  *tree;
+/*
+/*     RWR_CONTEXT local_context;
+/*     RWR_CONTEXT inval_context;
 /* DESCRIPTION
 /*     This module implements the trivial address rewriting engine.
 /*
@@ -35,6 +38,9 @@
 /*
 /*     rewrite_tree() rewrites a parse tree with a single address to
 /*     another tree.  A tree is a dummy node on top of a token list.
+/*
+/*     local_context and inval_context provide domain names for
+/*     completing incomplete address forms.
 /* STANDARDS
 /* DIAGNOSTICS
 /*     Problems and transactions are logged to the syslog daemon.
 
 #include "trivial-rewrite.h"
 
+RWR_CONTEXT local_context = {
+    VAR_MYORIGIN, &var_myorigin,
+    VAR_MYDOMAIN, &var_mydomain,
+};
+
+RWR_CONTEXT inval_context = {
+    VAR_INV_RWR_DOMAIN, &var_inv_rwr_domain,
+    VAR_INV_RWR_DOMAIN, &var_inv_rwr_domain,
+};
+
 static VSTRING *ruleset;
 static VSTRING *address;
 static VSTRING *result;
 
 /* rewrite_tree - rewrite address according to rule set */
 
-void    rewrite_tree(char *unused_ruleset, TOK822 *tree)
+void    rewrite_tree(RWR_CONTEXT *context, TOK822 *tree)
 {
     TOK822 *colon;
     TOK822 *domain;
@@ -159,7 +175,8 @@ void    rewrite_tree(char *unused_ruleset, TOK822 *tree)
         */
        else if (var_append_at_myorigin != 0) {
            domain = tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
-           tok822_sub_append(tree, tok822_scan(var_myorigin, (TOK822 **) 0));
+           tok822_sub_append(tree, tok822_scan(REW_PARAM_VALUE(context->origin),
+                                               (TOK822 **) 0));
        }
     }
 
@@ -174,7 +191,8 @@ void    rewrite_tree(char *unused_ruleset, TOK822 *tree)
        && tok822_find_type(domain, TOK822_DOMLIT) == 0
        && tok822_find_type(domain, '.') == 0) {
        tok822_sub_append(tree, tok822_alloc('.', (char *) 0));
-       tok822_sub_append(tree, tok822_scan(var_mydomain, (TOK822 **) 0));
+       tok822_sub_append(tree, tok822_scan(REW_PARAM_VALUE(context->domain),
+                                           (TOK822 **) 0));
     }
 
     /*
@@ -191,7 +209,7 @@ void    rewrite_tree(char *unused_ruleset, TOK822 *tree)
 
 /* rewrite_addr - rewrite address according to rule set */
 
-void    rewrite_addr(char *ruleset, char *addr, VSTRING *result)
+void    rewrite_addr(RWR_CONTEXT *context, char *addr, VSTRING *result)
 {
     TOK822 *tree;
 
@@ -199,7 +217,7 @@ void    rewrite_addr(char *ruleset, char *addr, VSTRING *result)
      * Sanity check. An address is supposed to be in externalized form.
      */
     if (*addr == 0) {
-       msg_warn("rewrite_addr: null address, ruleset \"%s\"", ruleset);
+       msg_warn("rewrite_addr: null address");
        vstring_strcpy(result, addr);
        return;
     }
@@ -209,7 +227,7 @@ void    rewrite_addr(char *ruleset, char *addr, VSTRING *result)
      * rewrite it, and convert back.
      */
     tree = tok822_scan_addr(addr);
-    rewrite_tree(ruleset, tree);
+    rewrite_tree(context, tree);
     tok822_externalize(result, tree, TOK822_STR_DEFL);
     tok822_free_tree(tree);
 }
@@ -218,13 +236,32 @@ void    rewrite_addr(char *ruleset, char *addr, VSTRING *result)
 
 int     rewrite_proto(VSTREAM *stream)
 {
+    RWR_CONTEXT *context;
+
     if (attr_scan(stream, ATTR_FLAG_STRICT,
                  ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset,
                  ATTR_TYPE_STR, MAIL_ATTR_ADDR, address,
                  ATTR_TYPE_END) != 2)
        return (-1);
 
-    rewrite_addr(vstring_str(ruleset), vstring_str(address), result);
+    /*
+     * Note: an unqualified username is for all practical purposes equivalent
+     * to a fully qualified local address, if only because a reply to an
+     * unqualified address will be sent to a local recipient. Having to
+     * support both forms is error prone, therefore an unqualified address is
+     * rewritten in the local domain context when no address rewriting
+     * context is given.
+     */
+    if (strcmp(vstring_str(ruleset), REWRITE_LOCAL) == 0
+       || strcmp(vstring_str(ruleset), REWRITE_NONE) == 0)
+       context = &local_context;
+    else if (strcmp(vstring_str(ruleset), REWRITE_INVALID) == 0)
+       context = &inval_context;
+    else {
+       msg_warn("unknown context: %s", vstring_str(ruleset));
+       return (-1);
+    }
+    rewrite_addr(context, vstring_str(address), result);
 
     if (msg_verbose)
        msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset),
index 5d0728702487b2fc1640f741cbf453a49f22ae6a..cdc1ebb7f943081711b8d8be98db6af2ccde1549 100644 (file)
@@ -8,15 +8,29 @@
 /* DESCRIPTION
 /*     The \fBtrivial-rewrite\fR daemon processes three types of client
 /*     service requests:
-/* .IP \fBrewrite\fR
-/*     Rewrite an address to standard form. The \fBtrivial-rewrite\fR
-/*     daemon by default appends local domain information to unqualified
-/*     addresses, swaps bang paths to domain form, and strips source
-/*     routing information. This process is under control of several
-/*     configuration parameters (see below).
-/* .IP \fBresolve\fR
+/* .IP "\fBrewrite \fIcontext address\fR"
+/*     Rewrite an address to standard form, according to the 
+/*     address rewriting context:
+/* .RS
+/* .IP \fBlocal\fR
+/* .IP \fBnone\fR
+/*     Append the domain names specified with \fB$myorigin\fR or
+/*     \fB$mydomain\fR to incomplete addresses; do \fBswap_bangpath\fR
+/*     and \fBallow_percent_hack\fR processing as described below, and
+/*     strip source routed addresses (\fI@site,@site:user@domain\fR)
+/*     to \fIuser@domain\fR form.
+/* .IP \fBinvalid\fR
+/*     Append the domain name specified with
+/*     \fB$invalid_header_rewrite_context_domain\fR to incomplete
+/*     addresses. Otherwise the result is identical to that of
+/*     the \fBlocal\fR address rewriting context. This prevents
+/*      Postfix from appending the local domain to spam from poorly
+/*     written remote clients.
+/* .RE
+/* .IP "\fBresolve \fIaddress\fR"
 /*     Resolve an address to a (\fItransport\fR, \fInexthop\fR,
-/*     \fIrecipient\fR) triple. The meaning of the results is as follows:
+/*      \fIrecipient\fR, \fIflags\fR) quadruple. The meaning of
+/*     the results is as follows:
 /* .RS
 /* .IP \fItransport\fR
 /*     The delivery agent to use. This is the first field of an entry
 /*     The host to send to and optional delivery method information.
 /* .IP \fIrecipient\fR
 /*     The envelope recipient address that is passed on to \fInexthop\fR.
+/* .IP \fIflags\fR
+/*     The address class, whether the address requires relaying, 
+/*     whether the address has problems, and whether the request failed.
 /* .RE
-/* .IP \fBverify\fR
+/* .IP "\fBverify \fIaddress\fR"
 /*     Resolve an address for address verification purposes.
 /* SERVER PROCESS MANAGEMENT
 /* .ad
 /* .IP "\fBallow_percent_hack (yes)\fR"
 /*     Enable the rewriting of the form "user%domain" to "user@domain".
 /* .IP "\fBappend_at_myorigin (yes)\fR"
-/*     Append the string "@$myorigin" to mail addresses without domain
-/*     information.
+/*     With locally submitted mail, append the string "@$myorigin" to mail
+/*     addresses without domain information.
 /* .IP "\fBappend_dot_mydomain (yes)\fR"
-/*     Append the string ".$mydomain" to addresses that have no ".domain"
-/*     information.
+/*     With locally submitted mail, append the string ".$mydomain" to
+/*     addresses that have no ".domain" information.
 /* .IP "\fBrecipient_delimiter (empty)\fR"
 /*     The separator between user names and address extensions (user+foo).
 /* .IP "\fBswap_bangpath (yes)\fR"
 /*     Enable the rewriting of "site!user" into "user@site".
+/* .PP
+/*     Available in Postfix 2.2 and later:
+/* .IP "\fBinvalid_header_rewrite_context_domain (domain.invalid)\fR"
+/*     Append this domain to incomplete message header addresses from
+/*     remote clients, when $remote_header_rewrite_context_name is set to
+/*     "invalid".
+/* .PP
+/*     Implemented by the smtpd(8) server:
+/* .IP "\fBremote_header_rewrite_context_name (local)\fR"
+/*     The address rewriting context that should be used for incomplete
+/*     mail header addresses from remote clients.
 /* ROUTING CONTROLS
 /* .ad
 /* .fi
@@ -273,6 +301,7 @@ char   *var_def_transport;
 char   *var_empty_addr;
 int     var_show_unk_rcpt_table;
 int     var_resolve_nulldom;
+char   *var_inv_rwr_domain;
 
  /*
   * Shadow personality for address verification.
@@ -400,6 +429,7 @@ int     main(int argc, char **argv)
        VAR_VRFY_RELAY_XPORT, DEF_VRFY_RELAY_XPORT, &var_vrfy_relay_xport, 1, 0,
        VAR_VRFY_DEF_XPORT, DEF_VRFY_DEF_XPORT, &var_vrfy_def_xport, 1, 0,
        VAR_VRFY_RELAYHOST, DEF_VRFY_RELAYHOST, &var_vrfy_relayhost, 0, 0,
+       VAR_INV_RWR_DOMAIN, DEF_INV_RWR_DOMAIN, &var_inv_rwr_domain, 1, 0,
        0,
     };
     static CONFIG_BOOL_TABLE bool_table[] = {
index c3816ab400dc98ad47ab7415d1194bfbe1987566..ce59970a9a273ef8037f0009e5a1aa7c6de65e7d 100644 (file)
  /*
   * rewrite.c
   */
+typedef struct {
+    const char *origin_name;           /* name of variable */
+    char  **origin;                    /* default origin */
+    const char *domain_name;           /* name of variable */
+    char  **domain;                    /* default domain */
+} RWR_CONTEXT;
+
+#define REW_PARAM_VALUE(x) (*(x))      /* make it easy to do it right */
+
 extern void rewrite_init(void);
 extern int rewrite_proto(VSTREAM *);
-extern void rewrite_addr(char *, char *, VSTRING *);
-extern void rewrite_tree(char *, TOK822 *);
+extern void rewrite_addr(RWR_CONTEXT *, char *, VSTRING *);
+extern void rewrite_tree(RWR_CONTEXT *, TOK822 *);
+extern RWR_CONTEXT local_context;
+extern RWR_CONTEXT inval_context;
 
  /*
   * resolve.c
@@ -61,4 +72,3 @@ extern int resolve_proto(RES_CONTEXT *, VSTREAM *);
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
 /*--*/
-
index 91ed1ba722b7ad9fe54cf8e616d85185bee2c57a..21170ea26a4a21c9071edfec50295864afdb3d07 100644 (file)
@@ -693,10 +693,11 @@ dict_nisplus.o: dict_nisplus.c
 dict_nisplus.o: sys_defs.h
 dict_nisplus.o: msg.h
 dict_nisplus.o: mymalloc.h
-dict_nisplus.o: htable.h
+dict_nisplus.o: vstring.h
+dict_nisplus.o: vbuf.h
+dict_nisplus.o: stringops.h
 dict_nisplus.o: dict.h
 dict_nisplus.o: vstream.h
-dict_nisplus.o: vbuf.h
 dict_nisplus.o: argv.h
 dict_nisplus.o: dict_nisplus.h
 dict_open.o: dict_open.c
index eabf015374f95be7f377d5f6356466bbc3d2a244..6dd2307132c58d272603b58dbf624efc58ce7de1 100644 (file)
@@ -225,7 +225,7 @@ int     attr_clnt_request(ATTR_CLNT *client, int send_flags,...)
                        SKIP_ARG(ap, long);
                        break;
                    case ATTR_TYPE_HASH:
-                       SKIP_ARG(ap, HTABLE *);
+                       (void) va_arg(ap, HTABLE *);
                        break;
                    default:
                        msg_panic("%s: unexpected attribute type %d",
index e6f3467d8afb83601164b2effad140708bca9790..7ac00214971167b6e089838c3e33fbc9cf9b0b8f 100644 (file)
@@ -6,8 +6,8 @@
 /* SYNOPSIS
 /*     #include <dict_nisplus.h>
 /*
-/*     DICT    *dict_nisplus_open(map, dummy, dict_flags)
-/*     char    *map;
+/*     DICT    *dict_nisplus_open(map, open_flags, dict_flags)
+/*     const char *map;
 /*     int     dummy;
 /*     int     dict_flags;
 /* DESCRIPTION
 /*     The \fIdummy\fR argument is not used.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
+/* DIAGNOSTICS
+/*     Fatal errors:
 /* LICENSE
 /* .ad
 /* .fi
 /*     The Secure Mailer license must be distributed with this software.
 /* AUTHOR(S)
+/*     Geoff Gibbs
+/*     UK-HGMP-RC
+/*     Hinxton
+/*     Cambridge
+/*     CB10 1SB, UK
+/*
+/*     based on the code for dict_nis.c et al by :-
+/*
 /*     Wietse Venema
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 
 /* System library. */
 
-#include "sys_defs.h"
+#include <sys_defs.h>
 #include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#ifdef HAS_NISPLUS
+#include <rpcsvc/nis.h>                        /* for nis_list */
+#endif
 
 /* Utility library. */
 
-#include "msg.h"
-#include "mymalloc.h"
-#include "htable.h"
-#include "dict.h"
-#include "dict_nisplus.h"
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <stringops.h>
+#include <dict.h>
+#include <dict_nisplus.h>
+
+#ifdef HAS_NISPLUS
 
 /* Application-specific. */
 
 typedef struct {
     DICT    dict;                      /* generic members */
+    char   *template;                  /* parsed query template */
+    int     column;                    /* NIS+ field number (start at 1) */
 } DICT_NISPLUS;
 
+ /*
+  * Begin quote from nis+(1):
+  * 
+  * The following text represents a  context-free  grammar  that defines  the
+  * set of legal  NIS+ names. The terminals in this grammar are the
+  * characters `.' (dot),  `['  (open  bracket), `]'  (close  bracket),  `,'
+  * (comma),  `=' (equals) and whitespace. Angle brackets (`<' and `>'),
+  * which delineate  non- terminals,  are  not  part of the grammar. The
+  * character `|' (vertical bar) is used to separate alternate productions
+  * and should be read as ``this production OR this production''.
+  * 
+  * name                ::=    . | <simple name> | <indexed name>
+  * 
+  * simple name         ::=    <string>. | <string>.<simple name>
+  * 
+  * indexed name        ::=    <search criterion>,<simple name>
+  * 
+  * search criterion    ::=    [ <attribute list> ]
+  * 
+  * attribute list      ::=    <attribute> |  <attribute>,<attribute list>
+  * 
+  * attribute           ::=    <string> = <string>
+  * 
+  * string              ::=    ISO Latin 1 character set except  the character
+  * '/'  (slash).  The initial character may not be a terminal character or
+  * the characters '@' (at), '+' (plus), or (`-') hyphen.
+  * 
+  * Terminals that appear in strings must be  quoted   with  `"' (double quote).
+  * The `"' character may be quoted by quoting it with itself `""'.
+  * 
+  * End quote fron nis+(1).
+  * 
+  * This NIS client always quotes the entire query string (the value part of
+  * [attribute=value],file.domain.) so the issue with initial characters
+  * should not be applicable. One wonders what restrictions are applicable
+  * when a string is quoted, but the manual doesn't specify what can appear
+  * between quotes, and we don't want to get burned.
+  */
+
+ /*
+  * SLMs.
+  */
+#define STR(x) vstring_str(x)
+
+/* dict_nisplus_lookup - find table entry */
+
+static const char *dict_nisplus_lookup(DICT *dict, const char *key)
+{
+    const char *myname = "dict_nisplus_lookup";
+    DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict;
+    static VSTRING *quoted_key;
+    static VSTRING *query;
+    static VSTRING *reply;
+    nis_result *nis_alias;
+    int     count;
+    const char *cp;
+    int     ch;
+
+    /*
+     * Initialize.
+     */
+    dict_errno = 0;
+    if (quoted_key == 0) {
+       query = vstring_alloc(100);
+       reply = vstring_alloc(100);
+       quoted_key = vstring_alloc(100);
+    }
+
+    /*
+     * Check that the lookup key does not contain characters disallowed by
+     * nis+(1).
+     * 
+     * XXX Many client implementations don't seem to care about disallowed
+     * characters.
+     */
+    VSTRING_RESET(quoted_key);
+    VSTRING_ADDCH(quoted_key, '"');
+    for (cp = key; (ch = *(unsigned const char *) cp) != 0; cp++) {
+       if ((ISASCII(ch) && !ISPRINT(ch)) || (ch > 126 && ch < 160)) {
+           msg_warn("map %s:%s: lookup key with non-printing character 0x%x:"
+                    " ignoring this request",
+                    dict->type, dict->name, ch);
+           return (0);
+       } else if (ch == '"') {
+           VSTRING_ADDCH(quoted_key, '"');
+       }
+       VSTRING_ADDCH(quoted_key, ch);
+    }
+    VSTRING_ADDCH(quoted_key, '"');
+    VSTRING_TERMINATE(quoted_key);
+
+    /*
+     * Plug the key into the query template, which typically looks something
+     * like the following: [alias=%s],mail_aliases.org_dir.my.nisplus.domain.
+     * 
+     * XXX The nis+ documentation defines a length limit for simple names like
+     * a.b.c., but defines no length limit for (the components of) indexed
+     * names such as [x=y],a.b.c. Our query length is limited because Postfix
+     * addresses (in envelopes or in headers) have a finite length.
+     */
+    vstring_sprintf(query, dict_nisplus->template, STR(quoted_key));
+    nis_alias = nis_list(STR(query), FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+
+    /*
+     * When lookup succeeds, the result may be unusable because it is
+     * ambiguous.
+     */
+    if (nis_alias->status == NIS_SUCCESS) {
+       if ((count = NIS_RES_NUMOBJ(nis_alias)) != 1) {
+           msg_warn("ambiguous match (%d results) for %s in NIS+ map %s:"
+                    " ignoring this request",
+                    count, key, dict_nisplus->dict.name);
+           nis_freeresult(nis_alias);
+           return (0);
+       } else {
+           vstring_strcpy(reply,
+                          NIS_RES_OBJECT(nis_alias)->zo_data.objdata_u
+                          .en_data.en_cols.en_cols_val[dict_nisplus->column]
+                          .ec_value.ec_value_val);
+           if (msg_verbose)
+               msg_info("%s: %s, column %d -> %s", myname, STR(query),
+                        dict_nisplus->column, STR(reply));
+           nis_freeresult(nis_alias);
+           return (STR(reply));
+       }
+    }
+
+    /*
+     * When the NIS+ lookup fails for reasons other than "key not found",
+     * keep logging warnings, and hope that someone will eventually notice
+     * the problem and fix it.
+     */
+    else {
+       if (nis_alias->status != NIS_NOTFOUND
+           && nis_alias->status != NIS_PARTIAL) {
+           msg_warn("lookup %s, NIS+ map %s: %s",
+                    key, dict_nisplus->dict.name,
+                    nis_sperrno(nis_alias->status));
+           dict_errno = DICT_ERR_RETRY;
+       }
+       nis_freeresult(nis_alias);
+       return (0);
+    }
+}
+
 /* dict_nisplus_close - close NISPLUS map */
 
 static void dict_nisplus_close(DICT *dict)
 {
     DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict;
 
-    myfree((char *) dict_nisplus);
+    myfree(dict_nisplus->template);
+    dict_free(dict);
 }
 
 /* dict_nisplus_open - open NISPLUS map */
 
-DICT   *dict_nisplus_open(const char *map, int unused_flags, int dict_flags)
+DICT   *dict_nisplus_open(const char *map, int open_flags, int dict_flags)
 {
+    const char *myname = "dict_nisplus_open";
     DICT_NISPLUS *dict_nisplus;
+    char   *col_field;
+
+    /*
+     * Sanity check.
+     */
+    if (open_flags != O_RDONLY)
+       msg_fatal("%s:%s map requires O_RDONLY access mode",
+                 DICT_TYPE_NISPLUS, map);
 
-    dict_nisplus = (DICT_NISPLUS *) dict_alloc(DICT_TYPE_NISPLUS, map,
-                                              sizeof(*dict_nisplus));
+    /*
+     * Initialize. This is a read-only map with fixed strings, not with
+     * regular expressions.
+     */
+    dict_nisplus = (DICT_NISPLUS *)
+       dict_alloc(DICT_TYPE_NISPLUS, map, sizeof(*dict_nisplus));
+    dict_nisplus->dict.lookup = dict_nisplus_lookup;
     dict_nisplus->dict.close = dict_nisplus_close;
     dict_nisplus->dict.flags = dict_flags | DICT_FLAG_FIXED;
-    return (DICT_DEBUG(&dict_nisplus->dict));
+
+    /*
+     * Convert the query template into an indexed name and column number. The
+     * query template looks like:
+     * 
+     * [attribute=%s;attribute=value...];simple.name.:column
+     * 
+     * One instance of %s gets to be replaced by a version of the lookup key;
+     * other attributes must specify fixed values. The reason for using ';'
+     * is that the comma character is special in main.cf. When no column
+     * number is given at the end of the map name, we use a default column.
+     */
+    dict_nisplus->template = mystrdup(map);
+    translit(dict_nisplus->template, ";", ",");
+    if ((col_field = strstr(dict_nisplus->template, ".:")) != 0) {
+       col_field[1] = 0;
+       col_field += 2;
+       if (!alldig(col_field) || (dict_nisplus->column = atoi(col_field)) < 1)
+           msg_fatal("bad column field in NIS+ map name: %s", map);
+    } else {
+       dict_nisplus->column = 1;
+    }
+    if (msg_verbose)
+       msg_info("%s: opened NIS+ table %s for column %d",
+                myname, dict_nisplus->template, dict_nisplus->column);
+    return (DICT_DEBUG (&dict_nisplus->dict));
 }
+
+#endif
index 0ed7a7558517df71eafccc0b4dcf791a984b1d2f..14e206a571f8b6443a75862d98c7073dffcb9ce1 100644 (file)
@@ -60,7 +60,7 @@
 
 /* name_mask - compute mask corresponding to list of names */
 
-int     name_mask(const char *context, NAME_MASK * table, const char *names)
+int     name_mask(const char *context, NAME_MASK *table, const char *names)
 {
     char   *myname = "name_mask";
     char   *saved_names = mystrdup(names);
@@ -92,7 +92,7 @@ int     name_mask(const char *context, NAME_MASK * table, const char *names)
 
 /* str_name_mask - mask to string */
 
-const char *str_name_mask(const char *context, NAME_MASK * table, int mask)
+const char *str_name_mask(const char *context, NAME_MASK *table, int mask)
 {
     char   *myname = "name_mask";
     NAME_MASK *np;