Prereq: "2.3.13"
diff -cr /var/tmp/postfix-2.3.13/src/global/mail_version.h ./src/global/mail_version.h
*** /var/tmp/postfix-2.3.13/src/global/mail_version.h	Wed Oct 17 13:10:42 2007
--- ./src/global/mail_version.h	Thu Jan 31 21:00:45 2008
***************
*** 20,27 ****
    * Patches change both the patchlevel and the release date. Snapshots have no
    * patchlevel; they change the release date only.
    */
! #define MAIL_RELEASE_DATE	"20071017"
! #define MAIL_VERSION_NUMBER	"2.3.13"
  
  #ifdef SNAPSHOT
  # define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
--- 20,27 ----
    * Patches change both the patchlevel and the release date. Snapshots have no
    * patchlevel; they change the release date only.
    */
! #define MAIL_RELEASE_DATE	"20080131"
! #define MAIL_VERSION_NUMBER	"2.3.14"
  
  #ifdef SNAPSHOT
  # define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -cr /var/tmp/postfix-2.3.13/HISTORY ./HISTORY
*** /var/tmp/postfix-2.3.13/HISTORY	Wed Oct 17 12:28:56 2007
--- ./HISTORY	Thu Jan 10 20:17:13 2008
***************
*** 13088,13090 ****
--- 13088,13126 ----
  	rate of delivery attempts when the queue file system is
  	mounted with "noatime".  File: flush/flush.c. Back-port
  	from Postfix 2.4/2.5.
+ 
+ 20071030
+ 
+ 	Bugfix (introduced Postfix 2.3): Postfix mistakenly enforced
+ 	the 64kbyte limit (for sending body parts TO Milter
+ 	applications) also while receiving packets FROM Milter
+ 	applications.  The limit is now at least 1GB.  File:
+ 	milter/milter8.c.
+ 
+ 20071202
+ 
+ 	Bugfix (introduced Postfix 2.2): don't update the back-to-back
+ 	delivery time stamp while deferring mail. File: *qmgr/qmgr_entry.c.
+ 
+ 20071211
+ 
+ 	Bugfix (introduced 19980315): the "write" equivalent of
+ 	bugfix 20030104. File: util/vstream.c.
+ 
+ 20071213
+ 
+ 	Bugfix (introduced Postfix 2.3): the SMTP client never
+ 	marked corrupt files as corrupt. Victor Duchovni. File:
+ 	smtp/smtp_proto.c.
+ 
+ 20071229
+ 
+ 	Bugfix: the Milter client did not replace the Postfix-specific
+ 	form for unknown host names by the Sendmail-specific form.
+ 	File: milter/milter8.c.
+ 
+ 20080104
+ 
+ 	Workaround: minor change to the Dovecot AUTH request to
+ 	prevent dovecot-auth memory wastage. Timo Sirainen.  File:
+ 	xsasl/xsasl_dovecot_server.c.
diff -cr /var/tmp/postfix-2.3.13/src/milter/milter8.c ./src/milter/milter8.c
*** /var/tmp/postfix-2.3.13/src/milter/milter8.c	Tue Jul 31 15:38:33 2007
--- ./src/milter/milter8.c	Thu Jan 31 20:49:10 2008
***************
*** 63,68 ****
--- 63,69 ----
  #include <stdlib.h>
  #include <string.h>
  #include <stdarg.h>
+ #include <limits.h>			/* INT_MAX */
  
  #ifndef SHUT_RDWR
  #define SHUT_RDWR	2
***************
*** 280,286 ****
   /*
    * We don't accept insane amounts of data.
    */
! #define XXX_MAX_DATA	(MILTER_CHUNK_SIZE * 2)
  #define XXX_TIMEOUT	10
  
  #ifndef USE_LIBMILTER_INCLUDES
--- 281,287 ----
   /*
    * We don't accept insane amounts of data.
    */
! #define XXX_MAX_DATA	(INT_MAX / 2)
  #define XXX_TIMEOUT	10
  
  #ifndef USE_LIBMILTER_INCLUDES
***************
*** 1624,1629 ****
--- 1625,1641 ----
      const char *myname = "milter8_conn_event";
      MILTER8 *milter = (MILTER8 *) m;
      int     port;
+     const char *sm_name;
+     char   *ptr = 0;
+     const char *resp;
+ 
+     /*
+      * Need a global definition for "unknown" host name or address that is
+      * shared by smtpd, cleanup and libmilter.
+      */
+ #define XXX_UNKNOWN	"unknown"
+ #define STR_EQ(x,y)	(strcmp((x), (y)) == 0)
+ #define STR_NE(x,y)	(strcmp((x), (y)) != 0)
  
      /*
       * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
***************
*** 1655,1694 ****
  	    port = 0;
  	}
  	milter->state = MILTER8_STAT_ENVELOPE;
  	switch (addr_family) {
  	case AF_INET:
! 	    return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				  DONT_SKIP_REPLY, macros,
! 				  MILTER8_DATA_STRING, client_name,
! 				  MILTER8_DATA_OCTET, SMFIA_INET,
! 				  MILTER8_DATA_NSHORT, htons(port),
! 				  MILTER8_DATA_STRING, client_addr,
! 				  MILTER8_DATA_END));
  #ifdef HAS_IPV6
  	case AF_INET6:
! 	    return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				  DONT_SKIP_REPLY, macros,
! 				  MILTER8_DATA_STRING, client_name,
! 				  MILTER8_DATA_OCTET, SMFIA_INET6,
! 				  MILTER8_DATA_NSHORT, htons(port),
! 				  MILTER8_DATA_STRING, client_addr,
! 				  MILTER8_DATA_END));
  #endif
  	case AF_UNIX:
! 	    return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				  DONT_SKIP_REPLY, macros,
! 				  MILTER8_DATA_STRING, client_name,
! 				  MILTER8_DATA_OCTET, SMFIA_UNIX,
! 				  MILTER8_DATA_NSHORT, htons(0),
! 				  MILTER8_DATA_STRING, client_addr,
! 				  MILTER8_DATA_END));
  	default:
! 	    return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				  DONT_SKIP_REPLY, macros,
! 				  MILTER8_DATA_STRING, client_name,
! 				  MILTER8_DATA_OCTET, SMFIA_UNKNOWN,
! 				  MILTER8_DATA_END));
  	}
      default:
  	msg_panic("%s: milter %s: bad state %d",
  		  myname, milter->m.name, milter->state);
--- 1667,1717 ----
  	    port = 0;
  	}
  	milter->state = MILTER8_STAT_ENVELOPE;
+ 	/* Transform unknown hostname from Postfix to Sendmail form. */
+ 	sm_name = (STR_NE(client_name, XXX_UNKNOWN) ? client_name :
+ 		   STR_EQ(client_addr, XXX_UNKNOWN) ? client_name :
+ 		   (ptr = concatenate("[", client_addr, "]", (char *) 0)));
  	switch (addr_family) {
  	case AF_INET:
! 	    resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				 DONT_SKIP_REPLY, macros,
! 				 MILTER8_DATA_STRING, sm_name,
! 				 MILTER8_DATA_OCTET, SMFIA_INET,
! 				 MILTER8_DATA_NSHORT, htons(port),
! 				 MILTER8_DATA_STRING, client_addr,
! 				 MILTER8_DATA_END);
! 	    break;
  #ifdef HAS_IPV6
  	case AF_INET6:
! 	    resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				 DONT_SKIP_REPLY, macros,
! 				 MILTER8_DATA_STRING, sm_name,
! 				 MILTER8_DATA_OCTET, SMFIA_INET6,
! 				 MILTER8_DATA_NSHORT, htons(port),
! 				 MILTER8_DATA_STRING, client_addr,
! 				 MILTER8_DATA_END);
! 	    break;
  #endif
  	case AF_UNIX:
! 	    resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				 DONT_SKIP_REPLY, macros,
! 				 MILTER8_DATA_STRING, sm_name,
! 				 MILTER8_DATA_OCTET, SMFIA_UNIX,
! 				 MILTER8_DATA_NSHORT, htons(0),
! 				 MILTER8_DATA_STRING, client_addr,
! 				 MILTER8_DATA_END);
! 	    break;
  	default:
! 	    resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
! 				 DONT_SKIP_REPLY, macros,
! 				 MILTER8_DATA_STRING, sm_name,
! 				 MILTER8_DATA_OCTET, SMFIA_UNKNOWN,
! 				 MILTER8_DATA_END);
! 	    break;
  	}
+ 	if (ptr != 0)
+ 	    myfree(ptr);
+ 	return (resp);
      default:
  	msg_panic("%s: milter %s: bad state %d",
  		  myname, milter->m.name, milter->state);
diff -cr /var/tmp/postfix-2.3.13/src/oqmgr/qmgr_entry.c ./src/oqmgr/qmgr_entry.c
*** /var/tmp/postfix-2.3.13/src/oqmgr/qmgr_entry.c	Fri Dec  1 20:24:07 2006
--- ./src/oqmgr/qmgr_entry.c	Wed Dec 12 14:33:18 2007
***************
*** 203,209 ****
      /*
       * Maintain back-to-back delivery status.
       */
!     queue->last_done = event_time();
  
      /*
       * When the in-core queue for this site is empty and when this site is
--- 203,210 ----
      /*
       * Maintain back-to-back delivery status.
       */
!     if (which == QMGR_QUEUE_BUSY)
! 	queue->last_done = event_time();
  
      /*
       * When the in-core queue for this site is empty and when this site is
diff -cr /var/tmp/postfix-2.3.13/src/pipe/pipe.c ./src/pipe/pipe.c
*** /var/tmp/postfix-2.3.13/src/pipe/pipe.c	Mon Jun 26 08:59:19 2006
--- ./src/pipe/pipe.c	Thu Jan 10 09:49:27 2008
***************
*** 840,846 ****
  	/*
  	 * null_sender=string
  	 */
! 	else if (strncasecmp("null_sender=", *argv, sizeof("eol=") - 1) == 0) {
  	    vstring_strcpy(attr->null_sender, *argv + sizeof("null_sender=") - 1);
  	}
  
--- 840,846 ----
  	/*
  	 * null_sender=string
  	 */
! 	else if (strncasecmp("null_sender=", *argv, sizeof("null_sender=") - 1) == 0) {
  	    vstring_strcpy(attr->null_sender, *argv + sizeof("null_sender=") - 1);
  	}
  
diff -cr /var/tmp/postfix-2.3.13/src/qmgr/qmgr_entry.c ./src/qmgr/qmgr_entry.c
*** /var/tmp/postfix-2.3.13/src/qmgr/qmgr_entry.c	Mon Jun 26 08:59:19 2006
--- ./src/qmgr/qmgr_entry.c	Wed Dec 12 14:33:03 2007
***************
*** 276,282 ****
      /*
       * Maintain back-to-back delivery status.
       */
!     queue->last_done = event_time();
  
      /*
       * When the in-core queue for this site is empty and when this site is
--- 276,283 ----
      /*
       * Maintain back-to-back delivery status.
       */
!     if (which == QMGR_QUEUE_BUSY)
! 	queue->last_done = event_time();
  
      /*
       * When the in-core queue for this site is empty and when this site is
diff -cr /var/tmp/postfix-2.3.13/src/smtp/smtp_proto.c ./src/smtp/smtp_proto.c
*** /var/tmp/postfix-2.3.13/src/smtp/smtp_proto.c	Sun Feb 25 09:26:59 2007
--- ./src/smtp/smtp_proto.c	Thu Dec 13 15:03:16 2007
***************
*** 1710,1716 ****
  		fail_status = smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
  					     SMTP_RESP_FAKE(&fake, "5.3.0"),
  					     "unreadable mail queue entry");
! 		if (fail_status == 0)
  		    (void) mark_corrupt(state->src);
  		RETURN(fail_status);
  	    }
--- 1710,1716 ----
  		fail_status = smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
  					     SMTP_RESP_FAKE(&fake, "5.3.0"),
  					     "unreadable mail queue entry");
! 		if (state->status == 0)
  		    (void) mark_corrupt(state->src);
  		RETURN(fail_status);
  	    }
diff -cr /var/tmp/postfix-2.3.13/src/util/vstream.c ./src/util/vstream.c
*** /var/tmp/postfix-2.3.13/src/util/vstream.c	Wed Aug 23 16:27:28 2006
--- ./src/util/vstream.c	Thu Dec 13 18:20:22 2007
***************
*** 477,482 ****
--- 477,483 ----
  
  static void vstream_buf_alloc(VBUF *bp, ssize_t len)
  {
+     VSTREAM *stream = VBUF_TO_APPL(bp, VSTREAM, buf);
      ssize_t used = bp->ptr - bp->data;
      const char *myname = "vstream_buf_alloc";
  
***************
*** 492,501 ****
      bp->data = (unsigned char *)
  	(bp->data ? myrealloc((char *) bp->data, len) : mymalloc(len));
      bp->len = len;
!     if (bp->flags & VSTREAM_FLAG_READ)
  	bp->ptr = bp->data + used;
!     else
  	VSTREAM_BUF_AT_OFFSET(bp, used);
  }
  
  /* vstream_buf_wipe - reset buffer to initial state */
--- 493,507 ----
      bp->data = (unsigned char *)
  	(bp->data ? myrealloc((char *) bp->data, len) : mymalloc(len));
      bp->len = len;
!     if (bp->flags & VSTREAM_FLAG_READ) {
  	bp->ptr = bp->data + used;
! 	if (bp->flags & VSTREAM_FLAG_DOUBLE)
! 	    VSTREAM_SAVE_STATE(stream, read_buf, read_fd);
!     } else {
  	VSTREAM_BUF_AT_OFFSET(bp, used);
+ 	if (bp->flags & VSTREAM_FLAG_DOUBLE)
+ 	    VSTREAM_SAVE_STATE(stream, write_buf, write_fd);
+     }
  }
  
  /* vstream_buf_wipe - reset buffer to initial state */
***************
*** 663,673 ****
       * allocation gives the application a chance to override the default
       * buffering policy.
       */
!     if (bp->data == 0) {
  	vstream_buf_alloc(bp, VSTREAM_BUFSIZE);
- 	if (bp->flags & VSTREAM_FLAG_DOUBLE)
- 	    VSTREAM_SAVE_STATE(stream, read_buf, read_fd);
-     }
  
      /*
       * If the stream is double-buffered and the write buffer is not empty,
--- 669,676 ----
       * allocation gives the application a chance to override the default
       * buffering policy.
       */
!     if (bp->data == 0)
  	vstream_buf_alloc(bp, VSTREAM_BUFSIZE);
  
      /*
       * If the stream is double-buffered and the write buffer is not empty,
diff -cr /var/tmp/postfix-2.3.13/src/xsasl/xsasl_dovecot_server.c ./src/xsasl/xsasl_dovecot_server.c
*** /var/tmp/postfix-2.3.13/src/xsasl/xsasl_dovecot_server.c	Mon Jun 26 08:59:19 2006
--- ./src/xsasl/xsasl_dovecot_server.c	Fri Jan  4 11:29:22 2008
***************
*** 453,459 ****
  	/* send the request */
  	server->last_request_id = ++server->impl->request_id_counter;
  	vstream_fprintf(server->impl->sasl_stream,
! 			"AUTH\t%u\t%s\tservice=%s",
  			server->last_request_id, sasl_method,
  			server->service);
  	if (init_response) {
--- 453,459 ----
  	/* send the request */
  	server->last_request_id = ++server->impl->request_id_counter;
  	vstream_fprintf(server->impl->sasl_stream,
! 			"AUTH\t%u\t%s\tservice=%s\tnologin",
  			server->last_request_id, sasl_method,
  			server->service);
  	if (init_response) {