]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.0.16-20031128
authorWietse Venema <wietse@porcupine.org>
Fri, 28 Nov 2003 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:29:15 +0000 (06:29 +0000)
85 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/ADDRESS_VERIFICATION_README
postfix/README_FILES/FILTER_README
postfix/README_FILES/SMTPD_PROXY_README
postfix/README_FILES/XCLIENT_README [new file with mode: 0644]
postfix/conf/sample-smtp.cf
postfix/conf/sample-smtpd.cf
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/makedefs
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/src/anvil/Makefile.in
postfix/src/bounce/Makefile.in
postfix/src/cleanup/Makefile.in
postfix/src/dns/Makefile.in
postfix/src/error/Makefile.in
postfix/src/flush/Makefile.in
postfix/src/fsstone/Makefile.in
postfix/src/global/Makefile.in
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_stream.c
postfix/src/global/mail_version.h
postfix/src/global/mime_state.c
postfix/src/global/rewrite_clnt.c
postfix/src/global/xtext.c
postfix/src/global/xtext.h
postfix/src/lmtp/Makefile.in
postfix/src/local/Makefile.in
postfix/src/master/Makefile.in
postfix/src/master/master_ent.c
postfix/src/nqmgr/Makefile.in
postfix/src/nqmgr/qmgr.h
postfix/src/nqmgr/qmgr_active.c
postfix/src/nqmgr/qmgr_deliver.c
postfix/src/nqmgr/qmgr_message.c
postfix/src/pickup/Makefile.in
postfix/src/pipe/Makefile.in
postfix/src/postalias/Makefile.in
postfix/src/postcat/Makefile.in
postfix/src/postconf/Makefile.in
postfix/src/postdrop/Makefile.in
postfix/src/postfix/Makefile.in
postfix/src/postkick/Makefile.in
postfix/src/postlock/Makefile.in
postfix/src/postlog/Makefile.in
postfix/src/postmap/Makefile.in
postfix/src/postqueue/Makefile.in
postfix/src/postsuper/Makefile.in
postfix/src/proxymap/Makefile.in
postfix/src/qmgr/Makefile.in
postfix/src/qmgr/qmgr.h
postfix/src/qmgr/qmgr_active.c
postfix/src/qmgr/qmgr_deliver.c
postfix/src/qmgr/qmgr_message.c
postfix/src/qmqpd/Makefile.in
postfix/src/sendmail/Makefile.in
postfix/src/sendmail/sendmail.c
postfix/src/showq/Makefile.in
postfix/src/smtp/Makefile.in
postfix/src/smtp/smtp.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_peer.c
postfix/src/smtpd/smtpd_proxy.c
postfix/src/smtpd/smtpd_sasl_proto.c
postfix/src/smtpd/smtpd_state.c
postfix/src/smtpd/smtpd_xclient.c [new file with mode: 0644]
postfix/src/smtpstone/Makefile.in
postfix/src/spawn/Makefile.in
postfix/src/trivial-rewrite/Makefile.in
postfix/src/util/Makefile.in
postfix/src/util/neuter.c [new file with mode: 0644]
postfix/src/util/stringops.h
postfix/src/util/sys_defs.h
postfix/src/verify/Makefile.in
postfix/src/virtual/Makefile.in

index 64210d687bee6e98cf6a1a117b19b7a93f97303a..6c4de13ef8388f85936b7334651f473f186db388 100644 (file)
 -TSMTPD_RBL_STATE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
+-TSMTPD_XCLIENT_ATTR
 -TSMTP_ADDR
 -TSMTP_CMD
 -TSMTP_RESP
index ae0da92eb34becee5d9418720b3d5636800cfdc4..0f63bfe143fcb087d0e58345d60f5e466d5e91b4 100644 (file)
@@ -8755,6 +8755,39 @@ Apologies for any names omitted.
        controls periodic logging of maximal connection counts or
        rates.  The default logging interval is 10 minutes.
 
+       Feature: "make makefiles WARN=stuff..." overrides the
+       built-in GCC warning options that are used when "make" is
+       invoked from within a source subdirectory. Files:  makedefs,
+       */Makefile.in.
+
+20031125
+
+       Feature: qmgr logs "queueid: deleted", just like postsuper,
+       when it removes a message from the mail queue.
+
+       Performance: smtpd connects to the cleanup or proxy server
+       AFTER the first valid RCPT TO command, instead of after
+       the first valid MAIL FROM command. This avoid wasting
+       real-time proxy filter resources when mail is stopped by
+       the SMTP server's access blocks.  File: smtpd/smtpd.c.
+
+20031126
+
+       Bugfix: "panic: mymalloc: requested length 0" when master.cf
+       specified an invalid host name or address.  Postfix now
+       logs more specific information. File:  master/master_ent.c.
+       Reported by several people.
+
+20031125-8
+
+       Feature: XCLIENT support to override the SMTP server's
+       client information for logging and/or access control. This
+       replaces the short-lived XADDR and XLOGINFO extensions.
+       Based on code by Victor Duchovni, with major simplifications.
+       Files: smtpd/{smtpd,smtpd_check,smtpd_proxy,smtpd_xclient}.c
+       smtp/smtp_smtp_proto.c, *qmgr/qmgr_message.c,
+       global/deliver_request.c.
+
 Open problems:
 
        High: when virtual aliasing is turned off after content
index 4abd3bba5ae4fd806ef8818538edc0b679367c61..e14ec7ec410bffcbd3e9fbf9c3da7dc2bc6ccd72 100644 (file)
@@ -9,7 +9,9 @@ normal mail, but are discarded instead of being deferred or bounced.
 
 The same technique may be useful to block mail for undeliverable
 recipients, for example on mail relay hosts that do not have a copy
-of all the relayed recipient addresses.
+of all the relayed recipient addresses. This prevents undeliverable
+junk mail from entering the queue, so that Postfix doesn't have to
+waste resources trying to send mailer-daemon messages back.
 
 With address verification turned on, normal mail will suffer only
 a short delay of up to 6 seconds while an address is verified for
@@ -95,6 +97,8 @@ specific domains that often appear in forged email.
 /etc/postfix/main.cf:
     smtpd_sender_restrictions = hash:/etc/postfix/sender_access
     unverified_sender_reject_code = 550
+    # Be sure to read the "Caching" section below!
+    address_verify_map = btree:/var/mta/verify
  
 /etc/postfix/sender_access:
     aol.com     reject_unverified_sender
@@ -120,6 +124,7 @@ To find out how sender address verification would affect your mail,
 specify "warn_if_reject reject_unverified_sender" so that you can
 see what mail would be blocked:
 
+/etc/postfix/main.cf:
     smtpd_sender_restrictions = 
        permit_mynetworks
        ... 
@@ -127,6 +132,8 @@ see what mail would be blocked:
        reject_unknown_sender_domain
        warn_if_reject reject_unverified_sender 
        ...
+    # Be sure to read the "Caching" section below!
+    address_verify_map = btree:/var/mta/verify
 
 This is also a good way to populate your cache with address
 verification results before you start to actually reject mail.
@@ -160,7 +167,7 @@ Caching
 NOTE: By default, address verification information is not stored
 in a persistent file. You have to specify one in main.cf (see
 below). Persistent storage is off by default because it may need
-more disk space than is available in your root file system.
+more disk space than is available in your file system.
 
 Address verification information is cached by the Postfix verify
 daemon.  Postfix has a bunch of parameters that control the caching
@@ -173,9 +180,9 @@ verification results.  If you don't specify a file, all address
 verification information is lost after "postfix reload" or "postfix
 stop".
 
-If your root file system has sufficient space, try:
+If your /var file system has sufficient space, try:
 
-    address_verify_map = btree:/etc/postfix/verify
+    address_verify_map = btree:/var/mta/verify
 
 NOTE: Do not put this file in a file system that fills up. When
 the address verification table gets corrupted the world comes to
@@ -197,8 +204,8 @@ accepted) and for negative results (address was rejected).
 
 Right now, no tools are provided to manage the address verification
 database. If the file gets too big, or if it gets corrupted, you
-can manually delete the file and run "postfix reload".  The new
-verify daemon process will then create a new, empty, database.
+can manually rename or delete the file and run "postfix reload".
+The new verify daemon process will then create a new database.
 
 Controlling the routing of address verification probes
 ======================================================
@@ -249,6 +256,7 @@ for address verification probes and leave everything else alone:
 /etc/postfix/main.cf:
     relayhost = $mydomain
     address_verify_relayhost =
+    ...
 
 Sites behind an address translation relay might have to use a
 different SMTP client that sends the correct hostname information:
index 6c377b0fd606292125f16a981e3aedb9c91f5a6b..b973c97cff76c357c251ea8a273b33e1bc5bc427 100644 (file)
@@ -233,12 +233,19 @@ one would set up the service in the Postfix master.cf file:
 
     /etc/postfix/master.cf:
         scan      unix  -       -       n       -       10       smtp
+       #       -o smtp_send_xclient_command=yes
 
 Instead of a limit of 10 concurrent processes, use whatever process
 limit is feasible for your machine.  Content inspection software
 can gobble up a lot of system resources, so you don't want to have
 too much of it running at the same time.
 
+Uncomment (but keep the leading white-space) the option setting:
+"smtp_send_xclient_command=yes", if you would like the scan transport
+to forward the original client name and IP address to the backend smtpd
+so that mail transaction logs show the real client name IP address.
+See sample-smtp.cf and smtp(8).
+
 The content filter can be set up with the Postfix spawn service,
 which is the Postfix equivalent of inetd. For example, to instantiate
 up to 10 content filtering processes on demand:
index d39e64cfcd4c58f6039b126e3b93cef13c174d18..c6f63acbf6f7af18fd0845410d65ecf71f54d93d 100644 (file)
@@ -68,7 +68,7 @@ How Postfix talks to the before-queue content filter
 The before-filter Postfix SMTP server connects to the content
 filter, delivers one message, and disconnects.  While sending mail
 into the content filter, Postfix speaks ESMTP but uses no command
-pipelining.  Postfix generates its own EHLO, XLOGINFO (for logging
+pipelining.  Postfix generates its own EHLO, XCLIENT (for logging
 the remote client IP address instead of localhost[127.0.0.1]), DATA
 and QUIT commands, and forwards unmodified copies of all the MAIL
 FROM and RCPT TO commands that the before-filter Postfix SMTP server
@@ -85,6 +85,9 @@ the connection with the after-filter Postfix SMTP server without
 completing the SMTP conversation with the after-filter Postfix SMTP
 server.
 
+More details on the postfix-to-proxy interaction is at the end of
+this document, in the section titled "Transparency".
+
 Configuration parameters
 ========================
 
@@ -119,7 +122,7 @@ for testing, of course.
     smtp      inet  n       -       n       -       -       smtpd
         -o smtpd_proxy_filter=26
     :26       inet  n       -       n       -       -       smtpd
-       -o smtpd_authorized_xloginfo_clients=127.0.0.0/8
+       -o smtpd_authorized_xclient_hosts=127.0.0.0/8
        -o smtpd_client_restrictions=
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
@@ -132,10 +135,10 @@ Note: do not specify spaces around the "=" or "," characters.
 The ":26" causes Postfix to listen on the localhost address only.
 DO NOT expose the secondary SMTP server to the Internet :-)
 
-The smtpd_authorized_xloginfo_clients parameter allows the before
-filter SMTP server to pass the remote SMTP client name and address
-to the after-filter SMTP server, so that the after-filter Postfix
-daemons log the remote client name and address instead of logging
+The smtpd_authorized_xclient_hosts parameter allows the before
+filter SMTP server to forward remote SMTP client information to
+the after-filter SMTP server, so that the after-filter Postfix
+daemons log the remote SMTP client information instead of logging
 localhost[127.0.0.1].
 
 The other parameter settings avoid duplication of effort that is
@@ -149,3 +152,36 @@ This configuration is sufficient for stress testing.
 
 Other suggestions for test configurations: use the Postfix smtp-sink
 command as the proxy, or something as basic as netcat.
+
+Transparency
+============
+
+The before-filter Postfix SMTP server forwards the MAIL FROM, RCPT
+TO and DATA commands that it has approved, but it does not forward
+other commands such as TLS or SASL commands.  It can therefore not
+be transparent.
+
+The real-time content filter, on the other hand, has to be transparent.
+In order to support non-transparent real-time content filters,
+Postfix would have to reconcile the before-filter Postfix ESMTP
+feature set with the feature set that Postfix receives from the
+real-time content filter.
+
+- When a future Postfix version supports DSN, but the content filter
+does not announce DSN support in the EHLO reply, then the before-filter
+SMTP server would have to either 1) suppress the DSN feature in
+its EHLO announcement, or 2) duplicate all the work that needs to
+be done when delivering DSN-aware mail to a non-DSN destination.
+
+- When the content filter does not announce 8BITMIME support in
+the EHLO reply, then the before-filter SMTP server would have to
+either 1) suppress the 8BITMIME feature in its EHLO announcement,
+or 2) convert the content to quoted-printable before giving it to
+the content filter.
+
+- Performance: when Postfix has to suppress elements from the
+before-filter EHLO reply because they are incompatible with the
+real-time content filter, then Postfix has to connect to the content
+filter as soon as the client sends a valid EHLO command. This wastes
+a lot of resources when all the MAIL FROM or RCPT TO commands are
+rejected.
diff --git a/postfix/README_FILES/XCLIENT_README b/postfix/README_FILES/XCLIENT_README
new file mode 100644 (file)
index 0000000..3624bc8
--- /dev/null
@@ -0,0 +1,185 @@
+Purpose of the XCLIENT extension to SMTP
+========================================
+
+The XCLIENT command targets problems in the following areas:
+
+1 - Access control tests. SMTP server access rules are difficult
+to verify when decisions can be triggered only by remote clients.
+In order to facilitate access rule testing, an SMTP client test
+program needs the ability to override the SMTP server's idea of
+the SMTP client hostname, network address, and other information.
+
+2 - Logging after content filter. With Internet->MTA1->filter->MTA2
+style content filter applications, remote client information is
+lost when MTA1 gives the mail to the content filter.  This complicates
+the interpretation of the audit trail.  In order maintain audit
+trail continuity, MTA1 needs the ability to forward client information
+through the content filter to MTA2.
+
+3 - Post-filter access control and logging. With Internet->filter->MTA
+style content filter applications, the content filter can be greatly
+simplified if it can delegate all decisions concerning mail relay
+and other access control to the MTA. This requires that the filter
+can forward client information to the MTA for access control
+purposes.
+
+The preceding suggests that there is a need for two modes of
+operation:
+
+  - Operation mode 1: override the SMTP server's idea of SMTP
+    client information for access control and audit trail purposes.
+    Attributes that one may want to override are:
+
+        client network address 
+        client hostname 
+        hostname lookup failure type (permanent or temporary)
+       client protocol (e.g., SMTP or ESMTP)
+
+  - Operation mode 2: forward remote client information for audit
+    trail purposes only.  Examples of attributes are:
+
+        client network address 
+        client hostname 
+       client protocol (e.g., SMTP or ESMTP)
+       client SMTP HELO parameter
+
+General XCLIENT command syntax
+==============================
+
+The XCLIENT command maintains one set of attributes with surrogate
+client information. The general XCLIENT command syntax is described
+below.  Upper case and quoted strings specify terminals, lowercase
+strings specify meta terminals, SP is whitespace, and descriptive
+text is in {}.  Although shown below in upper case, command and
+attribute names are in fact case insensitive.
+
+    xclient-command = XCLIENT *( SP argument )
+
+    argument = ( request | attribute )
+
+    request = ( RST | ACL | LOG )
+
+    attribute = name"="value
+
+    name = ( CLIENT_NAME | CLIENT_ADDR | CLIENT_CODE | PROTOCOL | HELO_NAME )
+
+    value = ( { empty } | xtext )
+
+    xtext = { attribute value encoded as per RFC 1891 }
+
+The XCLIENT command is typically sent immediately before or after
+the EHLO command, may be pipelined after the server announces ESMTP
+pipelining support, and must not be used in the middle of an SMTP
+transaction (i.e. between MAIL and DOT).
+
+The server reply codes are as follows:
+
+   Code | Meaning
+   -----|------------
+    250 | success 
+    501 | command syntax error
+    502 | unrecognized request name
+    503 | command out of order (name=value without prior ACL or LOG request)
+    421 | unable to proceed
+
+The server must report success in case of an unrecognized attribute
+name, although it may log a warning.
+
+Specific XCLIENT usage scenarios
+================================
+
+This section discusses the semantics of XCLIENT requests.  Specific
+syntax information is given in the next section.
+
+The RST request resets all XCLIENT attributes and disables any
+override of access control or audit trail attributes. Example:
+
+    XCLIENT RST
+
+The ACL request resets all XCLIENT attributes and must be specified
+before sending surrogate attributes for access control and audit
+trail purposes.  Attributes that are not explicitly specified will
+default to their actual value.  Example:
+
+    XCLIENT ACL CLIENT_NAME=spike.porcupine.org
+    XCLIENT CLIENT_ADDR=168.100.189.2
+
+This overrides only the client hostname and network address, but
+none of the other client attributes.
+
+The LOG request resets all XCLIENT attributes and must be specified
+before sending surrogate attributes for audit trail purposes.
+Attributes that are not explicitly specified will default to the
+unknown value.  Example:
+
+    XCLIENT LOG CLIENT_NAME=spike.porcupine.org CLIENT_ADDR=168.100.189.2
+    XCLIENT HELO_NAME=spike.porcupine.org PROTOCOL=ESMTP
+
+This overrides all client attributes that are defined in this
+document, leaving none at their default unknown value.
+
+Note 1: it is an error to specify name=value pairs without prior
+ACL or LOG request.
+
+Note 2: after an ACL or LOG request, attributes specified with
+successive XCLIENT commands accumulate until the next RST, ACL or
+LOG request.
+
+Note 3: if one XCLIENT command specifies multiple requests (e.g.,
+both ACL and LOG), only the last request takes effect.
+
+XCLIENT attribute value details
+===============================
+
+Attribute values are encoded as RFC 1891 xtext strings. To explicitly
+specify that an attribute value is unknown, the value must be empty;
+the client is not allowed to send its own internal representation
+for unknown information.
+
+CLIENT_CODE specifies CLIENT_NAME hostname lookup status information.
+Values are OK (success), TEMP (temporary lookup failure) or PERM
+(permanent lookup failure). When CLIENT_CODE is set to any value
+other than OK, the CLIENT_NAME attribute is set to the unknown
+value.
+
+CLIENT_NAME should specify a syntactically valid domain name and
+not a numerical address.  When a null client name is specified
+(i.e.  the client name is unknown), the CLIENT_CODE attribute is
+set to PERM. When a valid domain name is specified, CLIENT_CODE is
+set to OK. The server may process a syntactically invalid domain
+name as if it were unknown.
+
+CLIENT_ADDR must specify a numerical network address without [].
+
+PROTOCOL is a string of up to 64 printable characters.
+
+HELO_NAME should be a syntactically valid domain name.
+
+Note 4: syntactically valid CLIENT_NAME and HELO_NAME attributes
+can be up to 255 characters long. The client must not send XCLIENT
+commands that exceed the 512 character limit of SMTP commands.
+
+Note 5: attribute values may end up in Received: or other message
+headers.  The server may substitute any characters that are special
+according to RFC 822 or RFC 2822.
+
+Security
+========
+
+The XCLIENT command changes audit trails and changes client access
+permissions. For these reasons, use of the XCLIENT command must be
+restricted to authorized clients only. 
+
+The examples in this document assume that XCLIENT does not override
+its own access control mechanism.
+
+SMTP connection caching
+=======================
+
+SMTP connection caching makes it possible to deliver multiple
+messages within the same SMTP session. Thus, one persistent SMTP
+session with a content filter can carry messages from unrelated
+clients.  Attributes from one remote client should not affect the
+delivery of mail from a different remote client.  In order to
+prevent such information leakage, use the XCLIENT RST, ACL or LOG
+requests as appropriate.
index ca85a151a3873a2c14a1a45dd258c3b3095f265d..0d6e9cf113d25fb8ec972d8504ff218d5a3ae795 100644 (file)
@@ -76,6 +76,17 @@ smtp_never_send_ehlo = no
 # 
 smtp_defer_if_no_mx_address_found = no
 
+# The smtp_send_xclient_command parameter controls whether the Postfix
+# SMTP client will send an XCLIENT command to the SMTP server, when
+# the ESMTP HELO response of the remote host indicates XCLIENT support.
+# This allows an "smtp" delivery agent, used for content filter
+# message injection, to forward the name, address, protocol and HELO
+# name of the original client to the content filter and downstream
+# queuing SMTP server. Before you change the value to yes, it is best
+# to make sure your content filter supports this command.
+# 
+smtp_send_xclient_command = no
+
 # The smtp_line_length_limit parameter controls the length of
 # message header and body lines that Postfix will send via SMTP.
 # Lines that are longer are broken by inserting <CR> <LF> <SPACE>.
index 8f93a3631c07b643c5d9b0cf59bf8a12156417c0..0770765024675d8a635bc40aa748e61371347914 100644 (file)
@@ -154,32 +154,14 @@ smtpd_client_connection_limit_exceptions = $mynetworks
 #
 #disable_vrfy_command = no
 
-# The smtpd_authorized_xaddr_clients parameter specifies what clients
-# are allowed to specify the SMTP "XADDR client-address client-name"
-# command. This command changes Postfix's idea of the client hostname
-# and IP address for logging and for access control. Typical use is
-# for SMTPD access testing.
+# The smtpd_authorized_xclient_hosts parameter specifies what clients
+# are allowed to specify the XCLIENT extension to SMTP.
 #
-# By default, no clients are allowed to specify XADDR.
+# This command overrides SMTP client information that is used for
+# logging or access control. Typical use is for SMTP-based content
+# filters or for SMTP server access rule testing.
 #
-# Specify an explicit list of network/netmask patterns, where the
-# mask specifies the number of bits in the network part of a host
-# address. You can also specify hostnames or .domain names (the
-# initial dot causes the domain to match any name below it).
-#
-# You can also specify the absolute pathname of a pattern file instead
-# of listing the patterns here. Specify type:table for table-based lookups
-# (the value on the table right-hand side is not used).
-#
-smtpd_authorized_xaddr_clients =
-
-# The smtpd_authorized_xloginfo_clients parameter specifies what
-# clients are allowed to specify the SMTP "XLOGINFO client-address
-# client-name" command. This command changes Postfix's idea of the
-# client hostname and IP address for logging but not for access
-# control. Typical use is for SMTP-based content filters.
-#
-# By default, no clients are allowed to specify XLOGINFO.
+# By default, no clients are allowed to specify XCLIENT.
 #
 # Specify an explicit list of network/netmask patterns, where the
 # mask specifies the number of bits in the network part of a host
@@ -190,7 +172,7 @@ smtpd_authorized_xaddr_clients =
 # of listing the patterns here. Specify type:table for table-based lookups
 # (the value on the table right-hand side is not used).
 #
-smtpd_authorized_xloginfo_clients =
+smtpd_authorized_xclient_hosts =
 
 # The smtpd_authorized_verp_clients parameter specifies what clients
 # are allowed to specify the SMTP XVERP command. This command requests
index f9fe0ab727c5fa5c010ea8dc0e2df80fa6b179d0..eb8f02874970456a5c906f94001556f7f7c6ef72 100644 (file)
@@ -249,16 +249,20 @@ SMTP(8)                                                   SMTP(8)
               Timeout for  sending  the  <b>HELO</b>  command,  and  for
               receiving the server response.
 
+       <b>smtp_xclient_timeout</b>
+              Timeout  for  sending  the <b>XCLIENT</b> command, and for
+              receiving the server response.
+
        <b>smtp_mail_timeout</b>
-              Timeout  for sending the <b>MAIL FROM</b> command, and for
+              Timeout for sending the <b>MAIL FROM</b> command, and  for
               receiving the server response.
 
        <b>smtp_rcpt_timeout</b>
-              Timeout for sending the <b>RCPT TO</b>  command,  and  for
+              Timeout  for  sending  the <b>RCPT TO</b> command, and for
               receiving the server response.
 
        <b>smtp_data_init_timeout</b>
-              Timeout  for  sending  the  <b>DATA</b>  command,  and for
+              Timeout for  sending  the  <b>DATA</b>  command,  and  for
               receiving the server response.
 
        <b>smtp_data_xfer_timeout</b>
@@ -266,22 +270,29 @@ SMTP(8)                                                   SMTP(8)
 
        <b>smtp_data_done_timeout</b>
               Timeout  for  sending  the  "<b>.</b>"  command,  and  for
-              receiving  the server response. When no response is
-              received, a warning is logged that the mail may  be
+              receiving the server response. When no response  is
+              received,  a warning is logged that the mail may be
               delivered multiple times.
 
        <b>smtp_defer_if_no_mx_address_found</b>
-              If  no,  bounce mail when no MX host resolves to an
+              If no, bounce mail when no MX host resolves  to  an
               address (Postfix always ignores MX hosts with equal
-              or  worse  preference than the local MTA).  If yes,
-              keep trying until a suitable MX  host  resolves  or
+              or worse preference than the local MTA).   If  yes,
+              keep  trying  until  a suitable MX host resolves or
               until the mail is too old.
 
+       <b>smtp_send_xclient_command</b>
+              If the SMTP server announces XCLIENT support,  send
+              the  name,  address,  protocol and HELO name of the
+              original client. This can be used to forward client
+              information  through  a  content  filter to a down-
+              stream queuing SMTP server.
+
        <b>smtp_rset_timeout</b>
               Timeout for sending the <b>RSET</b> command.
 
        <b>smtp_quit_timeout</b>
-              Timeout  for  sending  the  <b>QUIT</b>  command,  and for
+              Timeout for  sending  the  <b>QUIT</b>  command,  and  for
               receiving the server response.
 
 <b>SEE ALSO</b>
@@ -291,7 +302,7 @@ SMTP(8)                                                   SMTP(8)
        syslogd(8) system logging
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index da940a734468c4cc4443f603016213beaffdd34c..9aefc27f1825780c91478550f93e2cfb449ba1e4 100644 (file)
@@ -170,42 +170,32 @@ SMTPD(8)                                                 SMTPD(8)
               Hostnames, domain names and/or addresses of clients
               that are authorized to use the XVERP extension.
 
-       <b>smtpd_authorized_xaddr_clients</b>
+       <b>smtpd_authorized_xclient_hosts</b>
               Hostnames, domain names and/or addresses of clients
-              that are  authorized  to  use  the  "XADDR  client-
-              address  client-name"  command.  This changes Post-
-              fix's idea of the SMTP client IP address and  host-
-              name for access control and for logging purposes.
-
-       <b>smtpd_authorized_xloginfo_clients</b>
-              Hostnames, domain names and/or addresses of clients
-              that are authorized to use  the  "XLOGINFO  client-
-              address  client-name"  command.   This  changes the
-              client name and address that are used for  logging,
-              without  affecting  the client IP address and host-
-              name that are used for access control.  XLOGINFO is
-              typically  used to propagate remote client informa-
-              tion through an SMTP-based content  filter  to  the
-              after-filter SMTP server.
+              that are authorized to  use  the  XCLIENT  command.
+              This  command changes client information for access
+              control and/or logging purposes, with the exception
+              of  the  <b>smtpd_authorized_xclient_hosts</b> access con-
+              trol itself.
 
        <b>debug_peer_level</b>
-              Increment  in  verbose  logging level when a remote
+              Increment in verbose logging level  when  a  remote
               host  matches  a  pattern  in  the  <b>debug_peer_list</b>
               parameter.
 
        <b>debug_peer_list</b>
-              List  of  domain or network patterns. When a remote
-              host matches a pattern, increase the  verbose  log-
-              ging   level   by   the  amount  specified  in  the
+              List of domain or network patterns. When  a  remote
+              host  matches  a pattern, increase the verbose log-
+              ging  level  by  the  amount   specified   in   the
               <b>debug_peer_level</b> parameter.
 
        <b>default_verp_delimiters</b>
               The default VERP delimiter characters that are used
-              when   the   XVERP  command  is  specified  without
+              when  the  XVERP  command  is   specified   without
               explicit delimiters.
 
        <b>error_notice_recipient</b>
-              Recipient   of    protocol/policy/resource/software
+              Recipient    of   protocol/policy/resource/software
               error notices.
 
        <b>hopcount_limit</b>
@@ -214,18 +204,18 @@ SMTPD(8)                                                 SMTPD(8)
        <b>notify_classes</b>
               List of error classes. Of special interest are:
 
-              <b>policy</b> When  a  client  violates any policy, mail a
+              <b>policy</b> When a client violates any  policy,  mail  a
                      transcript of the entire SMTP session to the
                      postmaster.
 
               <b>protocol</b>
-                     When  a client violates the SMTP protocol or
+                     When a client violates the SMTP protocol  or
                      issues  an  unimplemented  command,  mail  a
                      transcript of the entire SMTP session to the
                      postmaster.
 
        <b>smtpd_banner</b>
-              Text that follows the <b>220</b> status code in  the  SMTP
+              Text  that  follows the <b>220</b> status code in the SMTP
               greeting banner.
 
        <b>smtpd_expansion_filter</b>
@@ -233,57 +223,57 @@ SMTPD(8)                                                 SMTPD(8)
               expansion of rbl template responses and other text.
 
        <b>smtpd_recipient_limit</b>
-              Restrict  the  number  of  recipients that the SMTP
+              Restrict the number of  recipients  that  the  SMTP
               server accepts per message delivery.
 
        <b>smtpd_timeout</b>
-              Limit the time to send a  server  response  and  to
+              Limit  the  time  to  send a server response and to
               receive a client request.
 
        <b>soft_bounce</b>
-              Change  hard (5xx) reject responses into soft (4xx)
-              reject responses.  This can be useful  for  testing
+              Change hard (5xx) reject responses into soft  (4xx)
+              reject  responses.   This can be useful for testing
               purposes.
 
        <b>verp_delimiter_filter</b>
-              The  characters that Postfix accepts as VERP delim-
+              The characters that Postfix accepts as VERP  delim-
               iter characters.
 
 <b>Known versus unknown recipients</b>
        <b>show_user_unknown_table_name</b>
-              Whether or not to reveal  the  table  name  in  the
-              "User  unknown"  responses.  The extra detail makes
-              trouble shooting easier but also  reveals  informa-
+              Whether  or  not  to  reveal  the table name in the
+              "User unknown" responses. The  extra  detail  makes
+              trouble  shooting  easier but also reveals informa-
               tion that is nobody elses business.
 
        <b>unknown_local_recipient_reject_code</b>
               The response code when a client specifies a recipi-
-              ent  whose   domain   matches   <b>$mydestination</b>   or
+              ent   whose   domain   matches   <b>$mydestination</b>  or
               <b>$inet_interfaces</b>,  while  <b>$local_recipient_maps</b>  is
-              non-empty and does not list the  recipient  address
+              non-empty  and  does not list the recipient address
               or address local-part.
 
        <b>unknown_relay_recipient_reject_code</b>
               The response code when a client specifies a recipi-
               ent  whose  domain  matches  <b>$relay_domains</b>,  while
-              <b>$relay_recipient_maps</b>  is  non-empty  and  does not
+              <b>$relay_recipient_maps</b> is  non-empty  and  does  not
               list the recipient address.
 
        <b>unknown_virtual_alias_reject_code</b>
               The response code when a client specifies a recipi-
-              ent  whose  domain  matches <b>$virtual_alias_domains</b>,
-              while  the  recipient  is  not  listed   in   <b>$vir-</b>
+              ent whose  domain  matches  <b>$virtual_alias_domains</b>,
+              while   the   recipient  is  not  listed  in  <b>$vir-</b>
               <b>tual_alias_maps</b>.
 
        <b>unknown_virtual_mailbox_reject_code</b>
               The response code when a client specifies a recipi-
-              ent whose domain matches  <b>$virtual_mailbox_domains</b>,
+              ent  whose domain matches <b>$virtual_mailbox_domains</b>,
               while the recipient is not listed in <b>$virtual_mail-</b>
               <b>box_maps</b>.
 
 <b>Resource controls</b>
        <b>line_length_limit</b>
-              Limit the amount of memory in bytes  used  for  the
+              Limit  the  amount  of memory in bytes used for the
               handling of partial input lines.
 
        <b>message_size_limit</b>
@@ -291,9 +281,9 @@ SMTPD(8)                                                 SMTPD(8)
               ing on-disk storage for envelope information.
 
        <b>queue_minfree</b>
-              Minimal amount of free space in bytes in the  queue
-              file  system for the SMTP server to accept any mail
-              at  all  (default:  twice  the   <b>message_size_limit</b>
+              Minimal  amount of free space in bytes in the queue
+              file system for the SMTP server to accept any  mail
+              at   all  (default:  twice  the  <b>message_size_limit</b>
               value).
 
        <b>smtpd_history_flush_threshold</b>
@@ -303,21 +293,21 @@ SMTPD(8)                                                 SMTPD(8)
 
        <b>smtpd_client_connection_count_limit</b>
               The maximal number of simultaneous connections that
-              any client is allowed  to  make  to  this  service.
-              When  a  client  exceeds the limit, the SMTP server
+              any  client  is  allowed  to  make to this service.
+              When a client exceeds the limit,  the  SMTP  server
               logs a warning with the client name/address and the
               service name as configured in master.cf.
 
        <b>smtpd_client_connection_rate_limit</b>
-              The  maximal  number  of  connections per unit time
+              The maximal number of  connections  per  unit  time
               (specified with <b>connection_rate_time_unit</b>) that any
-              client  is  allowed to make to this service. When a
-              client exceeds the limit, the SMTP  server  logs  a
-              warning  with  the client name/address and the ser-
+              client is allowed to make to this service.  When  a
+              client  exceeds  the  limit, the SMTP server logs a
+              warning with the client name/address and  the  ser-
               vice name as configured in master.cf.
 
        <b>smtpd_client_connection_limit_exceptions</b>
-              Hostnames, .domain  names  and/or  network  address
+              Hostnames,  .domain  names  and/or  network address
               blocks of clients that are excluded from connection
               count or rate limits.
 
@@ -328,17 +318,17 @@ SMTPD(8)                                                 SMTPD(8)
 
        <b>smtpd_soft_error_limit</b>
               When an SMTP client has made this number of errors,
-              wait <i>error</i><b>_</b><i>count</i> seconds before responding  to  any
+              wait  <i>error</i><b>_</b><i>count</i>  seconds before responding to any
               client request.
 
        <b>smtpd_hard_error_limit</b>
-              Disconnect  after  a client has made this number of
+              Disconnect after a client has made this  number  of
               errors.
 
        <b>smtpd_junk_command_limit</b>
               Limit the number of times a client can issue a junk
-              command  such  as  NOOP,  VRFY, ETRN or RSET in one
-              SMTP session before it  is  penalized  with  tarpit
+              command such as NOOP, VRFY, ETRN  or  RSET  in  one
+              SMTP  session  before  it  is penalized with tarpit
               delays.
 
 <b>Delegated policy</b>
@@ -347,17 +337,17 @@ SMTPD(8)                                                 SMTPD(8)
               receiving from a delegated SMTPD policy server.
 
        <b>smtpd_policy_service_max_idle</b>
-              Time after which an  unused  SMTPD  policy  service
+              Time  after  which  an  unused SMTPD policy service
               connection is closed.
 
        <b>smtpd_policy_service_timeout</b>
-              Time  after  which  an  active SMTPD policy service
+              Time after which an  active  SMTPD  policy  service
               connection is closed.
 
 <b>UCE control restrictions</b>
        <b>parent_domain_matches_subdomains</b>
-              List of Postfix features that use  <i>domain.tld</i>  pat-
-              terns   to  match  <i>sub.domain.tld</i>  (as  opposed  to
+              List  of  Postfix features that use <i>domain.tld</i> pat-
+              terns  to  match  <i>sub.domain.tld</i>  (as  opposed   to
               requiring <i>.domain.tld</i> patterns).
 
        <b>smtpd_client_restrictions</b>
@@ -365,19 +355,19 @@ SMTPD(8)                                                 SMTPD(8)
               tem.
 
        <b>smtpd_helo_required</b>
-              Require  that  clients  introduce themselves at the
+              Require that clients introduce  themselves  at  the
               beginning of an SMTP session.
 
        <b>smtpd_helo_restrictions</b>
-              Restrict what client hostnames are allowed in  <b>HELO</b>
+              Restrict  what client hostnames are allowed in <b>HELO</b>
               and <b>EHLO</b> commands.
 
        <b>smtpd_sender_restrictions</b>
-              Restrict  what sender addresses are allowed in <b>MAIL</b>
+              Restrict what sender addresses are allowed in  <b>MAIL</b>
               <b>FROM</b> commands.
 
        <b>smtpd_recipient_restrictions</b>
-              Restrict what recipient addresses  are  allowed  in
+              Restrict  what  recipient  addresses are allowed in
               <b>RCPT TO</b> commands.
 
        <b>smtpd_etrn_restrictions</b>
@@ -385,96 +375,96 @@ SMTPD(8)                                                 SMTPD(8)
               mands, and what clients may issue <b>ETRN</b> commands.
 
        <b>smtpd_data_restrictions</b>
-              Restrictions on the <b>DATA</b>  command.  Currently,  the
-              only   restriction   that   makes   sense  here  is
+              Restrictions  on  the  <b>DATA</b> command. Currently, the
+              only  restriction  that   makes   sense   here   is
               <b>reject_unauth_pipelining</b>.
 
        <b>allow_untrusted_routing</b>
-              Allow untrusted clients to specify  addresses  with
-              sender-specified  routing.   Enabling this opens up
-              nasty relay loopholes involving trusted  backup  MX
+              Allow  untrusted  clients to specify addresses with
+              sender-specified routing.  Enabling this  opens  up
+              nasty  relay  loopholes involving trusted backup MX
               hosts.
 
        <b>smtpd_restriction_classes</b>
-              Declares  the  name of zero or more parameters that
-              contain a list of UCE restrictions.  The  names  of
-              these  parameters  can  then be used instead of the
+              Declares the name of zero or more  parameters  that
+              contain  a  list  of UCE restrictions. The names of
+              these parameters can then be used  instead  of  the
               restriction lists that they represent.
 
        <b>smtpd_null_access_lookup_key</b>
-              The lookup key to be used in  SMTPD  access  tables
-              instead  of  the null sender address. A null sender
+              The  lookup  key  to be used in SMTPD access tables
+              instead of the null sender address. A  null  sender
               address cannot be looked up.
 
        <b>maps_rbl_domains</b> (deprecated)
-              List of DNS domains that publish the  addresses  of
+              List  of  DNS domains that publish the addresses of
               blacklisted hosts. This is used with the deprecated
               <b>reject_maps_rbl</b> restriction.
 
        <b>permit_mx_backup_networks</b>
-              Only domains  whose  primary  MX  hosts  match  the
-              listed   networks   are   eligible   for  the  <b>per-</b>
+              Only  domains  whose  primary  MX  hosts  match the
+              listed  networks  are   eligible   for   the   <b>per-</b>
               <b>mit_mx_backup</b> feature.
 
        <b>relay_domains</b>
-              Restrict what domains this mail system  will  relay
-              mail  to.  The  domains  are routed to the delivery
+              Restrict  what  domains this mail system will relay
+              mail to. The domains are  routed  to  the  delivery
               agent specified with the <b>relay_transport</b> setting.
 
 <b>Sender/recipient address verification</b>
        Address verification is implemented by sending probe email
-       messages  that  are not actually delivered, and is enabled
-       via   the   reject_unverified_{sender,recipient}    access
-       restriction.   The  status of verification probes is main-
+       messages that are not actually delivered, and  is  enabled
+       via    the   reject_unverified_{sender,recipient}   access
+       restriction.  The status of verification probes  is  main-
        tained by the address verification service.
 
        <b>address_verify_poll_count</b>
-              How many times to query  the  address  verification
-              service  for  completion of an address verification
-              request.  Specify 1 to implement a simple  form  of
-              greylisting,  that is, always defer the request for
+              How  many  times  to query the address verification
+              service for completion of an  address  verification
+              request.   Specify  1 to implement a simple form of
+              greylisting, that is, always defer the request  for
               a new sender or recipient address.
 
        <b>address_verify_poll_delay</b>
-              Time to wait after querying the  address  verifica-
+              Time  to  wait after querying the address verifica-
               tion service for completion of an address verifica-
               tion request.
 
 <b>UCE control responses</b>
        <b>access_map_reject_code</b>
-              Response code when  a  client  violates  an  access
+              Response  code  when  a  client  violates an access
               database restriction.
 
        <b>default_rbl_reply</b>
               Default template reply when a request is RBL black-
-              listed.  This template is used by the  <b>reject_rbl_*</b>
-              and    <b>reject_rhsbl_*</b>   restrictions.   See   also:
+              listed.   This template is used by the <b>reject_rbl_*</b>
+              and   <b>reject_rhsbl_*</b>   restrictions.   See    also:
               <b>rbl_reply_maps</b> and <b>smtpd_expansion_filter</b>.
 
        <b>defer_code</b>
-              Response code when a client request is rejected  by
+              Response  code when a client request is rejected by
               the <b>defer</b> restriction.
 
        <b>invalid_hostname_reject_code</b>
-              Response   code   when   a   client   violates  the
+              Response  code   when   a   client   violates   the
               <b>reject_invalid_hostname</b> restriction.
 
        <b>maps_rbl_reject_code</b>
               Response code when a request is RBL blacklisted.
 
        <b>multi_recipient_bounce_reject_code</b>
-              Response code  when  a  multi-recipient  bounce  is
+              Response  code  when  a  multi-recipient  bounce is
               blocked.
 
        <b>rbl_reply_maps</b>
-              Table  with  template responses for RBL blacklisted
-              requests, indexed by RBL domain  name.  These  tem-
+              Table with template responses for  RBL  blacklisted
+              requests,  indexed  by  RBL domain name. These tem-
               plates   are   used   by   the   <b>reject_rbl_*</b>   and
-              <b>reject_rhsbl_*</b>     restrictions.     See      also:
+              <b>reject_rhsbl_*</b>      restrictions.     See     also:
               <b>default_rbl_reply</b> and <b>smtpd_expansion_filter</b>.
 
        <b>reject_code</b>
-              Response  code  when  the  client  matches a <b>reject</b>
+              Response code when  the  client  matches  a  <b>reject</b>
               restriction.
 
        <b>relay_domains_reject_code</b>
@@ -482,7 +472,7 @@ SMTPD(8)                                                 SMTPD(8)
               mail relay policy.
 
        <b>unknown_address_reject_code</b>
-              Response   code   when   a   client   violates  the
+              Response  code   when   a   client   violates   the
               <b>reject_unknown_address</b> restriction.
 
        <b>unknown_client_reject_code</b>
@@ -491,15 +481,15 @@ SMTPD(8)                                                 SMTPD(8)
               tion.
 
        <b>unknown_hostname_reject_code</b>
-              Response  code   when   a   client   violates   the
+              Response   code   when   a   client   violates  the
               <b>reject_unknown_hostname</b> restriction.
 
        <b>unverified_sender_reject_code</b>
-              Response  code when a sender address is known to be
+              Response code when a sender address is known to  be
               undeliverable.
 
        <b>unverified_recipient_reject_code</b>
-              Response code when a recipient address is known  to
+              Response  code when a recipient address is known to
               be undeliverable.
 
 <b>SEE ALSO</b>
@@ -510,7 +500,7 @@ SMTPD(8)                                                 SMTPD(8)
        <a href="verify.8.html">verify(8)</a> address verification service
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 0827f00e3c2b8853c875c7af039c2bb1ea4c42bc..1d0d2f4284d35476e4dc42d9a93c31540eeb7767 100644 (file)
@@ -6,7 +6,7 @@
 # SUMMARY
 #      makefile configuration utility
 # SYNOPSIS
-#      \fBmakedefs\fR
+#      \fBmake makefiles \fIname=value...\fR
 # DESCRIPTION
 #      The \fBmakedefs\fR command identifies the program compilation
 #      environment, and emits macro definitions on the standard output
@@ -29,6 +29,9 @@
 # .IP \fBOPT=\fIoptimization_level\fR
 #      Specifies a non-default optimization level. The default is \fB-O\fR.
 #      Specify \fBOPT=\fR to turn off optimization.
+# .IP \fBWARN=\fIwarning_flags\fR
+#      Specifies non-default gcc compiler warning options for use when
+#      "make" is invoked in a source subdirectory only.
 # LICENSE
 # .ad
 # .fi
@@ -320,7 +323,10 @@ case "$CC" in
         *) : ${OPT='-O'};;
 esac
 
-: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
+: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk} \
+${WARN='-W -Wformat -Wimplicit -Wmissing-prototypes \
+       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+       -Wunused'}
 
 export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
 
@@ -336,4 +342,5 @@ DEBUG       = $DEBUG
 AWK    = $AWK
 STRCASE = $STRCASE
 EXPORT = AUXLIBS='$AUXLIBS' CCARGS='$CCARGS' OPT='$OPT' DEBUG='$DEBUG'
+WARN   = $WARN
 EOF
index 4d5495fcf31543363314f7e041b74317d18fd6b0..c585f4945e73cd394b13b6cc6438157f31a6b383 100644 (file)
@@ -210,6 +210,9 @@ exchanger list.
 .IP \fBsmtp_helo_timeout\fR
 Timeout for sending the \fBHELO\fR command, and for
 receiving the server response.
+.IP \fBsmtp_xclient_timeout\fR
+Timeout for sending the \fBXCLIENT\fR command, and for
+receiving the server response.
 .IP \fBsmtp_mail_timeout\fR
 Timeout for sending the \fBMAIL FROM\fR command, and for
 receiving the server response.
@@ -231,6 +234,11 @@ If no, bounce mail when no MX host resolves to an address
 than the local MTA).
 If yes, keep trying until a suitable MX host resolves or until
 the mail is too old.
+.IP \fBsmtp_send_xclient_command\fR
+If the SMTP server announces XCLIENT support, send the name,
+address, protocol and HELO name of the original client. This
+can be used to forward client information through a content
+filter to a downstream queuing SMTP server.
 .IP \fBsmtp_rset_timeout\fR
 Timeout for sending the \fBRSET\fR command.
 .IP \fBsmtp_quit_timeout\fR
index a93f533bae19decb289fba4f24d41789411af08f..f4466b7b6c141601422df2023e3bf88c6ede9f3e 100644 (file)
@@ -157,20 +157,12 @@ anti-spoofing restriction.
 .IP \fBsmtpd_authorized_verp_clients\fR
 Hostnames, domain names and/or addresses of clients that are
 authorized to use the XVERP extension.
-.IP \fBsmtpd_authorized_xaddr_clients\fR
+.IP \fBsmtpd_authorized_xclient_hosts\fR
 Hostnames, domain names and/or addresses of clients that are
-authorized to use the "XADDR client-address client-name" command.
-This changes Postfix's
-idea of the SMTP client IP address and hostname for access
-control and for logging purposes.
-.IP \fBsmtpd_authorized_xloginfo_clients\fR
-Hostnames, domain names and/or addresses of clients that are
-authorized to use the "XLOGINFO client-address client-name" command.
-This changes the client
-name and address that are used for logging, without affecting the
-client IP address and hostname that are used for access control.
-XLOGINFO is typically used to propagate remote client information
-through an SMTP-based content filter to the after-filter SMTP server.
+authorized to use the XCLIENT command.  This command changes
+client information for access control and/or logging purposes,
+with the exception of the
+\fBsmtpd_authorized_xclient_hosts\fR access control itself.
 .IP \fBdebug_peer_level\fR
 Increment in verbose logging level when a remote host matches a
 pattern in the \fBdebug_peer_list\fR parameter.
index 7f4ea06b1a0c406126265450196ba2706a5778c2..189f14ec000b81b2d3a86299fb4138d8e7518bc8 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = anvil.c
 OBJS   = anvil.o
 HDRS   = 
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index abd9067b9b6a80e55c913b937eb1c2da7780a37c..6a3f352b3f9a4d888d2170c3669de0415a1ddba3 100644 (file)
@@ -7,9 +7,6 @@ OBJS    = bounce.o bounce_append_service.o bounce_notify_service.o \
        bounce_one_service.o bounce_warn_service.o bounce_trace_service.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index 8eb9a8807cacdd5d819242c72340829adc0ea90b..c390e5ae00fbfdf1ab9b2a7f27ec8df6a2369daa 100644 (file)
@@ -11,9 +11,6 @@ OBJS  = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
        cleanup_addr.o
 HDRS   =
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= cleanup_masquerade
index 9948582e7124d2c5b4d8846f71f77a2989c51470..c96f672565efcaa7fa7f8ea19cc804c616d9315b 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c
 OBJS   = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o
 HDRS   = dns.h
 TESTSRC        = test_dns_lookup.c test_alias_token.c
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused 
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 INCL   =
index 4ba674db5f107a6ebf0a60a0da2a09a210acd332..a6559a48bdd51f83666a18392f90f9901294891f 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = error.c
 OBJS   = error.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index 266254d9103e2693d4a2df69490eb858d13ef157..4708bb12cb0fdf9e09f51439f55a738e9da04118 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = flush.c
 OBJS   = flush.o
 HDRS   = 
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index e5f76b76f9b60b9260dce0b26f163b97a7daf8f1..d22b4bc554f1fb380f13b6cd1a7dcf5dce36cd04 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = fsstone.c
 OBJS   = fsstone.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index c6da6f946d54861e890a93bd780034e9ac748e0d..dc95fda3337003e58b79006585ce49027dd92b63 100644 (file)
@@ -68,9 +68,6 @@ HDRS  = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
        trace.h log_adhoc.h verify.h dict_proxy.h mail_dict.h qmgr_user.h \
        input_transp.h anvil_clnt.h
 TESTSRC        = rec2stream.c stream2rec.c recdump.c
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 INCL   =
index 08a95f32601ae56b25600665db66f67275472181..1ad6defb26625b8962b065398fcd93d261e77598 100644 (file)
 /*             long arrival_time;
 /*             RECIPIENT_LIST rcpt_list;
 /*             char    *hop_status;
+/*             char    *client_name;
+/*             char    *client_addr;
+/*             char    *client_proto;
+/*             char    *client_helo;
 /* .in -5
 /*     } DELIVER_REQUEST;
 /*
@@ -175,6 +179,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     static VSTRING *address;
     static VSTRING *errors_to;
     static VSTRING *return_receipt;
+    static VSTRING *client_name;
+    static VSTRING *client_addr;
+    static VSTRING *client_proto;
+    static VSTRING *client_helo;
     long    offset;
 
     /*
@@ -191,6 +199,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
        address = vstring_alloc(10);
        errors_to = vstring_alloc(10);
        return_receipt = vstring_alloc(10);
+       client_name = vstring_alloc(10);
+       client_addr = vstring_alloc(10);
+       client_proto = vstring_alloc(10);
+       client_helo = vstring_alloc(10);
     }
 
     /*
@@ -209,7 +221,11 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
                  ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to,
                  ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt,
                  ATTR_TYPE_LONG, MAIL_ATTR_TIME, &request->arrival_time,
-                 ATTR_TYPE_END) != 11) {
+                 ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, client_name,
+                 ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, client_addr,
+                 ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, client_proto,
+                 ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, client_helo,
+                 ATTR_TYPE_END) != 15) {
        msg_warn("%s: error receiving common attributes", myname);
        return (-1);
     }
@@ -224,6 +240,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     request->sender = mystrdup(vstring_str(address));
     request->errors_to = mystrdup(vstring_str(errors_to));
     request->return_receipt = mystrdup(vstring_str(return_receipt));
+    request->client_name = mystrdup(vstring_str(client_name));
+    request->client_addr = mystrdup(vstring_str(client_addr));
+    request->client_proto = mystrdup(vstring_str(client_proto));
+    request->client_helo = mystrdup(vstring_str(client_helo));
 
     /*
      * Extract the recipient offset and address list. Skip over any
@@ -298,6 +318,10 @@ static DELIVER_REQUEST *deliver_request_alloc(void)
     request->data_size = 0;
     recipient_list_init(&request->rcpt_list);
     request->hop_status = 0;
+    request->client_name = 0;
+    request->client_addr = 0;
+    request->client_proto = 0;
+    request->client_helo = 0;
     return (request);
 }
 
@@ -324,6 +348,14 @@ static void deliver_request_free(DELIVER_REQUEST *request)
     recipient_list_free(&request->rcpt_list);
     if (request->hop_status)
        myfree(request->hop_status);
+    if (request->client_name)
+       myfree(request->client_name);
+    if (request->client_addr)
+       myfree(request->client_addr);
+    if (request->client_proto)
+       myfree(request->client_proto);
+    if (request->client_helo)
+       myfree(request->client_helo);
     myfree((char *) request);
 }
 
index 124204a60a761f93c436ed708d992be2697eecfa..2264a28d702410865a0a479aa841722db66f23a0 100644 (file)
@@ -40,6 +40,10 @@ typedef struct DELIVER_REQUEST {
     long    arrival_time;              /* arrival time */
     RECIPIENT_LIST rcpt_list;          /* envelope recipients */
     char   *hop_status;                        /* reason if unavailable */
+    char   *client_name;               /* client hostname */
+    char   *client_addr;               /* client address */
+    char   *client_proto;              /* client protocol */
+    char   *client_helo;               /* helo parameter */
 } DELIVER_REQUEST;
 
 #define DEL_REQ_FLAG_DEFLT     (DEL_REQ_FLAG_SUCCESS | DEL_REQ_FLAG_BOUNCE)
index b41f969c7db41da7581e1c3ad853182d3cbaa6d5..260e61ecfba32f4e9f1801d8f5a31fcb2ca35ffe 100644 (file)
@@ -753,6 +753,10 @@ extern int var_smtp_conn_tmout;
 #define DEF_SMTP_HELO_TMOUT    "300s"
 extern int var_smtp_helo_tmout;
 
+#define VAR_SMTP_XCLNT_TMOUT   "smtp_xclient_timeout"
+#define DEF_SMTP_XCLNT_TMOUT   "300s"
+extern int var_smtp_xclnt_tmout;
+
 #define VAR_SMTP_MAIL_TMOUT    "smtp_mail_timeout"
 #define DEF_SMTP_MAIL_TMOUT    "300s"
 extern int var_smtp_mail_tmout;
@@ -841,6 +845,10 @@ extern int var_smtp_pix_delay;
 #define DEF_SMTP_DEFER_MXADDR  0
 extern bool var_smtp_defer_mxaddr;
 
+#define VAR_SMTP_SEND_XCLIENT  "smtp_send_xclient_command"
+#define DEF_SMTP_SEND_XCLIENT  0
+extern bool var_smtp_send_xclient;
+
  /*
   * SMTP server. The soft error limit determines how many errors an SMTP
   * client may make before we start to slow down; the hard error limit
@@ -1567,15 +1575,11 @@ extern bool var_verp_bounce_off;
 extern char *var_verp_clients;
 
  /*
-  * XADDR.
+  * XCLIENT, for rule testing and improved post-filter logging.
   */
-#define VAR_XADDR_CLIENTS              "smtpd_authorized_xaddr_clients"
-#define DEF_XADDR_CLIENTS              ""
-extern char *var_xaddr_clients;
-
-#define VAR_XLOGINFO_CLIENTS           "smtpd_authorized_xloginfo_clients"
-#define DEF_XLOGINFO_CLIENTS           ""
-extern char *var_xloginfo_clients;
+#define VAR_XCLIENT_HOSTS              "smtpd_authorized_xclient_hosts"
+#define DEF_XCLIENT_HOSTS              ""
+extern char *var_xclient_hosts;
 
  /*
   * Inbound mail flow control. This allows for a stiffer coupling between
index 04ad9bda428d8581163f62a736a0fe0777e25d4e..10718cfd1b5f29192fcfc98161b7b6b081258b27 100644 (file)
@@ -15,6 +15,7 @@
   * System library.
   */
 #include <stdarg.h>
+#include <string.h>
 
  /*
   * Utility library.
@@ -150,6 +151,24 @@ extern char *mail_pathname(const char *, const char *);
 #define MAIL_ATTR_ORG_NONE     "unknown"       /* origin unknown */
 #define MAIL_ATTR_ORG_LOCAL    "local" /* local submission */
 
+ /*
+  * Internal forms for unknown XCLIENT information.
+  */
+#define CLIENT_NAME_UNKNOWN    "unknown"
+#define CLIENT_ADDR_UNKNOWN    "unknown"
+#define CLIENT_NAMADDR_UNKNOWN CLIENT_NAME_UNKNOWN "[" CLIENT_ADDR_UNKNOWN "]"
+#define HELO_NAME_UNKNOWN      ""      /* or NULL */
+#define PROTOCOL_UNKNOWN       "unknown"
+
+ /*
+  * Internal forms: recognizing unknown XCLIENT information.
+  */
+#define IS_UNK_CLNT_NAME(v)    (!(v) || !strcmp((v), CLIENT_NAME_UNKNOWN))
+#define IS_UNK_CLNT_ADDR(v)    (!(v) || !strcmp((v), CLIENT_ADDR_UNKNOWN))
+#define IS_UNK_CLNT_NAMADDR(v) (!(v) || !strcmp((v), CLIENT_NAMADDR_UNKNOWN))
+#define IS_UNK_HELO_NAME(v)    (!(v) || !*(v))
+#define IS_UNK_PROTOCOL(v)     (!(v) || !strcmp((v), PROTOCOL_UNKNOWN))
+
 /* LICENSE
 /* .ad
 /* .fi
index 094cb00b05c1ba3c37b84836b83ba425af4038d7..19c82291148c9979e03d4befc1823c2f31b5584b 100644 (file)
@@ -84,6 +84,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <utime.h>
+#include <string.h>
 
 /* Utility library. */
 
index 6b0b71f10942d5f4bacce3378772995dd4728901..ce00d7d18f7150a7c2cf7de8b91dd8921477fcaf 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only, unless they include the same bugfix as a patch release.
   */
-#define MAIL_RELEASE_DATE      "20031113"
+#define MAIL_RELEASE_DATE      "20031128"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "2.0.16-" MAIL_RELEASE_DATE
index eb7bfc4ba9422272f3a31a5681b77c2ad50acffe..5c9630d354ad4eebd9b3081a535bdf38800fe27b 100644 (file)
@@ -387,7 +387,7 @@ static MIME_ENCODING mime_encoding_map[] = {        /* RFC 2045 */
   * Outputs and state changes are interleaved, so we must maintain separate
   * offsets for header and body segments.
   */
-#define HEAD_OUT(ptr, info) do { \
+#define HEAD_OUT(ptr, info, len) do { \
        (ptr)->head_out((ptr)->app_context, (ptr)->curr_state, \
                        (info), (ptr)->output_buffer, (ptr)->head_offset); \
        (ptr)->head_offset += (len) + 1; \
@@ -805,7 +805,7 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
                    || header_info->type != HDR_CONTENT_TRANSFER_ENCODING
                    || (state->static_flags & MIME_OPT_DOWNGRADE) == 0
                    || state->curr_domain == MIME_ENC_7BIT)
-                   HEAD_OUT(state, header_info);
+                   HEAD_OUT(state, header_info, len);
                state->prev_rec_type = 0;
                VSTRING_RESET(state->output_buffer);
            }
@@ -855,7 +855,7 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
                cp = CU_CHAR_PTR("quoted-printable");
            vstring_sprintf(state->output_buffer,
                            "Content-Transfer-Encoding: %s", cp);
-           HEAD_OUT(state, (HEADER_OPTS *) 0);
+           HEAD_OUT(state, (HEADER_OPTS *) 0, len);
            VSTRING_RESET(state->output_buffer);
        }
 
index 4a20c7ceee2e3fffc5f3d99b2ee8ceed91b80413..1eaca0eec62a8c34047bbacf8bc85ef6a4131924 100644 (file)
@@ -182,6 +182,7 @@ VSTRING *rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *r
 #include <stdlib.h>
 #include <string.h>
 #include <msg_vstream.h>
+#include <split_at.h>
 #include <vstring_vstream.h>
 #include <mail_conf.h>
 #include <mail_params.h>
@@ -237,8 +238,8 @@ int     main(int argc, char **argv)
        VSTRING *buffer = vstring_alloc(1);
 
        while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
-           if ((rule = strtok(STR(buffer), " \t,")) == 0
-               || (addr = strtok((char *) 0, " \t,")) == 0)
+           if ((addr = split_at(STR(buffer), ' ')) == 0
+               || *(rule = STR(buffer)) == 0)
                usage(argv[0]);
            rewrite(rule, addr, reply);
        }
index 14806e46e7cc783912dee0fef579c9c73ab4576b..959dd1aefc7ee2a50f86d21fd9a57b02e79338ac 100644 (file)
@@ -2,7 +2,7 @@
 /* NAME
 /*     xtext 3
 /* SUMMARY
-/*     quote/unquote text, HTTP style.
+/*     quote/unquote text, xtext style.
 /* SYNOPSIS
 /*     #include <xtext.h>
 /*
 /*     const char *unquoted;
 /*     const char *special;
 /*
+/*     VSTRING *xtext_unquote_append(unquoted, quoted)
+/*     VSTRING *unquoted;
+/*     const char *quoted;
+/*
 /*     VSTRING *xtext_unquote(unquoted, quoted)
 /*     VSTRING *unquoted;
 /*     const char *quoted;
@@ -19,6 +23,9 @@
 /*     +, <33(10) and >126(10), as well as characters specified with "special"
 /*     by +XX, XX being the two-digit uppercase hexadecimal equivalent.
 /*
+/*     xtext_quote_append() is like xtext_quote(), but appends the conversion
+/*     result to the result buffer.
+/*
 /*     xtext_unquote() performs the opposite transformation. This function
 /*     understands lowercase, uppercase, and mixed case +XX sequences. The
 /*     result value is the unquoted argument in case of success, a null pointer
 #define STR(x) vstring_str(x)
 #define LEN(x) VSTRING_LEN(x)
 
-/* xtext_quote - unquoted data to quoted */
+/* xtext_quote_append - append unquoted data to quoted data */
 
-VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
+VSTRING *xtext_quote_append(VSTRING *quoted, const char *unquoted,
+                                   const char *special)
 {
     const char *cp;
     int     ch;
 
-    VSTRING_RESET(quoted);
     for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) {
-       if (ch != '+' && ch > 32 && ch < 127 && strchr(special, ch) == 0) {
+       if (ch != '+' && ch > 32 && ch < 127
+           && (*special == 0 || strchr(special, ch) == 0)) {
            VSTRING_ADDCH(quoted, ch);
        } else {
            vstring_sprintf_append(quoted, "+%02X", ch);
@@ -72,6 +80,15 @@ VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
     return (quoted);
 }
 
+/* xtext_quote - unquoted data to quoted */
+
+VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
+{
+    VSTRING_RESET(quoted);
+    xtext_quote_append(quoted, unquoted, special);
+    return (quoted);
+}
+
 /* xtext_unquote - quoted data to unquoted */
 
 VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted)
index 8b924c6bcea68bb58002ad298800ca287d1020f4..1515242d32ada4d7f57e349cdd3bcc6f723f3112 100644 (file)
 
  /*
   * Utility library.
- */
 */
 #include <vstring.h>
 
  /*
   * External interface.
   */
 extern VSTRING *xtext_quote(VSTRING *, const char *, const char *);
+extern VSTRING *xtext_quote_append(VSTRING *, const char *, const char *);
 extern VSTRING *xtext_unquote(VSTRING *, const char *);
 
 /* LICENSE
index 4b86772e8ade2a21bf62f28eb8aa60b81cf1011c..baf5db8d4a10b4972bf6dd0f6fc3f6da4c0b3655 100644 (file)
@@ -7,9 +7,6 @@ OBJS    = lmtp.o lmtp_connect.o lmtp_proto.o lmtp_chat.o lmtp_session.o \
        lmtp_sasl_proto.o
 HDRS   = lmtp.h
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index 038e81edcfddbf4d1ecebc1ef87594978051011f..28dc05001daffea08698522a5cad554289c60579 100644 (file)
@@ -9,9 +9,6 @@ OBJS    = alias.o command.o delivered.o dotforward.o file.o forward.o \
        local_expand.o
 HDRS   = local.h
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 PROG   = local
index eeb2ce986dd059f3690fd21ed27b83b768a68d0d..3bca0e03d00ca5549d77af7bd42bd656843af8f7 100644 (file)
@@ -10,9 +10,6 @@ LIB_OBJ       = single_server.o multi_server.o trigger_server.o master_proto.o \
        mail_flow.o
 HDRS   = mail_server.h master_proto.h mail_flow.h
 INT_HDR        = master.h
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 LIB    = libmaster.a
index 11ff16cc94bcd161cea417724155fd8c1911b305..8c22bb91c952709b43f338b1c8940d47f434784b 100644 (file)
@@ -303,7 +303,9 @@ MASTER_SERV *get_master_ent()
            MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
                mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
            inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
-           inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
+           if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
+               msg_fatal("%s: line %d: bad hostname or network address: %s",
+                         VSTREAM_PATH(master_fp), master_line, host);
            inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
            serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
        } else if (strcasecmp(saved_interfaces, DEF_INET_INTERFACES) == 0) {
index c5f6254e7e1d24ee6136511944bb93ff7046a3ab..35f34f1eea0226f0f4ae64128b1272bdaa5ed33c 100644 (file)
@@ -9,9 +9,6 @@ OBJS    = qmgr.o qmgr_active.o qmgr_transport.o qmgr_queue.o qmgr_entry.o \
        qmgr_defer.o qmgr_enable.o qmgr_scan.o qmgr_bounce.o
 HDRS   = qmgr.h
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index e3fbd9ac0c90bd651a23c5e57d52e5361ff146eb..8a8f5a92572c28ea9c406b05c9f68db10356119b 100644 (file)
@@ -276,6 +276,10 @@ struct QMGR_MESSAGE {
     char   *redirect_addr;             /* info@spammer.tld */
     long    data_size;                 /* message content size */
     long    rcpt_offset;               /* more recipients here */
+    char   *client_name;               /* client hostname */
+    char   *client_addr;               /* client address */
+    char   *client_proto;              /* client protocol */
+    char   *client_helo;               /* helo parameter */
     QMGR_RCPT_LIST rcpt_list;          /* complete addresses */
     int     rcpt_count;                        /* used recipient slots */
     int     rcpt_limit;                        /* maximum read in-core */
index 67f574253dd35015aca98a064946d19d0fec0451..198bd44920efa7aaac7f481d8610032feaf092f6 100644 (file)
@@ -489,8 +489,9 @@ static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
                          message->queue_id, message->queue_name);
            msg_warn("%s: remove %s from %s: %m", myname,
                     message->queue_id, message->queue_name);
-       } else if (msg_verbose) {
-           msg_info("%s: remove %s", myname, message->queue_id);
+       } else {
+           /* Same format as logged by postsuper. */
+           msg_info("%s: removed", message->queue_id);
        }
     }
 
index 3f7e78bb5d306a0c5ffb14028b40f413ab2a0c40..cfdf635ff99c635a4d81e7019769574b5317632f 100644 (file)
@@ -161,6 +161,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
               ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
               ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time,
+              ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name,
+              ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
+              ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
+              ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
               ATTR_TYPE_END);
     if (sender_buf != 0)
        vstring_free(sender_buf);
index b2951133c066d5c51ab6603bc4724a19e51eba22..1dc1e410e5ea29325e3c6974eb76449ed856495e 100644 (file)
@@ -168,6 +168,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->warn_time = 0;
     message->rcpt_offset = 0;
     message->verp_delims = 0;
+    message->client_name = 0;
+    message->client_addr = 0;
+    message->client_proto = 0;
+    message->client_helo = 0;
     qmgr_rcpt_list_init(&message->rcpt_list);
     message->rcpt_count = 0;
     message->rcpt_limit = var_qmgr_msg_rcpt_limit;
@@ -525,6 +529,27 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    myfree(message->encoding);
                message->encoding = mystrdup(value);
            }
+           /* Original client attributes. */
+           if (strcmp(name, MAIL_ATTR_CLIENT_NAME) == 0) {
+               if (message->client_name != 0)
+                   myfree(message->client_name);
+               message->client_name = mystrdup(value);
+           }
+           if (strcmp(name, MAIL_ATTR_CLIENT_ADDR) == 0) {
+               if (message->client_addr != 0)
+                   myfree(message->client_addr);
+               message->client_addr = mystrdup(value);
+           }
+           if (strcmp(name, MAIL_ATTR_PROTO_NAME) == 0) {
+               if (message->client_proto != 0)
+                   myfree(message->client_proto);
+               message->client_proto = mystrdup(value);
+           }
+           if (strcmp(name, MAIL_ATTR_HELO_NAME) == 0) {
+               if (message->client_helo != 0)
+                   myfree(message->client_helo);
+               message->client_helo = mystrdup(value);
+           }
            /* Optional tracing flags. */
            else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
                message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@@ -586,6 +611,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        message->return_receipt = mystrdup("");
     if (message->encoding == 0)
        message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
+    if (message->client_name == 0)
+       message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
+    if (message->client_addr == 0)
+       message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+    if (message->client_proto == 0)
+       message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
+    if (message->client_helo == 0)
+       message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
 
     /*
      * Clean up.
index 44847920d4f8d59279a91aead80aaf3f5f6d9d0e..c007503af0dc27f858bc4510a8c17e6570e4b94c 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = pickup.c
 OBJS   = pickup.o
 HDRS   = 
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 7f0c13f38e2d4b487269ed6448069d813aa45643..d1063fcb24c8be6b9772e0a907502d70e8f82bbf 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = pipe.c
 OBJS   = pipe.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index acb8e86b9823428541d13bd4a692645e678abac7..702551a52863040062566eaba112f08bbdd6c4f8 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postalias.c
 OBJS   = postalias.o 
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index dca6108806e3c0a6c5375b0ea3290c5043d584f6..e1ba3bdc9aa5d6626e735f416e050165af726ea6 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postcat.c
 OBJS   = postcat.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 198be229e750908fff0cba8e4d6ff5ace7b3aa8a..6597e31ce97ec3e89aab9111da9d4017d554a78c 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postconf.c
 OBJS   = postconf.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 846e70fde01f240b6dbe7fcb725cec664560f77e..cb914ad96b28dfc80fe381ea8157604e3cd53c0e 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postdrop.c
 OBJS   = postdrop.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index bd1e8f5e30d5aba190f9121547a0ae71687d3985..ac53549d39713c753552f5ff4b3b5b105cf1403a 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postfix.c
 OBJS   = postfix.o 
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 FILES  = Makefile $(SRCS) $(HDRS)
index ce8b4a4858526b5735f72d03a3f9b9332bbfdda5..38c0fba9a09051acc20c8c19b1bddfabb81978d6 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postkick.c
 OBJS   = postkick.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index 3e95260c39cfea2cb5594272083dc2f851dfa4c1..4e4ea3ad0549327df26babaac651fcbfb00d98d7 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postlock.c
 OBJS   = postlock.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index 5feba3056cde5a95ec98dca5d6991008759ec1fc..8e57470ac512d3e2eb2cd1cffe5017273cff6263 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postlog.c
 OBJS   = postlog.o 
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 FILES  = Makefile $(SRCS) $(HDRS)
index 5dbb4ccfe3b535485f180a3d1c1b003a04a5c9a8..21cf87be5fcd9845dc3ed9ddf79dc636d2ed9769 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postmap.c
 OBJS   = postmap.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 29ba1bff45b6a2f2a68abba2632564f09a24dd8a..ba9e66f163834e32fe37f9df77d6713f29d7de57 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postqueue.c
 OBJS   = postqueue.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index aacc1841a1b0c7c601ace6ea59f2d14cc1b17969..1b9d8079d9a51c0598c61c4ff401465f0f2d830d 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = postsuper.c
 OBJS   = postsuper.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 91d20d8384fee5977819fb4a05cd1000e2d7df7d..e42f4389c6500c2f54ad50f37c75b90033a1b518 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = proxymap.c
 OBJS   = proxymap.o
 HDRS   = 
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 06ead63742123b3f913d2f7b9d12e355f49d332f..a640af3dc71281d57ae5529e0e8516ab55d4417d 100644 (file)
@@ -7,9 +7,6 @@ OBJS    = qmgr.o qmgr_active.o qmgr_transport.o qmgr_queue.o qmgr_entry.o \
        qmgr_defer.o qmgr_enable.o qmgr_scan.o qmgr_bounce.o
 HDRS   = qmgr.h
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 6386397143e958d40e7c280db63aa881b6ced7ec..2981b4b544e72919535c342fcdabdc7e8dd4d7c9 100644 (file)
@@ -236,6 +236,10 @@ struct QMGR_MESSAGE {
     char   *redirect_addr;             /* info@spammer.tld */
     long    data_size;                 /* message content size */
     long    rcpt_offset;               /* more recipients here */
+    char   *client_name;               /* client hostname */
+    char   *client_addr;               /* client address */
+    char   *client_proto;              /* client protocol */
+    char   *client_helo;               /* helo parameter */
     QMGR_RCPT_LIST rcpt_list;          /* complete addresses */
 };
 
index 3e25b6323e810dba20fa6b3b60a5641b51ec4f0b..6d4a248c194a820962a979b84d89e4c7695290ea 100644 (file)
@@ -489,8 +489,9 @@ static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
                          message->queue_id, message->queue_name);
            msg_warn("%s: remove %s from %s: %m", myname,
                     message->queue_id, message->queue_name);
-       } else if (msg_verbose) {
-           msg_info("%s: remove %s", myname, message->queue_id);
+       } else {
+           /* Same format as logged by postsuper. */
+           msg_info("%s: removed", message->queue_id);
        }
     }
 
index c1e6ab74904b4051107d5d361b8958507390ace5..d41064ad554b40edb110736e36da93c773b988ca 100644 (file)
@@ -156,6 +156,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
               ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
               ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time,
+              ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name,
+              ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
+              ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
+              ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
               ATTR_TYPE_END);
     if (sender_buf != 0)
        vstring_free(sender_buf);
index a860e384ca9cc3a8f071ece8f1176ea7dfae6890..70fa555dba27f334b8f6154379a7259c6f261f46 100644 (file)
@@ -158,6 +158,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->warn_time = 0;
     message->rcpt_offset = 0;
     message->verp_delims = 0;
+    message->client_name = 0;
+    message->client_addr = 0;
+    message->client_proto = 0;
+    message->client_helo = 0;
     qmgr_rcpt_list_init(&message->rcpt_list);
     return (message);
 }
@@ -490,6 +494,27 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    myfree(message->encoding);
                message->encoding = mystrdup(value);
            }
+           /* Original client attributes. */
+           if (strcmp(name, MAIL_ATTR_CLIENT_NAME) == 0) {
+               if (message->client_name != 0)
+                   myfree(message->client_name);
+               message->client_name = mystrdup(value);
+           }
+           if (strcmp(name, MAIL_ATTR_CLIENT_ADDR) == 0) {
+               if (message->client_addr != 0)
+                   myfree(message->client_addr);
+               message->client_addr = mystrdup(value);
+           }
+           if (strcmp(name, MAIL_ATTR_PROTO_NAME) == 0) {
+               if (message->client_proto != 0)
+                   myfree(message->client_proto);
+               message->client_proto = mystrdup(value);
+           }
+           if (strcmp(name, MAIL_ATTR_HELO_NAME) == 0) {
+               if (message->client_helo != 0)
+                   myfree(message->client_helo);
+               message->client_helo = mystrdup(value);
+           }
            /* Optional tracing flags. */
            else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
                message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@@ -551,6 +576,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        message->return_receipt = mystrdup("");
     if (message->encoding == 0)
        message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
+    if (message->client_name == 0)
+       message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
+    if (message->client_addr == 0)
+       message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+    if (message->client_proto == 0)
+       message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
+    if (message->client_helo == 0)
+       message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
 
     /*
      * Clean up.
index 2ccd7d449914be0fc608ead27379b09f90208694..e3fdf333c4433b604b2046e8d5713e9354536d8f 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = qmqpd.c qmqpd_state.c qmqpd_peer.c
 OBJS   = qmqpd.o qmqpd_state.o qmqpd_peer.o
 HDRS   =
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index 7fdaae2327ac2d221e28ab6e04efc81e51f40057..fbbb60600ce8392c661de44895de8271c4ccde45 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = sendmail.c
 OBJS   = sendmail.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
index a59957c01363231826808379bce29064fd2279e0..2dc1ed9e9f0b768b6b9db7498cca50b25645c748 100644 (file)
@@ -740,7 +740,7 @@ int     main(int argc, char **argv)
     for (fd = 0; fd < 3; fd++)
        if (fstat(fd, &st) == -1
            && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
-           msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
+           msg_fatal_status(EX_OSERR, "open /dev/null: %m");
 
     /*
      * The CDE desktop calendar manager leaks a parent file descriptor into
index 2001e4df340b951ab4036cb77f45f12cd156e64e..a8cba0c1f156d6783fb1bb9152559bb86213a89a 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = showq.c
 OBJS   = showq.o
 HDRS   = 
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index d510098143accc873b0184cebb78d24d18753afd..7249c3eff27cc8abaabc527d36dda3f473c8d778 100644 (file)
@@ -7,9 +7,6 @@ OBJS    = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
        smtp_sasl_proto.o smtp_sasl_glue.o
 HDRS   = smtp.h smtp_sasl.h
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= smtp_unalias
@@ -176,6 +173,7 @@ smtp_proto.o: ../../include/mail_proto.h
 smtp_proto.o: ../../include/attr.h
 smtp_proto.o: ../../include/mime_state.h
 smtp_proto.o: ../../include/header_opts.h
+smtp_proto.o: ../../include/xtext.h
 smtp_proto.o: smtp.h
 smtp_proto.o: ../../include/argv.h
 smtp_proto.o: smtp_sasl.h
index b1324c835eb0f0ad64a457b8a06a0e86391ce570..3400b7df3d764dd34f31e690c31def92c787cd05 100644 (file)
 /* .IP \fBsmtp_helo_timeout\fR
 /*     Timeout for sending the \fBHELO\fR command, and for
 /*     receiving the server response.
+/* .IP \fBsmtp_xclient_timeout\fR
+/*     Timeout for sending the \fBXCLIENT\fR command, and for
+/*     receiving the server response.
 /* .IP \fBsmtp_mail_timeout\fR
 /*     Timeout for sending the \fBMAIL FROM\fR command, and for
 /*     receiving the server response.
 /*     than the local MTA).
 /*     If yes, keep trying until a suitable MX host resolves or until
 /*     the mail is too old.
+/* .IP \fBsmtp_send_xclient_command\fR
+/*     If the SMTP server announces XCLIENT support, send the name,
+/*     address, protocol and HELO name of the original client. This
+/*     can be used to forward client information through a content
+/*     filter to a downstream queuing SMTP server.
 /* .IP \fBsmtp_rset_timeout\fR
 /*     Timeout for sending the \fBRSET\fR command.
 /* .IP \fBsmtp_quit_timeout\fR
   */
 int     var_smtp_conn_tmout;
 int     var_smtp_helo_tmout;
+int     var_smtp_xclnt_tmout;
 int     var_smtp_mail_tmout;
 int     var_smtp_rcpt_tmout;
 int     var_smtp_data0_tmout;
@@ -305,6 +314,7 @@ char   *var_smtp_helo_name;
 char   *var_smtp_host_lookup;
 bool    var_smtp_quote_821_env;
 bool    var_smtp_defer_mxaddr;
+bool    var_smtp_send_xclient;
 
  /*
   * Global variables. smtp_errno is set by the address lookup routines and by
@@ -492,6 +502,7 @@ int     main(int argc, char **argv)
     static CONFIG_TIME_TABLE time_table[] = {
        VAR_SMTP_CONN_TMOUT, DEF_SMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
        VAR_SMTP_HELO_TMOUT, DEF_SMTP_HELO_TMOUT, &var_smtp_helo_tmout, 1, 0,
+       VAR_SMTP_XCLNT_TMOUT, DEF_SMTP_XCLNT_TMOUT, &var_smtp_xclnt_tmout, 1, 0,
        VAR_SMTP_MAIL_TMOUT, DEF_SMTP_MAIL_TMOUT, &var_smtp_mail_tmout, 1, 0,
        VAR_SMTP_RCPT_TMOUT, DEF_SMTP_RCPT_TMOUT, &var_smtp_rcpt_tmout, 1, 0,
        VAR_SMTP_DATA0_TMOUT, DEF_SMTP_DATA0_TMOUT, &var_smtp_data0_tmout, 1, 0,
@@ -518,6 +529,7 @@ int     main(int argc, char **argv)
        VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
        VAR_SMTP_QUOTE_821_ENV, DEF_SMTP_QUOTE_821_ENV, &var_smtp_quote_821_env,
        VAR_SMTP_DEFER_MXADDR, DEF_SMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
+       VAR_SMTP_SEND_XCLIENT, DEF_SMTP_SEND_XCLIENT, &var_smtp_send_xclient,
        0,
     };
 
index c4500d1d1f1a6c4d2c0b88e41d8a277914c3620c..8c9d0407442a0b82b8d6c46bfabe58a9aafb954b 100644 (file)
@@ -64,6 +64,7 @@ typedef struct SMTP_STATE {
 #define SMTP_FEATURE_STARTTLS  (1<<4)
 #define SMTP_FEATURE_AUTH      (1<<5)
 #define SMTP_FEATURE_MAYBEPIX  (1<<6)  /* PIX smtp fixup mode */
+#define SMTP_FEATURE_XCLIENT   (1<<7)  /* server supports XCLIENT */
 
  /*
   * smtp.c
index 024d78e19c1c39c76b5326794119a03717cc6d92..243f1fab6d3c8f900ddb04409b1532cb908641dc 100644 (file)
 #include <quote_821_local.h>
 #include <mail_proto.h>
 #include <mime_state.h>
+#include <xtext.h>
 
 /* Application-specific. */
 
   * SMTP_STATE_DOT) must have smaller numerical values than the non-sending
   * states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
   */
-#define SMTP_STATE_MAIL                0
-#define SMTP_STATE_RCPT                1
-#define SMTP_STATE_DATA                2
-#define SMTP_STATE_DOT         3
-#define SMTP_STATE_ABORT       4
-#define SMTP_STATE_QUIT                5
-#define SMTP_STATE_LAST                6
+#define SMTP_STATE_XCLIENT_ADDR        0
+#define SMTP_STATE_XCLIENT_HELO        1
+#define SMTP_STATE_MAIL                2
+#define SMTP_STATE_RCPT                3
+#define SMTP_STATE_DATA                4
+#define SMTP_STATE_DOT         5
+#define SMTP_STATE_ABORT       6
+#define SMTP_STATE_QUIT                7
+#define SMTP_STATE_LAST                8
 
 int    *xfer_timeouts[SMTP_STATE_LAST] = {
+    &var_smtp_xclnt_tmout,
+    &var_smtp_xclnt_tmout,
     &var_smtp_mail_tmout,
     &var_smtp_rcpt_tmout,
     &var_smtp_data0_tmout,
@@ -141,6 +146,8 @@ int    *xfer_timeouts[SMTP_STATE_LAST] = {
 };
 
 char   *xfer_states[SMTP_STATE_LAST] = {
+    "sending XCLIENT address and name",
+    "sending XCLIENT helo_name and protocol",
     "sending MAIL FROM",
     "sending RCPT TO",
     "sending DATA command",
@@ -150,6 +157,8 @@ char   *xfer_states[SMTP_STATE_LAST] = {
 };
 
 char   *xfer_request[SMTP_STATE_LAST] = {
+    "XCLIENT command",
+    "XCLIENT command",
     "MAIL FROM command",
     "RCPT TO command",
     "DATA command",
@@ -250,6 +259,8 @@ int     smtp_helo(SMTP_STATE *state)
                state->features |= SMTP_FEATURE_8BITMIME;
            else if (strcasecmp(word, "PIPELINING") == 0)
                state->features |= SMTP_FEATURE_PIPELINING;
+           else if (strcasecmp(word, "XCLIENT") == 0)
+               state->features |= SMTP_FEATURE_XCLIENT;
            else if (strcasecmp(word, "SIZE") == 0) {
                state->features |= SMTP_FEATURE_SIZE;
                if ((word = mystrtok(&words, " \t")) != 0) {
@@ -374,6 +385,8 @@ int     smtp_xfer(SMTP_STATE *state)
     int     mail_from_rejected;
     int     downgrading;
     int     mime_errs;
+    int     send_xclient_addr = 0;
+    int     send_xclient_helo = 0;
 
     /*
      * Macros for readability.
@@ -472,9 +485,23 @@ int     smtp_xfer(SMTP_STATE *state)
      * receiver detects a serious problem (MAIL FROM rejected, all RCPT TO
      * commands rejected, DATA rejected) it forces the sender to abort the
      * SMTP dialog with RSET and QUIT.
+     * 
+     * Send "XCLIENT LOG" information only if we have a surrogate remote client
+     * name and address, i.e. the mail was actually received from the
+     * network. Since "XCLIENT LOG" overrides all remote client logging
+     * attributes, there is no need to send helo or protocol information that
+     * we do not have.
      */
     nrcpt = 0;
-    recv_state = send_state = SMTP_STATE_MAIL;
+    send_xclient_addr = (state->features & SMTP_FEATURE_XCLIENT)
+       && !IS_UNK_CLNT_NAME(request->client_name)
+       && !IS_UNK_CLNT_ADDR(request->client_addr);
+    if (send_xclient_addr) {
+       send_xclient_helo = !IS_UNK_HELO_NAME(request->client_helo)
+           || !IS_UNK_PROTOCOL(request->client_proto);
+       recv_state = send_state = SMTP_STATE_XCLIENT_ADDR;
+    } else
+       recv_state = send_state = SMTP_STATE_MAIL;
     next_rcpt = send_rcpt = recv_rcpt = 0;
     mail_from_rejected = 0;
 
@@ -491,6 +518,41 @@ int     smtp_xfer(SMTP_STATE *state)
        default:
            msg_panic("%s: bad sender state %d", myname, send_state);
 
+           /*
+            * Build the XCLIENT command. Send what we know, converting
+            * internal form to external form. With properly sanitized
+            * information, this stays within the 512 byte command line
+            * length limit.
+            */
+       case SMTP_STATE_XCLIENT_ADDR:
+           vstring_sprintf(next_command, "XCLIENT LOG");
+           if (!IS_UNK_CLNT_NAME(request->client_name)) {
+               vstring_strcat(next_command, " CLIENT_NAME=");
+               xtext_quote_append(next_command, request->client_name, "");
+           }
+           if (!IS_UNK_CLNT_ADDR(request->client_addr)) {
+               vstring_strcat(next_command, " CLIENT_ADDR=");
+               xtext_quote_append(next_command, request->client_addr, "");
+           }
+           if (send_xclient_helo)
+               next_state = SMTP_STATE_XCLIENT_HELO;
+           else
+               next_state = SMTP_STATE_MAIL;
+           break;
+
+       case SMTP_STATE_XCLIENT_HELO:
+           vstring_sprintf(next_command, "XCLIENT");
+           if (!IS_UNK_HELO_NAME(request->client_helo)) {
+               vstring_strcat(next_command, " HELO_NAME=");
+               xtext_quote_append(next_command, request->client_helo, "");
+           }
+           if (!IS_UNK_PROTOCOL(request->client_proto)) {
+               vstring_strcat(next_command, " PROTOCOL=");
+               xtext_quote_append(next_command, request->client_proto, "");
+           }
+           next_state = SMTP_STATE_MAIL;
+           break;
+
            /*
             * Build the MAIL FROM command.
             */
@@ -600,7 +662,7 @@ int     smtp_xfer(SMTP_STATE *state)
                /*
                 * Sanity check.
                 */
-               if (recv_state < SMTP_STATE_MAIL
+               if (recv_state < SMTP_STATE_XCLIENT_ADDR
                    || recv_state > SMTP_STATE_QUIT)
                    msg_panic("%s: bad receiver state %d (sender state %d)",
                              myname, recv_state, send_state);
@@ -621,6 +683,20 @@ int     smtp_xfer(SMTP_STATE *state)
                 */
                switch (recv_state) {
 
+                   /*
+                    * Ignore the XCLIENT response. No Duff device needed.
+                    */
+               case SMTP_STATE_XCLIENT_ADDR:
+                   if (send_xclient_helo)
+                       recv_state = SMTP_STATE_XCLIENT_HELO;
+                   else
+                       recv_state = SMTP_STATE_MAIL;
+                   break;
+
+               case SMTP_STATE_XCLIENT_HELO:
+                   recv_state = SMTP_STATE_MAIL;
+                   break;
+
                    /*
                     * Process the MAIL FROM response. When the server
                     * rejects the sender, set the mail_from_rejected flag so
index 2ddf62ae82c23f26c9e8b972f33b0cc02b1984bc..7161b3fffc0bf27d532bd18f4227de8980ed4ee7 100644 (file)
@@ -1,14 +1,13 @@
 SHELL  = /bin/sh
 SRCS   = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
-       smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c
+       smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
+       smtpd_xclient.c
 OBJS   = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
-       smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o
+       smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
+       smtpd_xclient.o
 HDRS   = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
        smtpd_sasl_glue.h smtpd_proxy.h
 TESTSRC        = smtpd_token_test.c
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= smtpd_token smtpd_check
@@ -122,6 +121,7 @@ smtpd.o: ../../include/dict.h
 smtpd.o: ../../include/argv.h
 smtpd.o: ../../include/watchdog.h
 smtpd.o: ../../include/iostuff.h
+smtpd.o: ../../include/split_at.h
 smtpd.o: ../../include/mail_params.h
 smtpd.o: ../../include/record.h
 smtpd.o: ../../include/rec_type.h
@@ -150,6 +150,7 @@ smtpd.o: ../../include/namadr_list.h
 smtpd.o: ../../include/input_transp.h
 smtpd.o: ../../include/anvil_clnt.h
 smtpd.o: ../../include/attr_clnt.h
+smtpd.o: ../../include/xtext.h
 smtpd.o: ../../include/mail_server.h
 smtpd.o: smtpd_token.h
 smtpd.o: smtpd.h
@@ -243,8 +244,11 @@ smtpd_peer.o: ../../include/valid_hostname.h
 smtpd_peer.o: ../../include/stringops.h
 smtpd_peer.o: ../../include/vstring.h
 smtpd_peer.o: ../../include/vbuf.h
-smtpd_peer.o: smtpd.h
+smtpd_peer.o: ../../include/mail_proto.h
 smtpd_peer.o: ../../include/vstream.h
+smtpd_peer.o: ../../include/iostuff.h
+smtpd_peer.o: ../../include/attr.h
+smtpd_peer.o: smtpd.h
 smtpd_peer.o: ../../include/argv.h
 smtpd_peer.o: ../../include/mail_stream.h
 smtpd_proxy.o: smtpd_proxy.c
@@ -262,6 +266,9 @@ smtpd_proxy.o: ../../include/smtp_stream.h
 smtpd_proxy.o: ../../include/cleanup_user.h
 smtpd_proxy.o: ../../include/mail_params.h
 smtpd_proxy.o: ../../include/rec_type.h
+smtpd_proxy.o: ../../include/xtext.h
+smtpd_proxy.o: ../../include/mail_proto.h
+smtpd_proxy.o: ../../include/attr.h
 smtpd_proxy.o: smtpd.h
 smtpd_proxy.o: ../../include/argv.h
 smtpd_proxy.o: ../../include/mail_stream.h
@@ -331,3 +338,16 @@ smtpd_token.o: ../../include/mvect.h
 smtpd_token.o: smtpd_token.h
 smtpd_token.o: ../../include/vstring.h
 smtpd_token.o: ../../include/vbuf.h
+smtpd_xclient.o: smtpd_xclient.c
+smtpd_xclient.o: ../../include/sys_defs.h
+smtpd_xclient.o: ../../include/mymalloc.h
+smtpd_xclient.o: ../../include/msg.h
+smtpd_xclient.o: ../../include/mail_proto.h
+smtpd_xclient.o: ../../include/vstream.h
+smtpd_xclient.o: ../../include/vbuf.h
+smtpd_xclient.o: ../../include/iostuff.h
+smtpd_xclient.o: ../../include/attr.h
+smtpd_xclient.o: smtpd.h
+smtpd_xclient.o: ../../include/vstring.h
+smtpd_xclient.o: ../../include/argv.h
+smtpd_xclient.o: ../../include/mail_stream.h
index 54555dc409249c9d57b5f41f4d3e4c9a27d141f7..301ebf39f7731a0c7cacf3a3be441e87da366a34 100644 (file)
 /* .IP \fBsmtpd_authorized_verp_clients\fR
 /*     Hostnames, domain names and/or addresses of clients that are
 /*     authorized to use the XVERP extension.
-/* .IP \fBsmtpd_authorized_xaddr_clients\fR
+/* .IP \fBsmtpd_authorized_xclient_hosts\fR
 /*     Hostnames, domain names and/or addresses of clients that are
-/*     authorized to use the "XADDR client-address client-name" command.
-/*     This changes Postfix's
-/*     idea of the SMTP client IP address and hostname for access
-/*     control and for logging purposes.
-/* .IP \fBsmtpd_authorized_xloginfo_clients\fR
-/*     Hostnames, domain names and/or addresses of clients that are
-/*     authorized to use the "XLOGINFO client-address client-name" command.
-/*     This changes the client
-/*     name and address that are used for logging, without affecting the
-/*     client IP address and hostname that are used for access control.
-/*     XLOGINFO is typically used to propagate remote client information
-/*     through an SMTP-based content filter to the after-filter SMTP server.
+/*     authorized to use the XCLIENT command.  This command changes
+/*     client information for access control and/or logging purposes,
+/*     with the exception of the
+/*     \fBsmtpd_authorized_xclient_hosts\fR access control itself.
 /* .IP \fBdebug_peer_level\fR
 /*     Increment in verbose logging level when a remote host matches a
 /*     pattern in the \fBdebug_peer_list\fR parameter.
 #include <dict.h>
 #include <watchdog.h>
 #include <iostuff.h>
+#include <split_at.h>
 
 /* Global library. */
 
 #include <namadr_list.h>
 #include <input_transp.h>
 #include <anvil_clnt.h>
+#include <xtext.h>
 
 /* Single-threaded server skeleton. */
 
@@ -557,8 +551,7 @@ char   *var_input_transp;
 int     var_smtpd_policy_tmout;
 int     var_smtpd_policy_idle;
 int     var_smtpd_policy_ttl;
-char   *var_xaddr_clients;
-char   *var_xloginfo_clients;
+char   *var_xclient_hosts;
 int     var_smtpd_crate_limit;
 int     var_smtpd_cconn_limit;
 char   *var_smtpd_hoggers;
@@ -578,16 +571,9 @@ char   *var_smtpd_hoggers;
 static NAMADR_LIST *verp_clients;
 
  /*
-  * XADDR command.
-  */
-#define XADDR_CMD              "XADDR"
-
-static NAMADR_LIST *xaddr_clients;
-
- /*
-  * XLOGINFO command.
+  * XCLIENT command.
   */
-static NAMADR_LIST *xloginfo_clients;
+static NAMADR_LIST *xclient_hosts;
 
  /*
   * Client connection and rate limiting.
@@ -630,11 +616,10 @@ static int sasl_client_exception(SMTPD_STATE *state)
        return (0);
 
     match = namadr_list_match(sasl_exceptions_networks,
-                             state->name, state->addr);
+                             ACL_NAME(state), ACL_ADDR(state));
 
     if (msg_verbose)
-       msg_info("sasl_exceptions: %s[%s], match=%d",
-                state->name, state->addr, match);
+       msg_info("sasl_exceptions: %s, match=%d", ACL_NAMADDR(state), match);
 
     return (match);
 }
@@ -679,6 +664,8 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     mail_reset(state);
     rcpt_reset(state);
     state->helo_name = mystrdup(printable(argv[1].strval, '?'));
+    neuter(state->helo_name, "<>()\\\";:@", '?');
+    /* Changing the protocol name breaks the unauthorized pipelining check. */
     if (strcmp(state->protocol, MAIL_PROTO_ESMTP) != 0)
        state->protocol = MAIL_PROTO_SMTP;
     smtpd_chat_reply(state, "250 %s", var_myhostname);
@@ -715,6 +702,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     mail_reset(state);
     rcpt_reset(state);
     state->helo_name = mystrdup(printable(argv[1].strval, '?'));
+    neuter(state->helo_name, "<>()\\\";:@", '?');
     state->protocol = MAIL_PROTO_ESMTP;
     smtpd_chat_reply(state, "250-%s", var_myhostname);
     smtpd_chat_reply(state, "250-PIPELINING");
@@ -733,12 +721,11 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
     }
 #endif
-    if (namadr_list_match(verp_clients, state->name, state->addr))
+    if (namadr_list_match(verp_clients, ACL_NAME(state), ACL_ADDR(state)))
        smtpd_chat_reply(state, "250-%s", VERP_CMD);
-    if (namadr_list_match(xaddr_clients, state->name, state->addr))
-       smtpd_chat_reply(state, "250-%s", XADDR_CMD);
-    if (namadr_list_match(xloginfo_clients, state->name, state->addr))
-       smtpd_chat_reply(state, "250-%s", XLOGINFO_CMD);
+    /* XCLIENT must not override its own access control. */
+    if (namadr_list_match(xclient_hosts, state->name, state->addr))
+       smtpd_chat_reply(state, "250-%s", XCLIENT_CMD);
     smtpd_chat_reply(state, "250 8BITMIME");
     return (0);
 }
@@ -754,8 +741,7 @@ static void helo_reset(SMTPD_STATE *state)
 
 /* mail_open_stream - open mail queue file or IPC stream */
 
-static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
-                             const char *encoding, const char *verp_delims)
+static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv)
 {
     char   *postdrop_command;
     int     cleanup_flags;
@@ -816,7 +802,7 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
        smtpd_sasl_mail_log(state);
     else
 #endif
-       msg_info("%s: client=%s", state->queue_id, state->namaddr);
+       msg_info("%s: client=%s", state->queue_id, LOG_NAMADDR(state));
 
     /*
      * Record the time of arrival, the sender envelope address, some session
@@ -828,24 +814,29 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
            rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
     }
     rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
-    if (encoding != 0)
+    if (state->encoding != 0)
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                   MAIL_ATTR_ENCODING, encoding);
+                   MAIL_ATTR_ENCODING, state->encoding);
+
+    /*
+     * Store the client attributes for logging purposes.
+     */
     if (SMTPD_STAND_ALONE(state) == 0) {
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                   MAIL_ATTR_CLIENT_NAME, state->name);
+                   MAIL_ATTR_CLIENT_NAME, LOG_NAME(state));
+       rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                   MAIL_ATTR_CLIENT_ADDR, LOG_ADDR(state));
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                   MAIL_ATTR_CLIENT_ADDR, state->addr);
+                   MAIL_ATTR_ORIGIN, LOG_NAMADDR(state));
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                   MAIL_ATTR_ORIGIN, state->namaddr);
-       if (state->helo_name != 0)
-           rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                       MAIL_ATTR_HELO_NAME, state->helo_name);
+                   MAIL_ATTR_HELO_NAME,
+                   IS_UNK_HELO_NAME(LOG_HELO_NAME(state)) ?
+                   HELO_NAME_UNKNOWN : LOG_HELO_NAME(state));
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                   MAIL_ATTR_PROTO_NAME, state->protocol);
+                   MAIL_ATTR_PROTO_NAME, LOG_PROTOCOL(state));
     }
-    if (verp_delims)
-       rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
+    if (state->verp_delims)
+       rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims);
 }
 
 /* extract_addr - extract address from rubble */
@@ -965,8 +956,8 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     int     narg;
     char   *arg;
     char   *verp_delims = 0;
-    char   *encoding = 0;
 
+    state->encoding = 0;
     state->msg_size = 0;
 
     /*
@@ -983,7 +974,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
        return (-1);
     }
-#define IN_MAIL_TRANSACTION(state) ((state)->cleanup || (state)->proxy)
+#define IN_MAIL_TRANSACTION(state) ((state)->sender != 0)
 
     if (IN_MAIL_TRANSACTION(state)) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
@@ -998,7 +989,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     }
     if (argv[2].tokval == SMTPD_TOK_ERROR) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
-       smtpd_chat_reply(state, "501 Bad address syntax");
+       smtpd_chat_reply(state, "501 Bad sender address syntax");
        return (-1);
     }
     if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) {
@@ -1009,9 +1000,9 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     for (narg = 3; narg < argc; narg++) {
        arg = argv[narg].strval;
        if (strcasecmp(arg, "BODY=8BITMIME") == 0) {    /* RFC 1652 */
-           encoding = MAIL_ATTR_ENC_8BIT;
+           state->encoding = MAIL_ATTR_ENC_8BIT;
        } else if (strcasecmp(arg, "BODY=7BIT") == 0) { /* RFC 1652 */
-           encoding = MAIL_ATTR_ENC_7BIT;
+           state->encoding = MAIL_ATTR_ENC_7BIT;
        } else if (strncasecmp(arg, "SIZE=", 5) == 0) { /* RFC 1870 */
            /* Reject non-numeric size. */
            if (!alldig(arg + 5)) {
@@ -1032,11 +1023,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
                return (-1);
            }
 #endif
-       } else if (namadr_list_match(verp_clients, state->name, state->addr)) {
-           if (strcasecmp(arg, VERP_CMD) == 0) {
+       } else if (namadr_list_match(verp_clients, ACL_NAME(state),
+                                    ACL_ADDR(state))
+                  && strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
+                  && (arg[VERP_CMD_LEN] == '=' || arg[VERP_CMD_LEN] == 0)) {
+           if (arg[VERP_CMD_LEN] == 0) {
                verp_delims = var_verp_delims;
-           } else if (strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
-                      && arg[VERP_CMD_LEN] == '=') {
+           } else {
                verp_delims = arg + VERP_CMD_LEN + 1;
                if (verp_delims_verify(verp_delims) != 0) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
@@ -1065,28 +1058,26 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     state->time = time((time_t *) 0);
 
     /*
-     * Open connection to SMTP proxy server.
+     * Check the queue file space, if applicable.
      */
-    if (SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt) {
-       if (smtpd_proxy_open(state, var_smtpd_proxy_filt, var_smtpd_proxy_tmout,
-                          var_smtpd_proxy_ehlo, STR(state->buffer)) != 0) {
-           smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
-           return (-1);
-       }
-    }
+#define USE_SMTPD_PROXY(state) \
+       (SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt)
 
-    /*
-     * Open queue file, or open connection to queue file writing process.
-     * Check for queue file space first.
-     */
-    else {
+    if (!USE_SMTPD_PROXY(state)) {
        if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
            smtpd_chat_reply(state, "%s", err);
            return (-1);
        }
-       mail_open_stream(state, argv, encoding, verp_delims);
     }
+
+    /*
+     * No more early returns. The mail transaction is in progress.
+     */
     state->sender = mystrdup(argv[2].strval);
+    if (verp_delims)
+       state->verp_delims = mystrdup(verp_delims);
+    if (USE_SMTPD_PROXY(state))
+       state->proxy_mail = mystrdup(STR(state->buffer));
     smtpd_chat_reply(state, "250 Ok");
     return (0);
 }
@@ -1115,6 +1106,10 @@ static void mail_reset(SMTPD_STATE *state)
        myfree(state->sender);
        state->sender = 0;
     }
+    if (state->verp_delims) {
+       myfree(state->verp_delims);
+       state->verp_delims = 0;
+    }
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable)
        smtpd_sasl_mail_reset(state);
@@ -1129,6 +1124,10 @@ static void mail_reset(SMTPD_STATE *state)
        (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT");
        smtpd_proxy_close(state);
     }
+    if (state->proxy_mail) {
+       myfree(state->proxy_mail);
+       state->proxy_mail = 0;
+    }
 }
 
 /* rcpt_cmd - process RCPT TO command */
@@ -1161,7 +1160,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     }
     if (argv[2].tokval == SMTPD_TOK_ERROR) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
-       smtpd_chat_reply(state, "501 Bad address syntax");
+       smtpd_chat_reply(state, "501 Bad recipient address syntax");
        return (-1);
     }
     if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) {
@@ -1188,6 +1187,21 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            return (-1);
        }
     }
+
+    /*
+     * Don't access the proxy, queue file, or queue file writer process until
+     * we have a valid recipient address.
+     */
+    if (state->proxy == 0 && state->proxy_mail) {
+       if (smtpd_proxy_open(state, var_smtpd_proxy_filt,
+                            var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
+                            state->proxy_mail) != 0) {
+           smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+           return (-1);
+       }
+    } else if (state->cleanup == 0) {
+       mail_open_stream(state, argv);
+    }
     if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK,
                                        "%s", STR(state->buffer)) != 0) {
        smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
@@ -1284,36 +1298,41 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
      * Terminate the message envelope segment. Start the message content
      * segment, and prepend our own Received: header. If there is only one
      * recipient, list the recipient address.
+     * 
+     * Suppress our own Received: header in the unlikely case that we are an
+     * intermediate proxy.
      */
     if (state->cleanup)
        rec_fputs(state->cleanup, REC_TYPE_MESG, "");
-    out_fprintf(out_stream, REC_TYPE_NORM,
-               "Received: from %s (%s [%s])",
-               state->helo_name ? state->helo_name : state->name,
-               state->name, state->addr);
-    if (state->rcpt_count == 1 && state->recipient) {
-       out_fprintf(out_stream, REC_TYPE_NORM,
-                   state->cleanup ? "\tby %s (%s) with %s id %s" :
-                   "\tby %s (%s) with %s",
-                   var_myhostname, var_mail_name,
-                   state->protocol, state->queue_id);
-       quote_822_local(state->buffer, state->recipient);
+    if (!state->proxy || state->xclient.addr == 0) {
        out_fprintf(out_stream, REC_TYPE_NORM,
+                   "Received: from %s (%s [%s])",
+                   state->helo_name ? state->helo_name : state->name,
+                   state->name, state->addr);
+       if (state->rcpt_count == 1 && state->recipient) {
+           out_fprintf(out_stream, REC_TYPE_NORM,
+                       state->cleanup ? "\tby %s (%s) with %s id %s" :
+                       "\tby %s (%s) with %s",
+                       var_myhostname, var_mail_name,
+                       state->protocol, state->queue_id);
+           quote_822_local(state->buffer, state->recipient);
+           out_fprintf(out_stream, REC_TYPE_NORM,
              "\tfor <%s>; %s", STR(state->buffer), mail_date(state->time));
-    } else {
-       out_fprintf(out_stream, REC_TYPE_NORM,
-                   state->cleanup ? "\tby %s (%s) with %s id %s;" :
-                   "\tby %s (%s) with %s;",
-                   var_myhostname, var_mail_name,
-                   state->protocol, state->queue_id);
-       out_fprintf(out_stream, REC_TYPE_NORM,
-                   "\t%s", mail_date(state->time));
-    }
+       } else {
+           out_fprintf(out_stream, REC_TYPE_NORM,
+                       state->cleanup ? "\tby %s (%s) with %s id %s;" :
+                       "\tby %s (%s) with %s;",
+                       var_myhostname, var_mail_name,
+                       state->protocol, state->queue_id);
+           out_fprintf(out_stream, REC_TYPE_NORM,
+                       "\t%s", mail_date(state->time));
+       }
 #ifdef RECEIVED_ENVELOPE_FROM
-    quote_822_local(state->buffer, state->sender);
-    out_fprintf(out_stream, REC_TYPE_NORM,
-               "\t(envelope-from %s)", STR(state->buffer));
+       quote_822_local(state->buffer, state->sender);
+       out_fprintf(out_stream, REC_TYPE_NORM,
+                   "\t(envelope-from %s)", STR(state->buffer));
 #endif
+    }
     smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
 
     /*
@@ -1650,75 +1669,213 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
     return (0);
 }
 
-/* xaddr_cmd - process XADDR */
+/* xclient_cmd - process XCLIENT */
 
-static int xaddr_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
+static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
 {
+    int     arg_no;
+    char   *raw_value;
+    char   *cooked_value;
+    char   *arg_val;
+    int     update_namaddr = 0;
 
     /*
-     * Sanity checks.
+     * Sanity checks. The XCLIENT command does not override its own access
+     * control.
      */
-    if (namadr_list_match(xaddr_clients, state->name, state->addr) == 0) {
+    if (namadr_list_match(xclient_hosts, state->name, state->addr) == 0) {
        state->error_mask |= MAIL_ERROR_POLICY;
        smtpd_chat_reply(state, "554 Error: insufficient authorization");
        return (-1);
     }
-    /* Todo: "XADDR address" to let Postfix look up the client name. */
-    if (argc != 3
-       || !valid_hostaddr(argv[1].strval, DONT_GRIPE)
-       || !valid_hostname(argv[2].strval, DONT_GRIPE)) {
-       state->error_mask |= MAIL_ERROR_PROTOCOL;
-       smtpd_chat_reply(state, "501 Syntax: %s address hostname", XADDR_CMD);
-       return (-1);
-    }
+#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
+#define UPDATE_STR(s, v) { if (s) myfree(s); s = mystrdup(v); }
 
     /*
-     * Change peer information for logging and for access control. Change a
-     * numerical hostname into "unknown", to make it easy to extract client
-     * information from Received: headers.
+     * Iterate over all XCLIENT arguments.
      */
-#define FIX_NUMERICAL_NAME(s) \
-       (valid_hostaddr((s), DONT_GRIPE) ?  "unknown" : (s))
-
-    smtpd_peer_reset(state);
-    state->name = mystrdup(FIX_NUMERICAL_NAME(argv[2].strval));
-    state->addr = mystrdup(argv[1].strval);
-    state->namaddr =
-       concatenate(state->name, "[", state->addr, "]", (char *) 0);
-    state->peer_code = strcmp(state->name, "unknown") ? 2 : 5;
-    smtpd_chat_reply(state, "250 Ok");
-    return (0);
-}
+    for (arg_no = 1; arg_no < argc; arg_no++) {
+       arg_val = argv[arg_no].strval;
+
+       /*
+        * Request name: what should happen with the stored attributes.
+        * Complain about unrecognized request names. The set of requests is
+        * unlikely to change.
+        */
+       if ((raw_value = split_at(arg_val, '=')) == 0) {
+           printable(arg_val, '?');
+           if (STREQ(arg_val, "RST")) {        /* blow them away */
+               smtpd_xclient_reset(state, XCLIENT_OVER_NONE);
+           } else if (STREQ(arg_val, "ACL")) { /* access control and logging */
+               smtpd_xclient_reset(state, XCLIENT_OVER_ACL | XCLIENT_OVER_LOG);
+           } else if (STREQ(arg_val, "LOG")) { /* logging only */
+               smtpd_xclient_reset(state, XCLIENT_OVER_LOG);
+           } else {                            /* error */
+               state->error_mask |= MAIL_ERROR_PROTOCOL;
+               smtpd_chat_reply(state, "501 Bad request: %s", arg_val);
+               return (-1);
+           }
+       }
 
-/* xloginfo_cmd - process XLOGINFO */
+       /*
+        * NAME=VALUE attribute. Decode the attribute and for safety's sake
+        * mask non-printable characters in the raw and decoded values; we
+        * don't want to handle unexploded munitions. Do not complain about
+        * unrecognized attribute names. The set of attributes may change
+        * over time.
+        * 
+        * The client can send multiple XCLIENT attributes in a single command,
+        * or multiple XCLIENT commands with fewer attributes.
+        * 
+        * Note: XCLIENT ACL overrides only specific logging and access control
+        * attributes (desirable for testing), while XCLIENT LOG overrides
+        * all logging attributes (for audit trail consistency).
+        */
+       else {
+           if (state->xclient.mode == 0) {
+               state->error_mask |= MAIL_ERROR_PROTOCOL;
+               smtpd_chat_reply(state, "503 Error: send %s ACL or LOG first",
+                                XCLIENT_CMD);
+               return (-1);
+           }
+           if (xtext_unquote(state->buffer, raw_value) == 0) {
+               state->error_mask |= MAIL_ERROR_PROTOCOL;
+               smtpd_chat_reply(state, "501 Bad attribute value syntax: %s",
+                                printable(raw_value, '?'));
+               return (-1);
+           }
+           cooked_value = printable(STR(state->buffer), '?');
+           (void) printable(raw_value, '?');
+
+           /*
+            * CLIENT_NAME=hostname. Also updates the client hostname lookup
+            * status code. Treat a numerical hostname as an unavailable
+            * name.
+            */
+           if (STREQ(arg_val, "CLIENT_NAME")) {
+               if (*raw_value && !valid_hostaddr(cooked_value, DONT_GRIPE)) {
+                   if (!valid_hostname(cooked_value, DONT_GRIPE)) {
+                       state->error_mask |= MAIL_ERROR_PROTOCOL;
+                       smtpd_chat_reply(state, "501 Bad hostname syntax: %s",
+                                        cooked_value);
+                       return (-1);
+                   }
+                   UPDATE_STR(state->xclient.name, cooked_value);
+                   state->xclient.peer_code = SMTPD_PEER_CODE_OK;
+               } else {
+                   UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
+                   state->xclient.peer_code = SMTPD_PEER_CODE_PERM;
+               }
+               update_namaddr = 1;
+           }
 
-static int xloginfo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
-{
+           /*
+            * CLIENT_ADDR=client network address.
+            */
+           else if (STREQ(arg_val, "CLIENT_ADDR")) {
+               if (*raw_value) {
+                   if (!valid_hostaddr(cooked_value, DONT_GRIPE)) {
+                       state->error_mask |= MAIL_ERROR_PROTOCOL;
+                       smtpd_chat_reply(state, "501 Bad address syntax: %s",
+                                        cooked_value);
+                       return (-1);
+                   }
+                   UPDATE_STR(state->xclient.addr, cooked_value);
+               } else {
+                   UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
+               }
+               update_namaddr = 1;
+           }
 
-    /*
-     * Sanity checks.
-     */
-    if (namadr_list_match(xloginfo_clients, state->name, state->addr) == 0) {
-       state->error_mask |= MAIL_ERROR_POLICY;
-       smtpd_chat_reply(state, "554 Error: insufficient authorization");
-       return (-1);
-    }
-    if (argc != 3
-       || !valid_hostaddr(argv[1].strval, DONT_GRIPE)
-       || !valid_hostname(argv[2].strval, DONT_GRIPE)) {
-       state->error_mask |= MAIL_ERROR_PROTOCOL;
-       smtpd_chat_reply(state, "501 Syntax: %s address hostname", XLOGINFO_CMD);
-       return (-1);
+           /*
+            * CLIENT_CODE=status. Reset the client hostname if the hostname
+            * lookup status is not OK.
+            */
+           else if (STREQ(arg_val, "CLIENT_CODE")) {
+               if (STREQ(cooked_value, "OK")) {
+                   state->xclient.peer_code = SMTPD_PEER_CODE_OK;
+               } else if (STREQ(cooked_value, "TEMP")) {
+                   state->xclient.peer_code = SMTPD_PEER_CODE_TEMP;
+                   UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
+                   update_namaddr = 1;
+               } else if (STREQ(cooked_value, "PERM")) {
+                   state->xclient.peer_code = SMTPD_PEER_CODE_PERM;
+                   UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
+                   update_namaddr = 1;
+               } else {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 Bad hostname status: %s",
+                                    cooked_value);
+                   return (-1);
+               }
+           }
+
+           /*
+            * HELO_NAME=hostname. An empty value means the information was
+            * not provided by the client and that we must not fall back to
+            * the non-XCLIENT value. Disallow characters that could mess up
+            * our own Received: message headers but allow [].
+            */
+           else if (STREQ(arg_val, "HELO_NAME")) {
+               if (*raw_value) {
+                   if (strlen(cooked_value) > VALID_HOSTNAME_LEN) {
+                       state->error_mask |= MAIL_ERROR_PROTOCOL;
+                       smtpd_chat_reply(state, "501 Bad HELO syntax: %s",
+                                        cooked_value);
+                       return (-1);
+                   }
+                   neuter(cooked_value, "<>()\\\";:@", '?');
+                   UPDATE_STR(state->xclient.helo_name, cooked_value);
+               } else {
+                   UPDATE_STR(state->xclient.helo_name, HELO_NAME_UNKNOWN);
+               }
+           }
+
+           /*
+            * PROTOCOL=protocol name. Disallow characters that could mess up
+            * our own Received: message headers.
+            */
+           else if (STREQ(arg_val, "PROTOCOL")) {
+               if (*raw_value) {
+                   if (*cooked_value == 0 || strlen(cooked_value) > 64) {
+                       state->error_mask |= MAIL_ERROR_PROTOCOL;
+                       smtpd_chat_reply(state, "501 Bad protocol syntax: %s",
+                                        cooked_value);
+                       return (-1);
+                   }
+                   neuter(cooked_value, "[]<>()\\\";:@", '?');
+                   UPDATE_STR(state->xclient.protocol, cooked_value);
+               } else {
+                   UPDATE_STR(state->xclient.protocol, PROTOCOL_UNKNOWN);
+               }
+           }
+
+           /*
+            * Unknown attribute name. Don't complain, and log a warning.
+            * Logging is safe because only authorized clients can issue
+            * XCLIENT commands.
+            */
+           else {
+               msg_warn("unknown %s attribute from %s: %s=%s",
+                        XCLIENT_CMD, state->namaddr, arg_val, cooked_value);
+           }
+       }
     }
 
     /*
-     * Change peer information for logging but not for access control. Change
-     * a numerical hostname into "unknown", for consistency with XADDR.
+     * Update the combined name and address when either has changed.
      */
-    myfree(state->namaddr);
-    state->namaddr =
-       concatenate(FIX_NUMERICAL_NAME(argv[2].strval),
-                   "[", argv[1].strval, "]", (char *) 0);
+#define MAYBE_OVERRIDE(state, attr) \
+       ((state)->xclient.attr ? (state)->xclient.attr : (state)->attr)
+
+    if (update_namaddr) {
+       if (state->xclient.namaddr)
+           myfree(state->xclient.namaddr);
+       state->xclient.namaddr =
+           concatenate(MAYBE_OVERRIDE(state, name), "[",
+                       MAYBE_OVERRIDE(state, addr), "]",
+                       (char *) 0);
+    }
     smtpd_chat_reply(state, "250 Ok");
     return (0);
 }
@@ -1774,8 +1931,7 @@ static SMTPD_CMD smtpd_cmd_table[] = {
     "VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
     "ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
     "QUIT", quit_cmd, 0,
-    "XADDR", xaddr_cmd, SMTPD_CMD_FLAG_LIMIT,
-    "XLOGINFO", xloginfo_cmd, SMTPD_CMD_FLAG_LIMIT,
+    "XCLIENT", xclient_cmd, SMTPD_CMD_FLAG_LIMIT,
     "Received:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
     "Reply-To:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
     "Message-ID:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
@@ -1835,6 +1991,12 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
        break;
 
     case 0:
+
+       /*
+        * XXX The client connection count/rate control uses the real client
+        * name/address to maintain consistency between connect and
+        * disconnect events.
+        */
        if (SMTPD_STAND_ALONE(state) == 0
            && anvil_clnt
            && !namadr_list_match(hogger_list, state->name, state->addr)
@@ -1855,6 +2017,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
                break;
            }
        }
+       /* XXX We use the real client for connect access control. */
        if (SMTPD_STAND_ALONE(state) == 0
            && var_smtpd_delay_reject == 0
            && (state->access_denied = smtpd_check_client(state)) != 0) {
@@ -1900,6 +2063,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
                smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
                break;
            }
+           /* XXX We use the real client for connect access control. */
            if (state->access_denied && cmdp->action != quit_cmd) {
                smtpd_chat_reply(state, "503 Error: access denied for %s",
                                 state->namaddr);       /* RFC 2821 Sec 3.1 */
@@ -1917,6 +2081,12 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
        }
        break;
     }
+
+    /*
+     * XXX The client connection count/rate control uses the real client
+     * name/address to maintain consistency between connect and disconnect
+     * events.
+     */
     if (SMTPD_STAND_ALONE(state) == 0
        && anvil_clnt
        && !namadr_list_match(hogger_list, state->name, state->addr))
@@ -2014,8 +2184,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
      */
     smtpd_noop_cmds = string_list_init(MATCH_FLAG_NONE, var_smtpd_noop_cmds);
     verp_clients = namadr_list_init(MATCH_FLAG_NONE, var_verp_clients);
-    xaddr_clients = namadr_list_init(MATCH_FLAG_NONE, var_xaddr_clients);
-    xloginfo_clients = namadr_list_init(MATCH_FLAG_NONE, var_xloginfo_clients);
+    xclient_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xclient_hosts);
     hogger_list = namadr_list_init(MATCH_FLAG_NONE, var_smtpd_hoggers);
     if (getuid() == 0 || getuid() == var_owner_uid)
        smtpd_check_init();
@@ -2153,8 +2322,7 @@ int     main(int argc, char **argv)
        VAR_SMTPD_PROXY_FILT, DEF_SMTPD_PROXY_FILT, &var_smtpd_proxy_filt, 0, 0,
        VAR_SMTPD_PROXY_EHLO, DEF_SMTPD_PROXY_EHLO, &var_smtpd_proxy_ehlo, 0, 0,
        VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0,
-       VAR_XADDR_CLIENTS, DEF_XADDR_CLIENTS, &var_xaddr_clients, 0, 0,
-       VAR_XLOGINFO_CLIENTS, DEF_XLOGINFO_CLIENTS, &var_xloginfo_clients, 0, 0,
+       VAR_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0,
        VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0,
        0,
     };
index 40438248ac83cb01c67fec861c490a653dd06ee2..0b418f59cdcaff6e72f83df1052ffbd2573cc413 100644 (file)
@@ -45,6 +45,16 @@ typedef struct SMTPD_DEFER {
     int     class;                     /* error notification class */
 } SMTPD_DEFER;
 
+typedef struct SMTPD_XCLIENT_ATTR {
+    int     mode;                      /* none, log, acl */
+    char   *name;                      /* name for access control */
+    char   *addr;                      /* address for access control */
+    char   *namaddr;                   /* name[address] */
+    int     peer_code;                 /* name status */
+    char   *protocol;                  /* email protocol */
+    char   *helo_name;                 /* helo/ehlo parameter */
+} SMTPD_XCLIENT_ATTR;
+
 typedef struct SMTPD_STATE {
     int     err;
     VSTREAM *client;
@@ -66,6 +76,8 @@ typedef struct SMTPD_STATE {
     ARGV   *history;
     char   *reason;
     char   *sender;
+    char   *encoding;
+    char   *verp_delims;
     char   *recipient;
     char   *etrn_name;
     char   *protocol;
@@ -97,6 +109,9 @@ typedef struct SMTPD_STATE {
     VSTRING *expand_buf;               /* scratch space for $name expansion */
     VSTREAM *proxy;                    /* proxy handle */
     VSTRING *proxy_buffer;             /* proxy query/reply buffer */
+    char   *proxy_mail;                        /* proxy MAIL FROM command */
+    int     proxy_features;            /* proxy ESMTP features */
+    SMTPD_XCLIENT_ATTR xclient;                /* override access control */
 } SMTPD_STATE;
 
 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
@@ -117,21 +132,54 @@ extern void smtpd_state_reset(SMTPD_STATE *);
        (state->client == VSTREAM_IN && getuid() != var_owner_uid)
 
  /*
-  * SMPTD peer information lookup.
+  * SMTPD peer information lookup.
   */
 extern void smtpd_peer_init(SMTPD_STATE *state);
 extern void smtpd_peer_reset(SMTPD_STATE *state);
 
+#define        SMTPD_PEER_CODE_OK      2
+#define SMTPD_PEER_CODE_TEMP   4
+#define SMTPD_PEER_CODE_PERM   5
+
  /*
-  * Transparency: before mail is queued, do we check for unknown recipients,
-  * do we allow address mapping, automatic bcc, header/body checks?
+  * XCLIENT support to override logging and/or access control attributes. It
+  * makes no sense to maintain separate attribute sets for XCLIENT LOG or
+  * XCLIENT ACL, so we set a flag to distinguish purpose.
   */
-extern int smtpd_input_transp_mask;
+#define XCLIENT_CMD            "XCLIENT"       /* XCLIENT command */
+#define XCLIENT_EHLO           "XCLIENT"       /* ESMTP advertisement */
+
+#define SMTPD_FEATURE_XCLIENT  (1<<0)  /* server supports XCLIENT */
+
+#define XCLIENT_OVER_NONE      (0)     /* override reset */
+#define XCLIENT_OVER_ACL       (1<<0)  /* override access control */
+#define XCLIENT_OVER_LOG       (1<<1)  /* override logging */
+
+#define XCLIENT_OVER(s, m, a) \
+       (((s)->xclient.mode & (m)) && (s)->xclient.a ? (s)->xclient.a : (s)->a)
+
+#define ACL_ADDR(s)            XCLIENT_OVER((s), XCLIENT_OVER_ACL, addr)
+#define ACL_NAME(s)            XCLIENT_OVER((s), XCLIENT_OVER_ACL, name)
+#define ACL_NAMADDR(s)         XCLIENT_OVER((s), XCLIENT_OVER_ACL, namaddr)
+#define ACL_PEER_CODE(s)       XCLIENT_OVER((s), XCLIENT_OVER_ACL, peer_code)
+#define ACL_PROTOCOL(s)                XCLIENT_OVER((s), XCLIENT_OVER_ACL, protocol)
+#define ACL_HELO_NAME(s)       XCLIENT_OVER((s), XCLIENT_OVER_ACL, helo_name)
+
+#define LOG_ADDR(s)            XCLIENT_OVER((s), XCLIENT_OVER_LOG, addr)
+#define LOG_NAME(s)            XCLIENT_OVER((s), XCLIENT_OVER_LOG, name)
+#define LOG_NAMADDR(s)         XCLIENT_OVER((s), XCLIENT_OVER_LOG, namaddr)
+#define LOG_PEER_CODE(s)       XCLIENT_OVER((s), XCLIENT_OVER_LOG, peer_code)
+#define LOG_PROTOCOL(s)                XCLIENT_OVER((s), XCLIENT_OVER_LOG, protocol)
+#define LOG_HELO_NAME(s)       XCLIENT_OVER((s), XCLIENT_OVER_LOG, helo_name)
+
+extern void smtpd_xclient_init(SMTPD_STATE *state);
+extern void smtpd_xclient_reset(SMTPD_STATE *state, int);
 
  /*
-  * XLOGINFO command.
+  * Transparency: before mail is queued, do we check for unknown recipients,
+  * do we allow address mapping, automatic bcc, header/body checks?
   */
-#define XLOGINFO_CMD           "XLOGINFO"
+extern int smtpd_input_transp_mask;
 
 /* LICENSE
 /* .ad
index da755fc8eeb43f7eb4bae9d6d5f232bfa7498ba7..b1688b59a738bb112676e1d62c1eb509b0ddff6f 100644 (file)
@@ -809,15 +809,15 @@ static void log_whatsup(SMTPD_STATE *state, const char *whatsup,
 
     vstring_sprintf(buf, "%s: %s: %s from %s: %s;",
                    state->queue_id ? state->queue_id : "NOQUEUE",
-                   whatsup, state->where, state->namaddr, text);
+                   whatsup, state->where, LOG_NAMADDR(state), text);
     if (state->sender)
        vstring_sprintf_append(buf, " from=<%s>", state->sender);
     if (state->recipient)
        vstring_sprintf_append(buf, " to=<%s>", state->recipient);
-    if (state->protocol)
-       vstring_sprintf_append(buf, " proto=%s", state->protocol);
-    if (state->helo_name)
-       vstring_sprintf_append(buf, " helo=<%s>", state->helo_name);
+    if (!IS_UNK_PROTOCOL(ACL_PROTOCOL(state)))
+       vstring_sprintf_append(buf, " proto=%s", ACL_PROTOCOL(state));
+    if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
+       vstring_sprintf_append(buf, " helo=<%s>", ACL_HELO_NAME(state));
     msg_info("%s", STR(buf));
     vstring_free(buf);
 }
@@ -968,14 +968,14 @@ static int reject_unknown_client(SMTPD_STATE *state)
     char   *myname = "reject_unknown_client";
 
     if (msg_verbose)
-       msg_info("%s: %s %s", myname, state->name, state->addr);
+       msg_info("%s: %s %s", myname, ACL_NAME(state), ACL_ADDR(state));
 
-    if (strcasecmp(state->name, "unknown") == 0)
+    if (IS_UNK_CLNT_NAME(ACL_NAME(state)))
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
                 "%d Client host rejected: cannot find your hostname, [%s]",
-                                  state->peer_code == 5 ?
+                             ACL_PEER_CODE(state) == SMTPD_PEER_CODE_PERM ?
                                   var_unk_client_code : 450,
-                                  state->addr));
+                                  ACL_ADDR(state)));
     return (SMTPD_CHECK_DUNNO);
 }
 
@@ -986,9 +986,9 @@ static int permit_mynetworks(SMTPD_STATE *state)
     char   *myname = "permit_mynetworks";
 
     if (msg_verbose)
-       msg_info("%s: %s %s", myname, state->name, state->addr);
+       msg_info("%s: %s %s", myname, ACL_NAME(state), ACL_ADDR(state));
 
-    if (namadr_list_match(mynetworks, state->name, state->addr))
+    if (namadr_list_match(mynetworks, ACL_NAME(state), ACL_ADDR(state)))
        return (SMTPD_CHECK_OK);
     return (SMTPD_CHECK_DUNNO);
 }
@@ -1207,7 +1207,7 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
     /*
      * Permit if the client matches the relay_domains list.
      */
-    if (domain_list_match(relay_domains, state->name))
+    if (domain_list_match(relay_domains, ACL_NAME(state)))
        return (SMTPD_CHECK_OK);
 
     /*
@@ -1309,7 +1309,7 @@ static int reject_unauth_pipelining(SMTPD_STATE *state,
     if (state->client != 0
        && SMTPD_STAND_ALONE(state) == 0
        && vstream_peek(state->client) > 0
-       && (strcasecmp(state->protocol, "ESMTP") != 0
+       && (strcasecmp(ACL_PROTOCOL(state), MAIL_PROTO_ESMTP) != 0
            || strcasecmp(state->where, "DATA") == 0)) {
        return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL,
           "503 <%s>: %s rejected: Improper use of SMTP command pipelining",
@@ -2518,13 +2518,14 @@ static const char *smtpd_expand_lookup(const char *name, int unused_mode,
      * Return NULL only for non-existent names.
      */
     if (STREQ(name, MAIL_ATTR_CLIENT)) {
-       return (state->namaddr);
+       return (ACL_NAMADDR(state));
     } else if (STREQ(name, MAIL_ATTR_CLIENT_ADDR)) {
-       return (state->addr);
+       return (ACL_ADDR(state));
     } else if (STREQ(name, MAIL_ATTR_CLIENT_NAME)) {
-       return (state->name);
+       return (ACL_NAME(state));
     } else if (STREQ(name, MAIL_ATTR_HELO_NAME)) {
-       return (state->helo_name ? state->helo_name : "");
+       return (IS_UNK_HELO_NAME(ACL_HELO_NAME(state)) ?
+               "" : ACL_HELO_NAME(state));
     } else if (STREQN(name, MAIL_ATTR_SENDER, CONST_LEN(MAIL_ATTR_SENDER))) {
        return (smtpd_expand_addr(state->expand_buf, state->sender,
                                  name, CONST_LEN(MAIL_ATTR_SENDER)));
@@ -2820,7 +2821,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
     static int warned;
 
     if (msg_verbose)
-       msg_info("%s: %s", myname, state->addr);
+       msg_info("%s: %s", myname, ACL_ADDR(state));
 
     if (warned == 0) {
        warned++;
@@ -2829,7 +2830,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
                 REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
     }
     while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
-       result = reject_rbl_addr(state, rbl_domain, state->addr,
+       result = reject_rbl_addr(state, rbl_domain, ACL_ADDR(state),
                                 SMTPD_NAME_CLIENT);
        if (result != SMTPD_CHECK_DUNNO)
            break;
@@ -2906,11 +2907,12 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
                          ATTR_FLAG_NONE,       /* Query attributes. */
                        ATTR_TYPE_STR, MAIL_ATTR_REQ, "smtpd_access_policy",
                          ATTR_TYPE_STR, MAIL_ATTR_PROTO_STATE, state->where,
-                      ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, state->protocol,
-                         ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, state->addr,
-                         ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, state->name,
+                  ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, ACL_PROTOCOL(state),
+                     ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, ACL_ADDR(state),
+                     ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, ACL_NAME(state),
                          ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME,
-                         state->helo_name ? state->helo_name : "",
+                         IS_UNK_HELO_NAME(ACL_HELO_NAME(state)) ?
+                         "" : ACL_HELO_NAME(state),
                          ATTR_TYPE_STR, MAIL_ATTR_SENDER,
                          state->sender ? state->sender : "",
                          ATTR_TYPE_STR, MAIL_ATTR_RECIP,
@@ -3075,8 +3077,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
        } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
            status = permit_mynetworks(state);
        } else if (is_map_command(state, name, CHECK_CLIENT_ACL, &cpp)) {
-           status = check_namadr_access(state, *cpp, state->name, state->addr,
-                                        FULL, &found, state->namaddr,
+           status = check_namadr_access(state, *cpp, ACL_NAME(state), ACL_ADDR(state),
+                                        FULL, &found, ACL_NAMADDR(state),
                                         SMTPD_NAME_CLIENT, def_acl);
        } else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
            status = reject_maps_rbl(state);
@@ -3085,7 +3087,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
            if (cpp[1] == 0)
                msg_warn("restriction %s requires domain name argument", name);
            else
-               status = reject_rbl_addr(state, *(cpp += 1), state->addr,
+               status = reject_rbl_addr(state, *(cpp += 1), ACL_ADDR(state),
                                         SMTPD_NAME_CLIENT);
        } else if (strcasecmp(name, REJECT_RHSBL_CLIENT) == 0) {
            if (cpp[1] == 0)
@@ -3093,69 +3095,73 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
                         name);
            else {
                cpp += 1;
-               if (strcasecmp(state->name, "unknown") != 0)
-                   status = reject_rbl_domain(state, *cpp, state->name,
+               if (!IS_UNK_CLNT_NAME(ACL_NAME(state)))
+                   status = reject_rbl_domain(state, *cpp, ACL_NAME(state),
                                               SMTPD_NAME_CLIENT);
            }
        }
 
        /*
         * HELO/EHLO parameter restrictions.
+        * 
+        * XXX With XCLIENT overrides, a zero-length name means the client did
+        * not send a HELO/EHLO command. Do not fall back to the non-XCLIENT
+        * HELO/EHLO value.
         */
        else if (is_map_command(state, name, CHECK_HELO_ACL, &cpp)) {
-           if (state->helo_name)
-               status = check_domain_access(state, *cpp, state->helo_name,
-                                            FULL, &found, state->helo_name,
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
+               status = check_domain_access(state, *cpp, ACL_HELO_NAME(state),
+                                        FULL, &found, ACL_HELO_NAME(state),
                                             SMTPD_NAME_HELO, def_acl);
        } else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
-           if (state->helo_name) {
-               if (*state->helo_name != '[')
-                   status = reject_invalid_hostname(state, state->helo_name,
-                                        state->helo_name, SMTPD_NAME_HELO);
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
+               if (*ACL_HELO_NAME(state) != '[')
+                   status = reject_invalid_hostname(state, ACL_HELO_NAME(state),
+                                    ACL_HELO_NAME(state), SMTPD_NAME_HELO);
                else
-                   status = reject_invalid_hostaddr(state, state->helo_name,
-                                        state->helo_name, SMTPD_NAME_HELO);
+                   status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
+                                    ACL_HELO_NAME(state), SMTPD_NAME_HELO);
            }
        } else if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
-           if (state->helo_name) {
-               if (*state->helo_name != '[')
-                   status = reject_unknown_hostname(state, state->helo_name,
-                                        state->helo_name, SMTPD_NAME_HELO);
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
+               if (*ACL_HELO_NAME(state) != '[')
+                   status = reject_unknown_hostname(state, ACL_HELO_NAME(state),
+                                    ACL_HELO_NAME(state), SMTPD_NAME_HELO);
                else
-                   status = reject_invalid_hostaddr(state, state->helo_name,
-                                        state->helo_name, SMTPD_NAME_HELO);
+                   status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
+                                    ACL_HELO_NAME(state), SMTPD_NAME_HELO);
            }
        } else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
            msg_warn("restriction %s is deprecated. Use %s instead",
                     PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS);
-           if (state->helo_name) {
-               if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
-               && (status = reject_invalid_hostaddr(state, state->helo_name,
-                                  state->helo_name, SMTPD_NAME_HELO)) == 0)
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
+               if (ACL_HELO_NAME(state)[strspn(ACL_HELO_NAME(state), "0123456789.")] == 0
+                   && (status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
+                              ACL_HELO_NAME(state), SMTPD_NAME_HELO)) == 0)
                    status = SMTPD_CHECK_OK;
            }
        } else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
-           if (state->helo_name) {
-               status = check_server_access(state, *cpp, state->helo_name,
-                                            T_NS, state->helo_name,
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
+               status = check_server_access(state, *cpp, ACL_HELO_NAME(state),
+                                            T_NS, ACL_HELO_NAME(state),
                                             SMTPD_NAME_HELO, def_acl);
-               forbid_whitelist(state, name, status, state->helo_name);
+               forbid_whitelist(state, name, status, ACL_HELO_NAME(state));
            }
        } else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) {
-           if (state->helo_name) {
-               status = check_server_access(state, *cpp, state->helo_name,
-                                            T_MX, state->helo_name,
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
+               status = check_server_access(state, *cpp, ACL_HELO_NAME(state),
+                                            T_MX, ACL_HELO_NAME(state),
                                             SMTPD_NAME_HELO, def_acl);
-               forbid_whitelist(state, name, status, state->helo_name);
+               forbid_whitelist(state, name, status, ACL_HELO_NAME(state));
            }
        } else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
-           if (state->helo_name) {
-               if (*state->helo_name != '[')
-                   status = reject_non_fqdn_hostname(state, state->helo_name,
-                                        state->helo_name, SMTPD_NAME_HELO);
+           if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
+               if (*ACL_HELO_NAME(state) != '[')
+                   status = reject_non_fqdn_hostname(state, ACL_HELO_NAME(state),
+                                    ACL_HELO_NAME(state), SMTPD_NAME_HELO);
                else
-                   status = reject_invalid_hostaddr(state, state->helo_name,
-                                        state->helo_name, SMTPD_NAME_HELO);
+                   status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
+                                    ACL_HELO_NAME(state), SMTPD_NAME_HELO);
            }
        } else if (strcasecmp(name, REJECT_RHSBL_HELO) == 0) {
            if (cpp[1] == 0)
@@ -3163,8 +3169,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
                         name);
            else {
                cpp += 1;
-               if (state->helo_name)
-                   status = reject_rbl_domain(state, *cpp, state->helo_name,
+               if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
+                   status = reject_rbl_domain(state, *cpp, ACL_HELO_NAME(state),
                                               SMTPD_NAME_HELO);
            }
        }
@@ -3361,7 +3367,7 @@ char   *smtpd_check_client(SMTPD_STATE *state)
     /*
      * Initialize.
      */
-    if (state->name == 0 || state->addr == 0)
+    if (ACL_NAME(state) == 0 || ACL_ADDR(state) == 0)
        return (0);
 
 #define SMTPD_CHECK_RESET() { \
@@ -3381,7 +3387,7 @@ char   *smtpd_check_client(SMTPD_STATE *state)
     SMTPD_CHECK_RESET();
     status = setjmp(smtpd_check_buf);
     if (status == 0 && client_restrctions->argc)
-       status = generic_checks(state, client_restrctions, state->namaddr,
+       status = generic_checks(state, client_restrctions, ACL_NAMADDR(state),
                                SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL);
     state->defer_if_permit_client = state->defer_if_permit.active;
 
@@ -3435,7 +3441,7 @@ char   *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
     SMTPD_CHECK_RESET();
     status = setjmp(smtpd_check_buf);
     if (status == 0 && helo_restrctions->argc)
-       status = generic_checks(state, helo_restrctions, state->helo_name,
+       status = generic_checks(state, helo_restrctions, ACL_HELO_NAME(state),
                                SMTPD_NAME_HELO, CHECK_HELO_ACL);
     state->defer_if_permit_helo = state->defer_if_permit.active;
 
@@ -3547,7 +3553,7 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
      */
     if (var_smtpd_delay_reject)
        if ((err = smtpd_check_client(state)) != 0
-           || (err = smtpd_check_helo(state, state->helo_name)) != 0
+           || (err = smtpd_check_helo(state, ACL_HELO_NAME(state))) != 0
            || (err = smtpd_check_mail(state, state->sender)) != 0)
            SMTPD_CHECK_RCPT_RETURN(err);
 
@@ -3616,7 +3622,7 @@ char   *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
      */
     if (var_smtpd_delay_reject)
        if ((err = smtpd_check_client(state)) != 0
-           || (err = smtpd_check_helo(state, state->helo_name)) != 0)
+           || (err = smtpd_check_helo(state, ACL_HELO_NAME(state))) != 0)
            SMTPD_CHECK_ETRN_RETURN(err);
 
     /*
@@ -4316,7 +4322,7 @@ int     main(int argc, char **argv)
                if (args->argc == 4)
                    state.peer_code = atoi(args->argv[3]);
                else
-                   state.peer_code = 2;
+                   state.peer_code = SMTPD_PEER_CODE_OK;
                if (state.namaddr)
                    myfree(state.namaddr);
                state.namaddr = concatenate(state.name, "[", state.addr,
index 583c6ebcc29577b925731682ed6d85b9b7b9ac65..28c127f2a5df9bcd223d24c007d03b88f6f71a91 100644 (file)
@@ -93,6 +93,7 @@ static int h_errno = TRY_AGAIN;
 
 /* Global library. */
 
+#include <mail_proto.h>
 
 /* Application-specific. */
 
@@ -124,9 +125,9 @@ void    smtpd_peer_init(SMTPD_STATE *state)
      * If peer went away, give up.
      */
     if (errno == ECONNRESET || errno == ECONNABORTED) {
-       state->name = mystrdup("unknown");
-       state->addr = mystrdup("unknown");
-       state->peer_code = 5;
+       state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+       state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+       state->peer_code = SMTPD_PEER_CODE_PERM;
     }
 
     /*
@@ -137,26 +138,27 @@ void    smtpd_peer_init(SMTPD_STATE *state)
        hp = gethostbyaddr((char *) &(sin.sin_addr),
                           sizeof(sin.sin_addr), AF_INET);
        if (hp == 0) {
-           state->name = mystrdup("unknown");
-           state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
+           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+           state->peer_code = (h_errno == TRY_AGAIN ?
+                               SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
        } else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
            msg_warn("numeric result %s in address->name lookup for %s",
                     hp->h_name, state->addr);
-           state->name = mystrdup("unknown");
-           state->peer_code = 5;
+           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+           state->peer_code = SMTPD_PEER_CODE_PERM;
        } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
-           state->name = mystrdup("unknown");
-           state->peer_code = 5;
+           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+           state->peer_code = SMTPD_PEER_CODE_PERM;
        } else {
            state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
-           state->peer_code = 2;
+           state->peer_code = SMTPD_PEER_CODE_OK;
 
            /*
             * Reject the hostname if it does not list the peer address.
             */
 #define REJECT_PEER_NAME(state, code) { \
        myfree(state->name); \
-       state->name = mystrdup("unknown"); \
+       state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
        state->peer_code = code; \
     }
 
@@ -164,17 +166,18 @@ void    smtpd_peer_init(SMTPD_STATE *state)
            if (hp == 0) {
                msg_warn("%s: hostname %s verification failed: %s",
                         state->addr, state->name, HSTRERROR(h_errno));
-               REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
+               REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ?
+                             SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
            } else if (hp->h_length != sizeof(sin.sin_addr)) {
                msg_warn("%s: hostname %s verification failed: bad address size %d",
                         state->addr, state->name, hp->h_length);
-               REJECT_PEER_NAME(state, 5);
+               REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
            } else {
                for (i = 0; /* void */ ; i++) {
                    if (hp->h_addr_list[i] == 0) {
                        msg_warn("%s: address not listed for hostname %s",
                                 state->addr, state->name);
-                       REJECT_PEER_NAME(state, 5);
+                       REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
                        break;
                    }
                    if (memcmp(hp->h_addr_list[i],
@@ -193,7 +196,7 @@ void    smtpd_peer_init(SMTPD_STATE *state)
     else {
        state->name = mystrdup("localhost");
        state->addr = mystrdup("127.0.0.1");    /* XXX bogus. */
-       state->peer_code = 2;
+       state->peer_code = SMTPD_PEER_CODE_OK;
     }
 
     /*
index ec532dddda6086938a43ff88c0d745ebfbbeebbb..3999c993bda422f9a71703131f4f34e064fe18a1 100644 (file)
 /*     have the same interface as the routines that are used for non-proxied
 /*     mail.
 /*
-/*     smtpd_proxy_open() should be called after receiving the MAIL FROM
-/*     command. It connects to the proxy service, sends EHLO, sends the
-/*     MAIL FROM command, and receives the reply. A non-zero result means
+/*     smtpd_proxy_open() connects to the proxy service, sends EHLO, sends
+/*     client information with the XCLIENT command if possible, sends
+/*     the MAIL FROM command, and receives the reply. A non-zero result means
 /*     trouble: either the proxy is unavailable, or it did not send the
 /*     expected reply.
-/*     All results are reported via the state->proxy_buffer field in a form
+/*     The result is reported via the state->proxy_buffer field in a form
 /*     that can be sent to the SMTP client. In case of error, the
 /*     state->error_mask and state->err fields are updated.
 /*     A state->proxy_buffer field is created automatically; this field
 #include <cleanup_user.h>
 #include <mail_params.h>
 #include <rec_type.h>
+#include <xtext.h>
+#include <mail_proto.h>
 
 /* Application-specific. */
 
 #define LEN(x) VSTRING_LEN(x)
 #define SMTPD_PROXY_CONNECT ((char *) 0)
 
-/* smtpd_proxy_open - open proxy connection after MAIL FROM */
+/* smtpd_proxy_open - open proxy connection */
 
 int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
                                 int timeout, const char *ehlo_name,
@@ -177,6 +179,8 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     int     fd;
     char   *lines;
     char   *line;
+    VSTRING *buf;
+    int     bad;
 
     /*
      * This buffer persists beyond the end of a proxy session so we can
@@ -205,7 +209,8 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
      * 
      * If this fails then we have a problem because the proxy should always
      * accept our connection. Make up our own response instead of passing
-     * back the greeting banner: the client expects a MAIL FROM reply.
+     * back the greeting banner: the proxy open might be delayed to the point
+     * that the client expects a MAIL FROM or RCPT TO reply.
      */
     if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONNECT) != 0) {
        vstring_sprintf(state->proxy_buffer,
@@ -217,8 +222,9 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     /*
      * Send our own EHLO command. If this fails then we have a problem
      * because the proxy should always accept our EHLO command. Make up our
-     * own response instead of passing back the EHLO reply: the client
-     * expects a MAIL FROM reply.
+     * own response instead of passing back the EHLO reply: the proxy open
+     * might be delayed to the point that the client expects a MAIL FROM or
+     * RCPT TO reply.
      */
     if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s", ehlo_name) != 0) {
        vstring_sprintf(state->proxy_buffer,
@@ -228,17 +234,46 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     }
 
     /*
-     * Parse the EHLO reply and see if we can forward the client hostname and
-     * address info for logging purposes. If the command fails, then proceed.
-     * It is not the end of the world.
+     * Parse the EHLO reply and see if we can forward logging information.
      */
+    state->proxy_features = 0;
     lines = STR(state->proxy_buffer);
     while ((line = mystrtok(&lines, "\n")) != 0)
        if (ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])
            && (line[3] == ' ' || line[3] == '-')
-           && strcmp(line + 4, XLOGINFO_CMD) == 0)
-           (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s %s %s",
-                                  XLOGINFO_CMD, state->addr, state->name);
+           && strcmp(line + 4, XCLIENT_EHLO) == 0)
+           state->proxy_features |= SMTPD_FEATURE_XCLIENT;
+
+    /*
+     * Send our XCLIENT attributes. Transform internal forms to external
+     * forms and encode the result as xtext.
+     */
+    if (state->proxy_features & SMTPD_FEATURE_XCLIENT) {
+       buf = vstring_alloc(100);
+       vstring_sprintf(buf, "%s LOG CLIENT_NAME=", XCLIENT_CMD);
+       if (!IS_UNK_CLNT_NAME(LOG_NAME(state)))
+           xtext_quote_append(buf, LOG_NAME(state), "");
+       vstring_strcat(buf, " CLIENT_ADDR=");
+       if (!IS_UNK_CLNT_ADDR(LOG_ADDR(state)))
+           xtext_quote_append(buf, LOG_ADDR(state), "");
+       bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
+       if (bad == 0) {
+           vstring_sprintf(buf, "%s HELO_NAME=", XCLIENT_CMD);
+           if (!IS_UNK_HELO_NAME(LOG_HELO_NAME(state)))
+               xtext_quote_append(buf, LOG_HELO_NAME(state), "");
+           vstring_strcat(buf, " PROTOCOL=");
+           if (!IS_UNK_PROTOCOL(LOG_PROTOCOL(state)))
+               xtext_quote_append(buf, LOG_PROTOCOL(state), "");
+           bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
+       }
+       vstring_free(buf);
+       if (bad) {
+           vstring_sprintf(state->proxy_buffer,
+                           "451 Error: queue file write error");
+           smtpd_proxy_close(state);
+           return (-1);
+       }
+    }
 
     /*
      * Pass-through the client's MAIL FROM command. If this fails, then we
index a0654384e0c6f76243a6ca38da84f849d981cded..4e412c50b7af5a2f5985c7ea363dddafa6aacc5f 100644 (file)
@@ -198,7 +198,7 @@ void    smtpd_sasl_mail_log(SMTPD_STATE *state)
 #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
 
     msg_info("%s: client=%s%s%s%s%s%s%s",
-            state->queue_id, state->namaddr,
+            state->queue_id, LOG_NAMADDR(state),
             IFELSE(state->sasl_method, ", sasl_method=", ""),
             IFELSE(state->sasl_method, state->sasl_method, ""),
             IFELSE(state->sasl_username, ", sasl_username=", ""),
index 53e805794096daa86ecc7acb7be666e0d15f4086..d5988b41681b67f79f9ab0e113d2f6d035ae5d48 100644 (file)
@@ -85,6 +85,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->history = 0;
     state->reason = 0;
     state->sender = 0;
+    state->verp_delims = 0;
     state->recipient = 0;
     state->etrn_name = 0;
     state->protocol = MAIL_PROTO_SMTP;
@@ -101,6 +102,8 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->expand_buf = 0;
     state->proxy = 0;
     state->proxy_buffer = 0;
+    state->proxy_mail = 0;
+    state->proxy_features = 0;
 
 #ifdef USE_SASL_AUTH
     if (SMTPD_STAND_ALONE(state))
@@ -114,6 +117,11 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
      */
     smtpd_peer_init(state);
 
+    /*
+     * Initialize xclient information.
+     */
+    smtpd_xclient_init(state);
+
     /*
      * Initialize the conversation history.
      */
@@ -133,6 +141,7 @@ void    smtpd_state_reset(SMTPD_STATE *state)
     if (state->buffer)
        vstring_free(state->buffer);
     smtpd_peer_reset(state);
+    smtpd_xclient_reset(state, XCLIENT_OVER_NONE);
     if (state->defer_if_permit.reason)
        vstring_free(state->defer_if_permit.reason);
     if (state->defer_if_reject.reason)
diff --git a/postfix/src/smtpd/smtpd_xclient.c b/postfix/src/smtpd/smtpd_xclient.c
new file mode 100644 (file)
index 0000000..75c92d9
--- /dev/null
@@ -0,0 +1,116 @@
+/*++
+/* NAME
+/*     smtpd_xclient 3
+/* SUMMARY
+/*     maintain XCLIENT information
+/* SYNOPSIS
+/*     #include "smtpd.h"
+/*
+/*     void    smtpd_xclient_init(state)
+/*     SMTPD_STATE *state;
+/*
+/*     void    smtpd_xclient_reset(state, mode)
+/*     SMTPD_STATE *state;
+/*     int     mode;
+/* DESCRIPTION
+/*     smtpd_xclient_init() initializes state variables that are
+/*     used for storage of XCLIENT command parameters.
+/*     These variables override specific members of the global state
+/*     structure for access control or logging purposes.
+/*
+/*     smtpd_xclient_reset() releases memory allocated after the return
+/*     from smtpd_xclient_init() and optionally presets the state variables 
+/*     to defaults that are suitable for the specified mode:
+/* .IP XCLIENT_OVER_NONE
+/*     This should be used after the XCLIENT RST request.
+/* .IP XCLIENT_OVER_ACL|XCLIENT_OVER_LOG
+/*     This should be used after the XCLIENT ACL request.
+/* .IP XCLIENT_OVER_LOG
+/*     This should be used after the XCLIENT LOG request.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <mymalloc.h>
+#include <msg.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+
+/* Application-specific. */
+
+#include <smtpd.h>
+
+/* smtpd_xclient_init - initialize XCLIENT attributes */
+
+void    smtpd_xclient_init(SMTPD_STATE *state)
+{
+    state->xclient.mode = 0;
+    state->xclient.name = 0;
+    state->xclient.addr = 0;
+    state->xclient.namaddr = 0;
+    state->xclient.peer_code = 0;
+    state->xclient.protocol = 0;
+    state->xclient.helo_name = 0;
+}
+
+/* smtpd_xclient_reset - reset XCLIENT attributes */
+
+void    smtpd_xclient_reset(SMTPD_STATE *state, int mode)
+{
+    switch (mode) {
+
+       /*
+        * Can't happen.
+        */
+    default:
+       msg_panic("smtpd_xclient_reset: unknown mode 0x%x", mode);
+
+       /*
+        * Restore smtpd_xclient_init() result. Allow selective override.
+        * This is desirable for access rule testing.
+        */
+#define FREE_AND_WIPE(s) { if (s) { myfree(s); s = 0; } }
+
+    case XCLIENT_OVER_NONE:
+    case XCLIENT_OVER_ACL | XCLIENT_OVER_LOG:
+       FREE_AND_WIPE(state->xclient.name);
+       FREE_AND_WIPE(state->xclient.addr);
+       FREE_AND_WIPE(state->xclient.namaddr);
+       state->xclient.peer_code = 0;
+       FREE_AND_WIPE(state->xclient.protocol);
+       FREE_AND_WIPE(state->xclient.helo_name);
+       break;
+
+       /*
+        * Non-selective override. Set all attributes to "unknown". This is
+        * desirable to avoid polluting the audit trail with data from mixed
+        * origins.
+        */
+#define FREE_AND_DUP(s,v) { if (s) { myfree(s); s = mystrdup(v); } }
+
+    case XCLIENT_OVER_LOG:
+       FREE_AND_DUP(state->xclient.name, CLIENT_NAME_UNKNOWN);
+       FREE_AND_DUP(state->xclient.addr, CLIENT_ADDR_UNKNOWN);
+       FREE_AND_DUP(state->xclient.namaddr, CLIENT_NAMADDR_UNKNOWN);
+       state->xclient.peer_code = 0;
+       FREE_AND_DUP(state->xclient.protocol, PROTOCOL_UNKNOWN);
+       FREE_AND_DUP(state->xclient.helo_name, HELO_NAME_UNKNOWN);
+       break;
+    }
+    state->xclient.mode = mode;
+}
index c541cdbaa57743365378e39a1d32e1365d9f51d4..d8dbd5ceb2b7e7bd8da0c01cf39502f306af669e 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = smtp-source.c smtp-sink.c qmqp-source.c qmqp-sink.c
 OBJS   = smtp-source.o smtp-sink.o qmqp-source.o qmqp-sink.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 95fcb3e31251fae012846fe249cfd4a8a6aed9af..3a1cdb12e92784bfc829cc1b04eb3f9a09bad38e 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = spawn.c
 OBJS   = spawn.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 556aaf047de2ceab5055f6a56491384d6b6468f1..94f6d89aadccd6b237a819f442c093f1c70eaff2 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = trivial-rewrite.c rewrite.c resolve.c transport.c
 OBJS   = trivial-rewrite.o rewrite.o resolve.o transport.o
 HDRS   = 
 TESTSRC        = 
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 LIB    = 
index 5dc045801a2c7f257edf7a7137e91869e10110c0..efdd532e4e0cdd3ca41b9d87ff30e70204dcf4a7 100644 (file)
@@ -27,7 +27,7 @@ SRCS  = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
        username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
        vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
        write_buf.c write_wait.c auto_clnt.c attr_clnt.c attr_scan_plain.c \
-       attr_print_plain.c sane_connect.c
+       attr_print_plain.c sane_connect.c neuter.c
 OBJS   = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
        attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
        chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
@@ -56,7 +56,7 @@ OBJS  = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
        username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
        vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
        write_buf.o write_wait.o auto_clnt.o attr_clnt.o attr_scan_plain.o \
-       attr_print_plain.o sane_connect.o $(STRCASE)
+       attr_print_plain.o sane_connect.o $(STRCASE) neuter.o
 HDRS   = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
        connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
        dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
@@ -78,9 +78,6 @@ HDRS  = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
        auto_clnt.h attr_clnt.h sane_connect.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c dup2_pass_on_exec.c
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 FILES  = Makefile $(SRCS) $(HDRS)
@@ -1046,6 +1043,11 @@ netstring.o: vstream.h
 netstring.o: vbuf.h
 netstring.o: vstring.h
 netstring.o: netstring.h
+neuter.o: neuter.c
+neuter.o: sys_defs.h
+neuter.o: stringops.h
+neuter.o: vstring.h
+neuter.o: vbuf.h
 non_blocking.o: non_blocking.c
 non_blocking.o: sys_defs.h
 non_blocking.o: msg.h
diff --git a/postfix/src/util/neuter.c b/postfix/src/util/neuter.c
new file mode 100644 (file)
index 0000000..1d0279e
--- /dev/null
@@ -0,0 +1,56 @@
+/*++
+/* NAME
+/*     neuter 3
+/* SUMMARY
+/*     mask non-neuter characters
+/* SYNOPSIS
+/*     #include <stringops.h>
+/*
+/*     char    *neuter(buffer, bad, replacement)
+/*     char    *buffer;
+/*     const char *bad;
+/*     int     replacement;
+/* DESCRIPTION
+/*     neuter() replaces bad characters in its input
+/*     by the given replacement.
+/*
+/*     Arguments:
+/* .IP buffer
+/*     The null-terminated input string.
+/* .IP bad
+/*     The null-terminated bad character string.
+/* .IP replacement
+/*     Replacement value for characters in \fIbuffer\fR that do not
+/*     pass the  bad character test.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <stringops.h>
+
+/* neuter - neutralize bad characters */
+
+char   *neuter(char *string, const char *bad, int replacement)
+{
+    char   *cp;
+    int     ch;
+
+    for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++)
+       if (strchr(bad, ch) != 0)
+           *cp = replacement;
+    return (string);
+}
index 0cd80c797d13158a6e5cd6b83a40b54b07aa8f98..1f05045fcd412f5bea5a5c9b8067e3f9da4da4e5 100644 (file)
@@ -20,6 +20,7 @@
   * External interface.
   */
 extern char *printable(char *, int);
+extern char *neuter(char *, const char *, int);
 extern char *lowercase(char *);
 extern char *skipblanks(const char *);
 extern char *trimblanks(char *, int);
index 4ea98c931e9e199431ce74b347b5e8415687dacd..6d556e257399869abe8d79b7d4b00146911fe8cf 100644 (file)
 #define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
 #endif
 
-#if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4)
+/* __FreeBSD_version version is major+minor */
+
+#if __FreeBSD_version >= 200000
 #define HAS_DUPLEX_PIPE
+#define HAS_ISSETUGID
 #endif
 
-#if defined(OPENBSD2) || defined(OPENBSD3) \
-    || defined(FREEBSD3) || defined(FREEBSD4)
+#if __FreeBSD_version >= 400000
+#define SOCKADDR_SIZE  socklen_t
+#define SOCKOPT_SIZE   socklen_t
+#endif
+
+/* OpenBSD version is year+month */
+
+#if OpenBSD >= 200000                  /* XXX */
 #define HAS_ISSETUGID
 #endif
 
-#if defined(NETBSD1)
+#if OpenBSD >= 200200                  /* XXX */
+#define SOCKADDR_SIZE  socklen_t
+#define SOCKOPT_SIZE   socklen_t
+#endif
+
+/* __NetBSD_Version__ is major+minor */
+
+#if __NetBSD_Version__ >= 103000000    /* XXX */
 #undef DEF_MAILBOX_LOCK
 #define DEF_MAILBOX_LOCK "flock, dotlock"
+#endif
+
+#if __NetBSD_Version__ >= 106000000    /* XXX */
+#define SOCKADDR_SIZE  socklen_t
+#define SOCKOPT_SIZE   socklen_t
 #endif
 
  /*
@@ -493,6 +514,7 @@ extern int initgroups(const char *, int);
 #ifdef LINUX2
 #define SUPPORTED
 #include <sys/types.h>
+#include <features.h>
 #define USE_PATHS_H
 #define HAS_FLOCK_LOCK
 #define HAS_FCNTL_LOCK
@@ -516,6 +538,10 @@ extern int initgroups(const char *, int);
 #define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
 #define NATIVE_COMMAND_DIR "/usr/sbin"
 #define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+#define SOCKADDR_SIZE  socklen_t
+#define SOCKOPT_SIZE   socklen_t
+#endif
 #endif
 
 #ifdef LINUX1
@@ -908,6 +934,9 @@ extern int dup2_pass_on_exec(int oldd, int newd);
 #endif
 #define OPTIND  (optind > 0 ? optind : 1)
 
+ /*
+  * Check for required but missing definitions.
+  */
 #if !defined(HAS_FCNTL_LOCK) && !defined(HAS_FLOCK_LOCK)
 #error "define HAS_FCNTL_LOCK and/or HAS_FLOCK_LOCK"
 #endif
@@ -929,7 +958,7 @@ extern int dup2_pass_on_exec(int oldd, int newd);
 #endif
 
  /*
-  * Defaults for normal systems.
+  * Defaults for systems that pre-date POSIX socklen_t.
   */
 #ifndef SOCKADDR_SIZE
 #define SOCKADDR_SIZE  int
@@ -939,6 +968,9 @@ extern int dup2_pass_on_exec(int oldd, int newd);
 #define SOCKOPT_SIZE   int
 #endif
 
+ /*
+  * Defaults for normal systems.
+  */
 #ifndef LOCAL_LISTEN
 #define LOCAL_LISTEN   unix_listen
 #define LOCAL_ACCEPT   unix_accept
index 169affba0d941c40ab169db07bbbcadf17624ea1..2daf6659e657d14c2b6aa1f2236bcef417288abd 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = verify.c
 OBJS   = verify.o
 HDRS   = 
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
index 7ab0308559461bbce19a1977cb85ab26ebc4831b..e439102f9cd9d1daf884dcd69561752e640d3e45 100644 (file)
@@ -3,9 +3,6 @@ SRCS    = virtual.c mailbox.c recipient.c deliver_attr.c maildir.c unknown.c
 OBJS   = virtual.o mailbox.o recipient.o deliver_attr.o maildir.o unknown.o
 HDRS   = virtual.h
 TESTSRC        =
-WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
-       -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-       -Wunused
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 PROG   = virtual