]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.4-20060721
authorWietse Venema <wietse@porcupine.org>
Fri, 21 Jul 2006 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:29 +0000 (06:32 +0000)
16 files changed:
postfix/HISTORY
postfix/Makefile.in
postfix/README_FILES/MILTER_README
postfix/README_FILES/RELEASE_NOTES [changed from file to symlink]
postfix/html/MILTER_README.html
postfix/implementation-notes/MILTER [new file with mode: 0644]
postfix/proto/MILTER_README.html
postfix/src/cleanup/cleanup.h
postfix/src/cleanup/cleanup_milter.c
postfix/src/cleanup/cleanup_state.c
postfix/src/global/mail_version.h
postfix/src/pickup/pickup.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_milter.c
postfix/src/smtpd/smtpd_state.c

index 1ea8da4d3fed4501af59fd5212ddda9b10ceff31..5ba3c211fa0da18f0199abb33669edf0bfdfcf4b 100644 (file)
@@ -12582,6 +12582,25 @@ Apologies for any names omitted.
        Compatibility: replace %% in milter replies by %, and strip
        single (i.e. invalid) % characters. File: milter/milter8.c.
 
+       Compatibility: $_ macro support for Milter applications.
+       Files: smtpd/smtpd.c, smtpd/smtpd_milter.c,
+       cleanup/cleanup_state.c, cleanup/cleanup_milter.c.
+
+20060721
+
+       Safety: disable Milter processing after "postsuper -r".  If
+       the mail has been filtered there is no need to do it again.
+       Moreover, when mail has passed through an external content
+       filter, we don't have sufficient information to reproduce
+       the exact same SMTP events and Sendmail macros that Milters
+       received when the mail originally arrived in Postfix.  File:
+       pickup/pickup.c.
+
+       Bugfix: Milters received a truncated ORCPT=xxx parameter
+       due to destructive parsing of something that didn't have
+       to be preserved before Milter support was added to Postfix.
+       File: smtpd/smtpd.c.
+
 Wish list:
 
        Add M flag (enable multi-recipient delivery) to pipe daemon.
index e3d75e6ef6bdc9783a7c65e96cac69d50ec5060e..5dadb462ced9e80279d00ddf46e6a44f33d75dd8 100644 (file)
@@ -61,6 +61,8 @@ depend_update:
 tidy:  clean
        rm -f Makefile */Makefile src/*/Makefile
        cp Makefile.init Makefile
+       rm -f README_FILES/RELEASE_NOTES
+       ln -s ../RELEASE_NOTES README_FILES
        rm -f bin/[!CRS]* lib/[!CRS]* include/[!CRS]* libexec/[!CRS]* \
            junk */junk */*/junk \
            *core */*core */*/*core \
index 659e23a0664c098ab68036ca09962944b1490279..ca95394f61d28bc20d43cf87ece03a8eb0ed5f7c 100644 (file)
@@ -104,7 +104,7 @@ On other platforms you have two options:
     Sendmail source code instead:
 
         $ g\bgz\bzc\bca\bat\bt s\bse\ben\bnd\bdm\bma\bai\bil\bl-\b-x\bx.\b.y\by.\b.z\bz.\b.t\bta\bar\br.\b.g\bgz\bz |\b| t\bta\bar\br x\bxf\bf -\b-
-        $ c\bcd\bd s\bse\ben\bnd\bdm\bma\bai\bil\bl-\b-x\bx.\b.y\by.\b.z\bz
+        $ c\bcd\bd s\bse\ben\bnd\bdm\bma\bai\bil\bl-\b-x\bx.\b.y\by.\b.z\bz/\b/l\bli\bib\bbm\bmi\bil\blt\bte\ber\br
         $ m\bma\bak\bke\be
         [...lots of output omitted...]
 
@@ -316,6 +316,9 @@ workarounds section below for solutions.
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |j                   |Always                   |value of myhostname       |
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |_                   |Always                   |The validated client name |
+    |                    |                         |and address               |
+    |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |{auth_authen}       |MAIL, DATA, EOM          |SASL login name           |
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |{auth_author}       |MAIL, DATA, EOM          |SASL sender               |
deleted file mode 100644 (file)
index ef08d6de54bbc73ca482b547671456cc7cf2abb6..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,113 +0,0 @@
-The stable Postfix release is called postfix-2.2.x where 2=major
-release number, 2=minor release number, x=patchlevel.  The stable
-release never changes except for patches that address bugs or
-emergencies. Patches change the patchlevel and the release date.
-
-New features are developed in snapshot releases. These are called
-postfix-2.3-yyyymmdd where yyyymmdd is the release date (yyyy=year,
-mm=month, dd=day).  Patches are never issued for snapshot releases;
-instead, a new snapshot is released.
-
-The mail_release_date configuration parameter (format: yyyymmdd)
-specifies the release date of a stable release or snapshot release.
-
-Incompatibility with Postfix 2.1 and earlier
-============================================
-
-If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
-before proceeding.
-
-Major changes with snapshot 20050510
-====================================
-
-This release improves usability of DSN (enhanced status codes) in
-Postfix access tables, RBL reply templates and in transport maps
-that use the error(8) delivery agent.
-
-- When the SMTP server rejects a sender address, it transforms a
-  recipient DSN status (e.g., 4.1.1-4.1.6) into the corresponding
-  sender DSN status, and vice versa.
-
-- When the SMTP server rejects non-address information (such as the
-  HELO command parameter or the client hostname/address), it
-  transforms a sender or recipient DSN status into a generic
-  non-address DSN status (e.g., 4.0.0).
-
-These transformations are needed when the same access table or RBL
-reply template are used for client, helo, sender, or recipient
-restrictions; or when the same error(8) mailer information is used
-for both senders and recipients.
-
-Incompatibility with snapshot 20050503
-======================================
-
-The format of some "warning:" messages in the maillog has changed
-so that they are easier to sort:
-
-- The logging now talks about "access table", instead of using three
-different expressions "access table", "access map" and "SMTPD access
-map" for the same thing.
-
-- "non-SMTP command" is now logged BEFORE the client name/address
-and the offending client input, instead of at the end.
-
-Major change with snapshot 20050427+DSN
-=======================================
-
-This is experimental DSN support added to snapshot 20050427.  The
-code is not for production purposes; it is not fully tested, some
-names and interfaces are still rough around the edges, and it does
-not update the oqmgr so you have to use qmgr instead.  Some
-implementation notes and open issues are described in the
-DSN_SUPPORT_README file (top-level directory).
-
-Incompatibility with snapshot 20050329
-======================================
-
-If you use TLS, you need to execute "postfix reload" because the
-TLS manager protocol has changed.
-
-Incompatibility with snapshot 20050328
-======================================
-
-The logging format has changed. Postfix delivery agents now log the
-RFC 3463 enhanced status code as "dsn=x.y.z" where y and z can be
-up to three digits each. See the file pfloggsum-dsn-patch for an
-update to the pfloggsum script.
-
-After you upgrade from Postfix 2.2 or 2.3 you need to execute
-"postfix reload", otherwise you will keep running the old Postfix
-queue manager, which gives no special treatment to the enhanced
-status codes that it receives from Postfix delivery agents.
-
-Major changes with snapshot 20050328
-====================================
-
-This release introduces support for RFC 3463 enhanced status codes.
-For example, status code 5.1.1 means "recipient unknown". Postfix
-recognizes enhanced status codes in remote server replies, generates
-enhanced status codes while handling email, and reports enhanced
-status codes in non-delivery notifications.  This improves the user
-interaction with mail clients that hide the text of error messages
-from users.
-
-You can, but don't have to, specify RFC 3463 enhanced status codes
-in the output from commands that receive mail from a pipe. If a
-command terminates with non-zero exit status, and an enhanced status
-code is present at the beginning of the command output, then that
-status code takes precedence over the non-zero exit status.
-
-You can, but don't have to, specify RFC 3463 enhanced status codes
-in Postfix access maps, header/body_checks REJECT actions, or in
-RBL replies.  For example:
-
-    REJECT 5.7.1 You can't go here from there
-
-The status 5.7.1 means "no authorization, message refused", and is
-the default for access maps, header/body_checks REJECT actions, and
-for RBL replies.
-
-If you specify your own enhanced status code, the Postfix SMTP
-server will automatically change a leading '5' digit (hard error)
-into '4' where appropriate.  This is needed, for example, with
-soft_bounce=yes.
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..577eefe81a6d6573e513f1965722f9483b1ad6f3
--- /dev/null
@@ -0,0 +1 @@
+../RELEASE_NOTES
\ No newline at end of file
index 9f8a5151be5bc1cd26fe350afcd9a7c37f9254b9..2619bab66bced4d3a702ebc679e6d0417c918eea 100644 (file)
@@ -228,7 +228,7 @@ library from Sendmail source code instead: </p>
 <blockquote>
 <pre>
 $ <b>gzcat sendmail-<i>x.y.z</i>.tar.gz | tar xf -</b>
-$ <b>cd sendmail-<i>x.y.z</i></b>
+$ <b>cd sendmail-<i>x.y.z</i>/libmilter</b>
 $ <b>make</b>
 [...<i>lots of output omitted</i>...]
 </pre>
@@ -521,6 +521,9 @@ href="#workarounds">workarounds</a> section below for solutions.
 <tr> <td> j </td> <td> Always </td> <td> value of <a href="postconf.5.html#myhostname">myhostname</a> </td>
 </tr>
 
+<tr> <td> _ </td> <td> Always </td> <td> The validated client name
+and address </td> </tr>
+
 <tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOM </td> <td> SASL
 login name </td> </tr>
 
diff --git a/postfix/implementation-notes/MILTER b/postfix/implementation-notes/MILTER
new file mode 100644 (file)
index 0000000..587500c
--- /dev/null
@@ -0,0 +1,255 @@
+Distribution of Milter responsibility
+=====================================
+
+Milters look at the SMTP commands as well as the message content.
+In Postfix these are handled by different processes:
+
+- smtpd(8) (the SMTP server) focuses on the SMTP commands, strips
+  the SMTP encapsulation, and passes envelope information and message
+  content to the cleanup server.
+
+- the cleanup(8) server parses the message content (it understands
+  headers, body, and MIME structure), and creates a queue file with
+  envelope and content information. The cleanup server adds additional
+  envelope records, such as when to send a "delayed mail" notice.
+
+If we want to support message modifications (add/delete recipient,
+add/delete/replace header, replace body) then it pretty much has
+to be implemented in the cleanup server, if we want to avoid extra
+temporary files.
+
+Network versus local submission
+===============================
+
+As of Sendmail 8.12, all mail is received via SMTP, so all mail is
+subject to Miltering (local submissions are queued in a submission
+queue and then delivered via SMTP to the main MTA). In Postfix,
+local submissions are received by the pickup server, which feeds
+the mail into the cleanup server after doing some sanity checks.
+
+How do we set up the Milters with SMTP mail versus local submissions?
+
+- SMTP mail: smtpd creates Milter contexts, and sends them, including
+  their sockets, to the cleanup server. The smtpd is responsible
+  for sending the Milter abort and close messages. Both smtpd and
+  cleanup are responsible for closing their Milter socket. Since
+  smtpd and cleanup inspect mail at different times, there is no
+  conflict with access to the Milter socket.
+
+- Local submission: the cleanup server creates Milter contexts.
+  The cleanup server provides dummy connect and helo information,
+  or perhaps none at all, and provides sender and recipient events.
+  The cleanup server is responsible for sending the Milter abort
+  and close messages, and for closing the Milter socket.
+
+A special case of local submission is "sendmail -t". This creates
+a record stream in which recipients appear after content. However,
+Milters expect to receive envelope information before content, not
+after.  This is not a problem: just like a queue manager, the
+cleanup-side Milter client can jump around through the queue file
+and send the information to the Milter in the expected order.
+
+Interaction with XCLIENT, "postsuper -r", and external content filters
+======================================================================
+
+Milter applications expect that the MTA supplies context information
+in the form of Sendmail-like macros (j=hostname, {client_name}=the
+SMTP client hostname, etc.). Not all these macros have a Postfix
+equivalent. Postfix 2.3 makes a subset available.
+
+If Postfix does not implement a specific macro, people can usually
+work around it. But we should avoid inconsistency. If Postfix can
+make macro X available at Milter protocol stage Y, then it must
+also be able to make that macro available at all later Milter
+protocol stages, even those that are handled by a different Postfix
+process.
+
+Thus, when adding Milter support for a specific Sendmail-like macro    
+to the SMTP server:
+
+- We may have to update the XCLIENT protocol, so that Milter
+  applications can be tested with XCLIENT. If not, then we must
+  prominently document everywhere that XCLIENT does not provide
+  100% accurate simulation for Milters. An additional complication
+  is that the SMTP command length is limited, and that each XCLIENT
+  command resets the SMTP server to the 220 stage and generates
+  "connect" events for anvil(8) and for Milters.
+
+- The SMTP server has to send the corresponding attribute to the
+  cleanup server.  The cleanup server then stores the attribute in
+  the queue file, so that Milters produce consistent results when
+  mail is re-queued with "postsuper -r".
+
+But wait, there is more. If mail is filtered by an external content
+filter, then it needs to preserve all the Milter attributes so that
+after "postsuper -r", Milters produce the exact same result as when
+mail was received originally by Postfix. Specifically, after
+"postsuper -r" a signing Milter must not sign mail that it did not
+sign on the first pass through Postfix, and it must not reject mail
+that it accepted on the first pass through Postfix.
+
+Instead of trying to re-create the Milter execution environment
+after "postsuper -r" we simply disable Milter processing. The
+rationale for this is: if mail was Miltered before it was written
+to queue file, then there is no need to Milter it again.
+
+We might want to take a similar approach with external (signing or
+blocking) content filters: don't filter mail that has already been
+filtered. Unfortunately, this is complicated by the fact that mail
+can make multiple iterations through Postfix (for example, when
+multiple external content filters are configured). Mail that was
+caught by "postsuper -r" somewhere in the middle if this trip should
+not be allowed to slip past any filters. To achieve this, we would
+have to preserve its current "content_filter" record that specifies
+what needs to be done next. This is the opposite of normal "postsuper
+-r" usage, which is most often intended to remove unwanted
+"content_filter" records. We could add a postsuper command-line
+option to re-queue and preserve "content_filter" records, but is
+is unlikely that humans will ever be able to use this correctly.
+
+Message envelope or content modifications
+=========================================
+
+Milters can send modification requests after receiving the end of
+the message body.  If we can implement all the header/body-related
+Milter operations in the cleanup server, then we can try to edit
+the queue file in place, without ever having to make a temporary
+copy. Once a Milter is done editing, the queue file can be used as
+input for the next Milter, and so on. Finally, the cleanup server
+calls fsync() and waits for successful return.
+
+To implement in-place queue file edits, we need to introduce
+surprisingly little change to the existing Postfix queue file
+structure.  All we need is a way to specify a jump from one place
+in the file to another.
+
+Postfix does not store queue files as plain text files. Instead all
+information is stored in records with an explicit type and length
+for sender, recipient, arrival time, and so on.  Even the content
+that makes up the message header and body is stored as records with
+an explicit type and length.  This organization makes it very easy
+to introduce pointer records, which is what we will use to jump
+from one place in a queue file to another place.
+
+- Deleting a recipient or header record is easy - just mark the
+  record as killed.  When deleting a recipient, we must kill all
+  recipient records that result from virtual alias expansion of the
+  original recipient address. When deleting a very long header or
+  body line, multiple queue file records may need to be killed. We
+  won't try to reuse the deleted space for other purposes.
+
+- Replacing header or body records involves pointer records.
+  Basically, a record is replaced by overwriting it with a forward
+  pointer to space after the end of the queue file, putting the new
+  record there, followed by a reverse pointer to the record that
+  follows the replaced information. If the replaced record is shorter
+  than a pointer record, we relocate the records that follow it to
+  the new area, until we have enough space for the forward pointer
+  record. See below for a discussion on what it takes to make this
+  safe.
+
+  Postfix queue files are segmented. The first segment is for
+  envelope records, the second for message header and body content,
+  and the third segment is for information that was extracted or
+  generated from the message header and body content.  Each segment
+  is terminated by a marker record. For now we don't want to change
+  their location. In particular, we want to avoid moving the start
+  of a segment.
+
+  To ensure that we can always replace a header or body record by
+  a pointer record, without having to relocate a marker record, the
+  cleanup server always places a dummy pointer record at the end
+  of the headers and at the end of the body.
+
+  When a Milter wants to replace an entire body, we have the option
+  to overwrite existing body records until we run out of space, and
+  then writing a pointer to space at the end of the queue file,
+  followed by the remainder of the body, and a pointer to the marker
+  that ends the message content segment.
+
+- Appending a recipient or header record involves pointer records
+  as well. This requires that the queue file already contains a
+  dummy pointer record at the place where we want to append recipient
+  or header content (Milters currently do not replace individual
+  body records, but we could add this if need be).  To append,
+  change the dummy pointer into a forward pointer to space after
+  the end of a message, put the new record there, followed by a
+  reverse pointer to the record that follows the forward pointer.
+
+  To append another record, replace the reverse pointer by a forward
+  pointer to space after the end of a message, put the new record
+  there, followed by the value of the reverse pointer that we
+  replace. Thus, there is no one-to-one correspondence between
+  forward and backward pointers! In fact, there can be multiple
+  forward pointers for one reverse pointer.
+
+When relocating a record we must not relocate the target of a jump
+==================================================================
+
+As discussed above, when replacing an existing record, we overwrite
+it with a forward pointer to the new information. If the old record
+is too small we relocate one or more records that follow the record
+that's being replaced, until we have enough space for the forward
+pointer record.
+
+Now we have to become really careful. Could we end up relocating a
+record that is the target of a forward or reverse pointer, and thus
+corrupt the queue file? The answer is NO.
+
+- We never relocate end-of-segment marker records. Instead, the
+  cleanup server writes dummy pointer records to guarantee that
+  there is always space for a pointer.
+
+- When a record is the target of a forward pointer, it is "edited"
+  information that is preceded either by the end-of-queue-file
+  marker record, or it is preceded by the reverse pointer at the
+  end of earlier written "edited" information. Thus, the target of
+  a forward pointer will not be relocated to make space for a pointer
+  record.
+
+- When a record is the target of a reverse pointer, it is always
+  preceded by a forward pointer record (or by a forward pointer
+  record followed by some unused space). Thus, the target of a
+  reverse pointer will not be relocated to make space for a pointer
+  record.
+
+Could we end up relocating a pointer record?  Yes, but that is OK,
+as long as pointers contain absolute offsets.
+
+Pointer records introduce the possibility of loops
+==================================================
+
+When a queue file is damaged, a bogus pointer value may send Postfix
+into a loop. This must not happen.
+
+Detecting loops is not trivial:
+
+- A sequence of multiple forward pointers may be followed by one
+  legitimate reverse pointer to the location after the first forward
+  pointer. See above for a discussion of how to append a record to
+  an appended record.
+
+- We do know, however, that there will not be more reverse pointers
+  than forward pointers. But this does not help much.
+
+Perhaps we can include a record count at the start of the queue
+file, so that the record walking code knows that it's looking at
+some records more than once, and return an error indication.
+
+How many bytes do we need for a pointer record?
+===============================================
+
+A pointer record would look like this:
+
+    type (1 byte)
+    offset (see below)
+
+Postfix uses long for queue file size/offset information, and stores
+them as %15ld in the SIZE record at the start of the queue file.
+This is somewhat less than a 64-bit long, but it is enough for a
+some time to come, and it is easily changed without breaking forward
+or backward compatibility.
+
+It does mean, however, that a pointer record can easily exceed the
+length of a header record. This is why we go through the trouble
+of record relocation and dummy records.
index 7005e09863ecae6291d5a91500ae7b4a504a3946..3fcf83da22bea9ff32693531c89462c92a587386 100644 (file)
@@ -228,7 +228,7 @@ library from Sendmail source code instead: </p>
 <blockquote>
 <pre>
 $ <b>gzcat sendmail-<i>x.y.z</i>.tar.gz | tar xf -</b>
-$ <b>cd sendmail-<i>x.y.z</i></b>
+$ <b>cd sendmail-<i>x.y.z</i>/libmilter</b>
 $ <b>make</b>
 [...<i>lots of output omitted</i>...]
 </pre>
@@ -521,6 +521,9 @@ href="#workarounds">workarounds</a> section below for solutions.
 <tr> <td> j </td> <td> Always </td> <td> value of myhostname </td>
 </tr>
 
+<tr> <td> _ </td> <td> Always </td> <td> The validated client name
+and address </td> </tr>
+
 <tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOM </td> <td> SASL
 login name </td> </tr>
 
index c3b5dd612a21196195f0d952d6204c68bd531f42..12b1d77dc92edddec137bfc2b521d0b51fd4f38d 100644 (file)
@@ -91,6 +91,7 @@ typedef struct CLEANUP_STATE {
 #endif
     MILTERS *milters;                  /* mail filters */
     const char *client_name;           /* real or ersatz client */
+    const char *reverse_name;          /* real or ersatz client */
     const char *client_addr;           /* real or ersatz client */
     int     client_af;                 /* real or ersatz client */
     const char *client_port;           /* real or ersatz client */
index beacd8249fac2ea299a48245ea2872fbd25e4a80..152c5c484de67b14606311d632e865f4cbffc110 100644 (file)
@@ -1215,12 +1215,21 @@ static const char *cleanup_milter_eval(const char *name, void *ptr)
     /*
      * Connect macros.
      */
+    if (strcmp(name, S8_MAC__) == 0) {
+       vstring_sprintf(state->temp1, "%s [%s]",
+                       state->reverse_name, state->client_addr);
+       if (strcasecmp(state->client_name, state->reverse_name) != 0)
+           vstring_strcat(state->temp1, " (may be forged)");
+       return (STR(state->temp1));
+    }
     if (strcmp(name, S8_MAC_J) == 0)
        return (var_myhostname);
     if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
-       return (nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR));
+       return (state->client_addr);
     if (strcmp(name, S8_MAC_CLIENT_NAME) == 0)
-       return (nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_NAME));
+       return (state->client_name);
+    if (strcmp(name, S8_MAC_CLIENT_PTR) == 0)
+       return (state->reverse_name);
 
     /*
      * MAIL FROM macros.
@@ -1373,6 +1382,8 @@ static void cleanup_milter_client_init(CLEANUP_STATE *state)
 #define NO_CLIENT_PORT "0"
 
     state->client_name = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_NAME);
+    state->reverse_name =
+       nvtable_find(state->attr, MAIL_ATTR_ACT_REVERSE_CLIENT_NAME);
     state->client_addr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR);
     state->client_port = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_PORT);
     proto_attr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_AF);
@@ -1384,6 +1395,8 @@ static void cleanup_milter_client_init(CLEANUP_STATE *state)
        state->client_af = AF_INET;
     } else
        state->client_af = atoi(proto_attr);
+    if (state->reverse_name == 0)
+       state->reverse_name = state->client_name;
     if (state->client_port == 0)
        state->client_port = NO_CLIENT_PORT;
 }
index d1fc37203f6c64bda88b3d85a454f87b6372b92d..2cbd73ec234a103bc4d5f3b98ecfe0581e02bfa8 100644 (file)
@@ -109,6 +109,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
     state->verp_delims = 0;
     state->milters = 0;
     state->client_name = 0;
+    state->reverse_name = 0;
     state->client_addr = 0;
     state->client_af = 0;
     state->client_port = 0;
index aefe5c413f13350b1a1d89e648f607c6406c4638..083656c3fb43fa13930b7bcc00c3d322e0c64fed 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20060720"
+#define MAIL_RELEASE_DATE      "20060721"
 #define MAIL_VERSION_NUMBER    "2.4"
 
 #ifdef SNAPSHOT
index bb1704e4f3099bf364038dca95f0d4ccb0687c8a..1cc8bb424a977c2c4d79cc64c1dcc766288bf17b 100644 (file)
@@ -442,6 +442,13 @@ static int pickup_file(PICKUP_INFO *info)
      * bounces its copy of the message. because the original input file is
      * not readable by the bounce service.
      * 
+     * If mail is re-injected with "postsuper -r", disable Milter applications.
+     * If they were run before the mail was queued then there is no need to
+     * run them again. Moreover, the queue file does not contain enough
+     * information to reproduce the exact same SMTP events and Sendmail
+     * macros that Milters received when the mail originally arrived in
+     * Postfix.
+     * 
      * The actual message copying code is in a separate routine, so that it is
      * easier to implement the many possible error exits without forgetting
      * to close files, or to release memory.
@@ -449,6 +456,8 @@ static int pickup_file(PICKUP_INFO *info)
     cleanup_flags =
        input_transp_cleanup(CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL,
                             pickup_input_transp_mask);
+    if (info->st.st_uid == var_owner_uid && (info->st.st_mode & S_IROTH) == 0)
+       cleanup_flags &= ~CLEANUP_FLAG_MILTER;
 
     cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
     if (attr_scan(cleanup, ATTR_FLAG_STRICT,
index 1f6dfdfd814aefbb92b4164262341f1b1ebed53f..00098b56e06dec69fd12729a47ceea2376222a96 100644 (file)
@@ -1699,6 +1699,8 @@ static int mail_open_stream(SMTPD_STATE *state)
             */
            rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                        MAIL_ATTR_ACT_CLIENT_NAME, state->name);
+           rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                   MAIL_ATTR_ACT_REVERSE_CLIENT_NAME, state->reverse_name);
            rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                        MAIL_ATTR_ACT_CLIENT_ADDR, state->addr);
            if (state->helo_name)
@@ -2246,10 +2248,11 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
                smtpd_chat_reply(state, "501 5.7.1 DSN support is disabled");
                return (-1);
            }
+           vstring_strcpy(state->dsn_orcpt_buf, arg + 6);
            if (dsn_orcpt_addr
-               || (coded_addr = split_at(arg + 6, ';')) == 0
+               || (coded_addr = split_at(STR(state->dsn_orcpt_buf), ';')) == 0
                || xtext_unquote(state->dsn_buf, coded_addr) == 0
-               || *(dsn_orcpt_type = arg + 6) == 0) {
+               || *(dsn_orcpt_type = STR(state->dsn_orcpt_buf)) == 0) {
                state->error_mask |= MAIL_ERROR_PROTOCOL;
                smtpd_chat_reply(state,
                             "501 5.5.4 Error: Bad ORCPT parameter syntax");
index 6f3f324d2ed24aa29922de25445c71a2c7caa1d4..44478605c69d655600ede3cbc59a3e8a0f63d8c3 100644 (file)
@@ -145,6 +145,7 @@ typedef struct SMTPD_STATE {
     char   *dsn_envid;                 /* temporary MAIL FROM state */
     int     dsn_ret;                   /* temporary MAIL FROM state */
     VSTRING *dsn_buf;                  /* scratch space for xtext expansion */
+    VSTRING *dsn_orcpt_buf;            /* scratch space for ORCPT parsing */
 
     /*
      * Pass-through proxy client.
index bf322c949ce00d96e2ea3e585127ac2047a4406a..2b4df40a934f77ab434f247ad6c419a878bcaaec 100644 (file)
@@ -78,6 +78,15 @@ const char *smtpd_milter_eval(const char *name, void *ptr)
     /*
      * Connect macros.
      */
+    if (strcmp(name, S8_MAC__) == 0) {
+       if (state->expand_buf == 0)
+           state->expand_buf = vstring_alloc(10);
+       vstring_sprintf(state->expand_buf, "%s [%s]",
+                       state->reverse_name, state->addr);
+       if (strcasecmp(state->name, state->reverse_name) != 0)
+           vstring_strcat(state->expand_buf, " (may be forged)");
+       return (STR(state->expand_buf));
+    }
     if (strcmp(name, S8_MAC_J) == 0)
        return (var_myhostname);
     if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
index fd8fb56406e3dd8ba195b9bb8350fd149998e727..64aa5a72ebaaf31d493092e22396951e7803df79 100644 (file)
@@ -137,6 +137,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
 #endif
     state->dsn_envid = 0;
     state->dsn_buf = vstring_alloc(100);
+    state->dsn_orcpt_buf = vstring_alloc(100);
 #ifdef USE_TLS
     state->tls_use_tls = 0;
     state->tls_enforce_tls = 0;