Postfix 2.1.3 fixes the following problems:

- Missing patch for variadic argument list reuse.

- With a non-default route for address verification probes, normal
mail could be sent over the probe route and vice versa.

- The SMTP server didn't neuter whitespace in HELO commands, so that
it could mess up XFORWARD commands.

- Some cosmetic documentation fixes.

Prereq: "2.1.2"
diff -cr /tmp/postfix-2.1.2/src/global/mail_version.h ./src/global/mail_version.h
*** /tmp/postfix-2.1.2/src/global/mail_version.h	Mon Jun 14 17:43:33 2004
--- ./src/global/mail_version.h	Wed Jun 16 14:19:03 2004
***************
*** 20,27 ****
    * Patches change the patchlevel and the release date. Snapshots change the
    * release date only.
    */
! #define MAIL_RELEASE_DATE	"20040615"
! #define MAIL_VERSION_NUMBER	"2.1.2"
  
  #define VAR_MAIL_VERSION	"mail_version"
  #ifdef SNAPSHOT
--- 20,27 ----
    * Patches change the patchlevel and the release date. Snapshots change the
    * release date only.
    */
! #define MAIL_RELEASE_DATE	"20040616"
! #define MAIL_VERSION_NUMBER	"2.1.3"
  
  #define VAR_MAIL_VERSION	"mail_version"
  #ifdef SNAPSHOT
diff -cr /tmp/postfix-2.1.2/HISTORY ./HISTORY
*** /tmp/postfix-2.1.2/HISTORY	Mon Jun 14 17:47:38 2004
--- ./HISTORY	Wed Jun 16 16:22:04 2004
***************
*** 9373,9375 ****
--- 9373,9391 ----
  	John Heasley. File: util/sys_defs.h.
  
  	Documentation: typo fixes by IKEDA Nozomu.
+ 
+ 20040616
+ 
+ 	Bugfix: one missed variadic argument list fix. Victor
+ 	Duchovni, Morgan Stanley. File: global/verify.c.
+ 
+ 	Bugfix: the resolver client cache should be context dependent
+ 	because address verification probes may use a different
+ 	route than normal mail deliveries. File: global/resolve_clnt.c.
+ 
+ 	Safety: added similar context dependence to the address
+ 	rewriting client in order to avoid trouble when Postfix is
+ 	changed. File: global/rewrite_clnt.c.
+ 
+ 	Bugfix: space in HELO commands could end up in XFORWARD
+ 	commands.  File: smtpd/smtpd.c.
diff -cr /tmp/postfix-2.1.2/README_FILES/BASIC_CONFIGURATION_README ./README_FILES/BASIC_CONFIGURATION_README
*** /tmp/postfix-2.1.2/README_FILES/BASIC_CONFIGURATION_README	Thu Apr 15 16:54:47 2004
--- ./README_FILES/BASIC_CONFIGURATION_README	Wed Jun 16 14:25:41 2004
***************
*** 116,123 ****
  the parent domain of the machine name.
  
  For the sake of consistency between sender and recipient addresses, myorigin
! also specifies the default domain name that is appended to an unqualified
! recipient address.
  
  Examples (specify only one of the following):
  
--- 116,123 ----
  the parent domain of the machine name.
  
  For the sake of consistency between sender and recipient addresses, myorigin
! also specifies the domain name that is appended to an unqualified recipient
! address.
  
  Examples (specify only one of the following):
  
diff -cr /tmp/postfix-2.1.2/html/BASIC_CONFIGURATION_README.html ./html/BASIC_CONFIGURATION_README.html
*** /tmp/postfix-2.1.2/html/BASIC_CONFIGURATION_README.html	Thu Apr 15 16:54:46 2004
--- ./html/BASIC_CONFIGURATION_README.html	Wed Jun 16 14:25:36 2004
***************
*** 187,193 ****
  domain of the machine name. </p>
  
  <p> For the sake of consistency between sender and recipient addresses,
! <a href="postconf.5.html#myorigin">myorigin</a> also specifies the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> name that is appended
  to an unqualified recipient address. </p>
  
  <p> Examples (specify only one of the following): </p>
--- 187,193 ----
  domain of the machine name. </p>
  
  <p> For the sake of consistency between sender and recipient addresses,
! <a href="postconf.5.html#myorigin">myorigin</a> also specifies the domain name that is appended
  to an unqualified recipient address. </p>
  
  <p> Examples (specify only one of the following): </p>
diff -cr /tmp/postfix-2.1.2/html/postconf.5.html ./html/postconf.5.html
*** /tmp/postfix-2.1.2/html/postconf.5.html	Mon Jun 14 17:18:53 2004
--- ./html/postconf.5.html	Wed Jun 16 18:40:35 2004
***************
*** 3335,3341 ****
  </p>
  
  <p>
! By default, address masquerading is limited to envelope recipient
  addresses, and to header sender and header recipient addresses.
  This allows you to use address masquerading on a mail gateway while
  still being able to forward mail to users on individual machines.
--- 3335,3341 ----
  </p>
  
  <p>
! By default, address masquerading is limited to envelope sender
  addresses, and to header sender and header recipient addresses.
  This allows you to use address masquerading on a mail gateway while
  still being able to forward mail to users on individual machines.
***************
*** 3773,3779 ****
  (default: $<a href="postconf.5.html#myhostname">myhostname</a>)</b></DT><DD>
  
  <p>
! The <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to. The default,
  $<a href="postconf.5.html#myhostname">myhostname</a>, is adequate for small sites.  If you run a domain with
  multiple machines, you should (1) change this to $<a href="postconf.5.html#mydomain">mydomain</a> and (2)
--- 3773,3779 ----
  (default: $<a href="postconf.5.html#myhostname">myhostname</a>)</b></DT><DD>
  
  <p>
! The domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to. The default,
  $<a href="postconf.5.html#myhostname">myhostname</a>, is adequate for small sites.  If you run a domain with
  multiple machines, you should (1) change this to $<a href="postconf.5.html#mydomain">mydomain</a> and (2)
diff -cr /tmp/postfix-2.1.2/html/smtpd.8.html ./html/smtpd.8.html
*** /tmp/postfix-2.1.2/html/smtpd.8.html	Mon Jun 14 17:38:32 2004
--- ./html/smtpd.8.html	Wed Jun 16 18:40:37 2004
***************
*** 708,716 ****
                privileges than "strangers".
  
         <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
!               The  default  domain  name that locally-posted mail
!               appears to come from, and that locally posted  mail
!               is delivered to.
  
         <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
                The  process ID of a Postfix command or daemon pro-
--- 708,716 ----
                privileges than "strangers".
  
         <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-
!               ered to.
  
         <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
                The  process ID of a Postfix command or daemon pro-
diff -cr /tmp/postfix-2.1.2/man/man5/postconf.5 ./man/man5/postconf.5
*** /tmp/postfix-2.1.2/man/man5/postconf.5	Mon Jun 14 17:18:53 2004
--- ./man/man5/postconf.5	Wed Jun 16 18:40:35 2004
***************
*** 1670,1676 ****
  .SH masquerade_classes (default: envelope_sender, header_sender, header_recipient)
  What addresses are subject to address masquerading.
  .PP
! By default, address masquerading is limited to envelope recipient
  addresses, and to header sender and header recipient addresses.
  This allows you to use address masquerading on a mail gateway while
  still being able to forward mail to users on individual machines.
--- 1670,1676 ----
  .SH masquerade_classes (default: envelope_sender, header_sender, header_recipient)
  What addresses are subject to address masquerading.
  .PP
! By default, address masquerading is limited to envelope sender
  addresses, and to header sender and header recipient addresses.
  This allows you to use address masquerading on a mail gateway while
  still being able to forward mail to users on individual machines.
***************
*** 1929,1935 ****
  an explicit mynetworks list by hand, as described with the mynetworks
  configuration parameter.
  .SH myorigin (default: $myhostname)
! The default domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to. The default,
  $myhostname, is adequate for small sites.  If you run a domain with
  multiple machines, you should (1) change this to $mydomain and (2)
--- 1929,1935 ----
  an explicit mynetworks list by hand, as described with the mynetworks
  configuration parameter.
  .SH myorigin (default: $myhostname)
! The domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to. The default,
  $myhostname, is adequate for small sites.  If you run a domain with
  multiple machines, you should (1) change this to $mydomain and (2)
diff -cr /tmp/postfix-2.1.2/man/man8/smtpd.8 ./man/man8/smtpd.8
*** /tmp/postfix-2.1.2/man/man8/smtpd.8	Mon Jun 14 17:38:30 2004
--- ./man/man8/smtpd.8	Wed Jun 16 18:40:36 2004
***************
*** 580,586 ****
  The list of "trusted" SMTP clients that have more privileges than
  "strangers".
  .IP "\fBmyorigin ($myhostname)\fR"
! The default domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to.
  .IP "\fBprocess_id (read-only)\fR"
  The process ID of a Postfix command or daemon process.
--- 580,586 ----
  The list of "trusted" SMTP clients that have more privileges than
  "strangers".
  .IP "\fBmyorigin ($myhostname)\fR"
! The domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to.
  .IP "\fBprocess_id (read-only)\fR"
  The process ID of a Postfix command or daemon process.
diff -cr /tmp/postfix-2.1.2/proto/BASIC_CONFIGURATION_README.html ./proto/BASIC_CONFIGURATION_README.html
*** /tmp/postfix-2.1.2/proto/BASIC_CONFIGURATION_README.html	Thu Apr 15 16:49:13 2004
--- ./proto/BASIC_CONFIGURATION_README.html	Wed Jun 16 14:24:02 2004
***************
*** 187,193 ****
  domain of the machine name. </p>
  
  <p> For the sake of consistency between sender and recipient addresses,
! myorigin also specifies the default domain name that is appended
  to an unqualified recipient address. </p>
  
  <p> Examples (specify only one of the following): </p>
--- 187,193 ----
  domain of the machine name. </p>
  
  <p> For the sake of consistency between sender and recipient addresses,
! myorigin also specifies the domain name that is appended
  to an unqualified recipient address. </p>
  
  <p> Examples (specify only one of the following): </p>
diff -cr /tmp/postfix-2.1.2/proto/postconf.proto ./proto/postconf.proto
*** /tmp/postfix-2.1.2/proto/postconf.proto	Mon Jun 14 17:17:40 2004
--- ./proto/postconf.proto	Wed Jun 16 18:40:26 2004
***************
*** 2064,2070 ****
  </p>
  
  <p>
! By default, address masquerading is limited to envelope recipient
  addresses, and to header sender and header recipient addresses.
  This allows you to use address masquerading on a mail gateway while
  still being able to forward mail to users on individual machines.
--- 2064,2070 ----
  </p>
  
  <p>
! By default, address masquerading is limited to envelope sender
  addresses, and to header sender and header recipient addresses.
  This allows you to use address masquerading on a mail gateway while
  still being able to forward mail to users on individual machines.
***************
*** 2370,2376 ****
  %PARAM myorigin $myhostname
  
  <p>
! The default domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to. The default,
  $myhostname, is adequate for small sites.  If you run a domain with
  multiple machines, you should (1) change this to $mydomain and (2)
--- 2370,2376 ----
  %PARAM myorigin $myhostname
  
  <p>
! The domain name that locally-posted mail appears to come
  from, and that locally posted mail is delivered to. The default,
  $myhostname, is adequate for small sites.  If you run a domain with
  multiple machines, you should (1) change this to $mydomain and (2)
diff -cr /tmp/postfix-2.1.2/src/global/mynetworks.c ./src/global/mynetworks.c
*** /tmp/postfix-2.1.2/src/global/mynetworks.c	Sat Feb 24 20:46:07 2001
--- ./src/global/mynetworks.c	Wed Jun 16 14:01:14 2004
***************
*** 91,96 ****
--- 91,107 ----
  	mask_style = name_mask("mynetworks mask style", mask_styles,
  			       var_mynetworks_style);
  
+ 	/*
+ 	 * XXX Workaround: name_mask() needs a flags argument so that we can
+ 	 * require exactly one value, or we need to provide an API that is
+ 	 * dedicated for single-valued flags.
+ 	 */
+ 	for (i = 0, junk = mask_style; junk != 0; junk >>= 1)
+ 	    i += (junk & 1);
+ 	if (i != 1)
+ 	    msg_fatal("bad %s value: %s; specify exactly one value",
+ 		      VAR_MYNETWORKS_STYLE, var_mynetworks_style);
+ 
  	result = vstring_alloc(20);
  	my_addr_list = own_inet_addr_list();
  	my_mask_list = own_inet_mask_list();
diff -cr /tmp/postfix-2.1.2/src/global/resolve_clnt.c ./src/global/resolve_clnt.c
*** /tmp/postfix-2.1.2/src/global/resolve_clnt.c	Fri Mar 26 13:39:41 2004
--- ./src/global/resolve_clnt.c	Wed Jun 16 12:33:01 2004
***************
*** 127,132 ****
--- 127,133 ----
    */
  extern CLNT_STREAM *rewrite_clnt_stream;
  
+ static VSTRING *last_class;
  static VSTRING *last_addr;
  static RESOLVE_REPLY last_reply;
  
***************
*** 151,156 ****
--- 152,158 ----
       * One-entry cache.
       */
      if (last_addr == 0) {
+ 	last_class = vstring_alloc(10);
  	last_addr = vstring_alloc(100);
  	resolve_clnt_init(&last_reply);
      }
***************
*** 169,175 ****
       */
  #define IFSET(flag, text) ((reply->flags & (flag)) ? (text) : "")
  
!     if (*addr && strcmp(addr, STR(last_addr)) == 0) {
  	vstring_strcpy(reply->transport, STR(last_reply.transport));
  	vstring_strcpy(reply->nexthop, STR(last_reply.nexthop));
  	vstring_strcpy(reply->recipient, STR(last_reply.recipient));
--- 171,178 ----
       */
  #define IFSET(flag, text) ((reply->flags & (flag)) ? (text) : "")
  
!     if (*addr && strcmp(addr, STR(last_addr)) == 0
! 	&& strcmp(class, STR(last_class)) == 0) {
  	vstring_strcpy(reply->transport, STR(last_reply.transport));
  	vstring_strcpy(reply->nexthop, STR(last_reply.nexthop));
  	vstring_strcpy(reply->recipient, STR(last_reply.recipient));
***************
*** 246,251 ****
--- 249,255 ----
      /*
       * Update the cache.
       */
+     vstring_strcpy(last_class, class);
      vstring_strcpy(last_addr, addr);
      vstring_strcpy(last_reply.transport, STR(reply->transport));
      vstring_strcpy(last_reply.nexthop, STR(reply->nexthop));
diff -cr /tmp/postfix-2.1.2/src/global/rewrite_clnt.c ./src/global/rewrite_clnt.c
*** /tmp/postfix-2.1.2/src/global/rewrite_clnt.c	Fri Mar 26 14:02:38 2004
--- ./src/global/rewrite_clnt.c	Wed Jun 16 12:35:16 2004
***************
*** 72,77 ****
--- 72,78 ----
    */
  CLNT_STREAM *rewrite_clnt_stream = 0;
  
+ static VSTRING *last_rule;
  static VSTRING *last_addr;
  static VSTRING *last_result;
  
***************
*** 85,90 ****
--- 86,92 ----
       * One-entry cache.
       */
      if (last_addr == 0) {
+ 	last_rule = vstring_alloc(10);
  	last_addr = vstring_alloc(100);
  	last_result = vstring_alloc(100);
      }
***************
*** 102,111 ****
  
      /*
       * Peek at the cache.
-      * 
-      * XXX Must be made "rule" specific.
       */
!     if (strcmp(addr, STR(last_addr)) == 0) {
  	vstring_strcpy(result, STR(last_result));
  	if (msg_verbose)
  	    msg_info("rewrite_clnt: cached: %s: %s -> %s",
--- 104,112 ----
  
      /*
       * Peek at the cache.
       */
!     if (strcmp(addr, STR(last_addr)) == 0
! 	&& strcmp(rule, STR(last_rule)) == 0) {
  	vstring_strcpy(result, STR(last_result));
  	if (msg_verbose)
  	    msg_info("rewrite_clnt: cached: %s: %s -> %s",
***************
*** 152,157 ****
--- 153,159 ----
      /*
       * Update the cache.
       */
+     vstring_strcpy(last_rule, rule);
      vstring_strcpy(last_addr, addr);
      vstring_strcpy(last_result, STR(result));
  
diff -cr /tmp/postfix-2.1.2/src/global/verify.c ./src/global/verify.c
*** /tmp/postfix-2.1.2/src/global/verify.c	Mon Jun 14 13:20:02 2004
--- ./src/global/verify.c	Wed Jun 16 07:37:12 2004
***************
*** 142,148 ****
       */
      vstring_vsprintf(text, fmt, ap);
      if (var_verify_neg_cache || rcpt_stat == DEL_RCPT_STAT_OK) {
! 	req_stat = verify_clnt_vupdate(orig_rcpt, rcpt_stat, fmt, ap);
  	if (req_stat == VRFY_STAT_OK && strcasecmp(recipient, orig_rcpt) != 0)
  	    req_stat = verify_clnt_update(recipient, rcpt_stat,
  					  "%s", vstring_str(text));
--- 142,149 ----
       */
      vstring_vsprintf(text, fmt, ap);
      if (var_verify_neg_cache || rcpt_stat == DEL_RCPT_STAT_OK) {
! 	req_stat = verify_clnt_update(orig_rcpt, rcpt_stat,
! 				      "%s", vstring_str(text));
  	if (req_stat == VRFY_STAT_OK && strcasecmp(recipient, orig_rcpt) != 0)
  	    req_stat = verify_clnt_update(recipient, rcpt_stat,
  					  "%s", vstring_str(text));
diff -cr /tmp/postfix-2.1.2/src/smtpd/smtpd.c ./src/smtpd/smtpd.c
*** /tmp/postfix-2.1.2/src/smtpd/smtpd.c	Mon Jun 14 17:38:17 2004
--- ./src/smtpd/smtpd.c	Wed Jun 16 18:40:36 2004
***************
*** 534,540 ****
  /*	The list of "trusted" SMTP clients that have more privileges than
  /*	"strangers".
  /* .IP "\fBmyorigin ($myhostname)\fR"
! /*	The default domain name that locally-posted mail appears to come
  /*	from, and that locally posted mail is delivered to.
  /* .IP "\fBprocess_id (read-only)\fR"
  /*	The process ID of a Postfix command or daemon process.
--- 534,540 ----
  /*	The list of "trusted" SMTP clients that have more privileges than
  /*	"strangers".
  /* .IP "\fBmyorigin ($myhostname)\fR"
! /*	The domain name that locally-posted mail appears to come
  /*	from, and that locally posted mail is delivered to.
  /* .IP "\fBprocess_id (read-only)\fR"
  /*	The process ID of a Postfix command or daemon process.
***************
*** 811,816 ****
--- 811,821 ----
  static void rcpt_reset(SMTPD_STATE *);
  static void chat_reset(SMTPD_STATE *, int);
  
+  /*
+   * This filter is applied after printable().
+   */
+ #define NEUTER_CHARACTERS " <>()\\\";:@"
+ 
  #ifdef USE_SASL_AUTH
  
   /*
***************
*** 882,888 ****
      mail_reset(state);
      rcpt_reset(state);
      state->helo_name = mystrdup(printable(argv[1].strval, '?'));
!     neuter(state->helo_name, "<>()\\\";:@", '?');
      /* Downgrading the protocol name breaks the unauthorized pipelining test. */
      if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0
  	&& strcasecmp(state->protocol, MAIL_PROTO_SMTP) != 0) {
--- 887,893 ----
      mail_reset(state);
      rcpt_reset(state);
      state->helo_name = mystrdup(printable(argv[1].strval, '?'));
!     neuter(state->helo_name, NEUTER_CHARACTERS, '?');
      /* Downgrading the protocol name breaks the unauthorized pipelining test. */
      if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0
  	&& strcasecmp(state->protocol, MAIL_PROTO_SMTP) != 0) {
***************
*** 923,929 ****
      mail_reset(state);
      rcpt_reset(state);
      state->helo_name = mystrdup(printable(argv[1].strval, '?'));
!     neuter(state->helo_name, "<>()\\\";:@", '?');
      if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0) {
  	myfree(state->protocol);
  	state->protocol = mystrdup(MAIL_PROTO_ESMTP);
--- 928,934 ----
      mail_reset(state);
      rcpt_reset(state);
      state->helo_name = mystrdup(printable(argv[1].strval, '?'));
!     neuter(state->helo_name, NEUTER_CHARACTERS, '?');
      if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0) {
  	myfree(state->protocol);
  	state->protocol = mystrdup(MAIL_PROTO_ESMTP);
***************
*** 2012,2018 ****
  	    if (s) myfree(s); \
  	    s = (v) ? mystrdup(v) : 0; \
  	} while(0)
- #define NEUTER_CHARACTERS "<>()\\\";:@"
  
      /*
       * Iterate over all attribute=value elements.
--- 2017,2022 ----