]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.0.16-20031213
authorWietse Venema <wietse@porcupine.org>
Sat, 13 Dec 2003 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:29:18 +0000 (06:29 +0000)
43 files changed:
postfix/HISTORY
postfix/README_FILES/XCLIENT_README
postfix/conf/sample-auth.cf
postfix/conf/sample-smtp.cf
postfix/conf/sample-smtpd.cf
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/html/uce.html
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/src/global/Makefile.in
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_proto.h
postfix/src/global/mail_queue.c
postfix/src/global/mail_version.h
postfix/src/global/peer_name.c [deleted file]
postfix/src/global/peer_name.h [deleted file]
postfix/src/global/recipient_list.c
postfix/src/nqmgr/qmgr_rcpt_list.c
postfix/src/qmgr/qmgr_rcpt_list.c
postfix/src/qmqpd/qmqpd.c
postfix/src/qmqpd/qmqpd.h
postfix/src/qmqpd/qmqpd_peer.c
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_proxy.c
postfix/src/smtpd/smtpd_state.c
postfix/src/smtpd/smtpd_xclient.c [deleted file]
postfix/src/smtpd/smtpd_xforward.c [new file with mode: 0644]
postfix/src/smtpstone/smtp-source.c
postfix/src/util/argv.c
postfix/src/util/inet_addr_list.c
postfix/src/util/intv.c
postfix/src/util/mvect.c
postfix/src/util/name_code.c
postfix/src/util/name_code.h
postfix/src/util/vstring.c

index d11a0b4ae44704ce71c0ded7a0dbd8245f428bf1..1a06f19e7ac0e6e0853808df0d2faac3db702a79 100644 (file)
@@ -8812,11 +8812,26 @@ Apologies for any names omitted.
        Minor cleanups of the xclient error messages; xclient
        command lookup tables. File: smtpd/smtpd.c.
 
+20031206
+
+       Feature: reject_sender_login_mismatch allows multiple owners
+       of a sender address.  Code by Liviu Daia.  Files:
+       smtpd/smtpd_check.c and documentation.
+
+       The reject_sender_login_mismatch feature is now implemented
+       by elementary features reject_unauth_sender_login_mismatch
+       (reject if the client is not SASL logged in but the sender
+       address has an owner in smtpd_sender_login_maps) and
+       reject_auth_sender_login_mismatch (reject if the client is
+       SASL logged in but does not own the sender address).  Code
+       by Liviu Daia.  Files: smtpd/smtpd_check.c and documentation.
+
 20031207
 
        Bugfix: fallback_transport and mailbox_transport were broken
        because the deliver_pass.c module was not updated for the
        changed message delivery protocol.
+
 Open problems:
 
        High: when virtual aliasing is turned off after content
@@ -8884,3 +8899,6 @@ Open problems:
 
        Low: with quoted-printable, perhaps use =46rom instead of
        >From.
+
+       virtual_mailbox_path expression like forward_path, so that
+       people can specify prefix and suffix.
index 258048b471a8cea6598bf4728363bff4ff6ab3c2..3077aed91c3164b4ad3b2418f2f76cf40c2a2319 100644 (file)
@@ -25,19 +25,23 @@ the filter can override the MTA's idea of the SMTP client hostname,
 network address, and other information, for the entire duration of
 an SMTP session.
 
+4 - Fetchmail.
+
 Command overview
 ================
 
-The EHLO keyword associated with this extension is XCLIENT.
+The EHLO keyword associated with this extension is XCLIENT. In EHLO
+replies, XCLIENT is followed by the names of the supported XCLIENT
+functions.
 
-The XCLIENT OVERRIDE command updates remote client attributes that
+The XCLIENT OVERRIDE function updates remote client attributes that
 the MTA normally uses for access control, message headers, logging
 and so on, for the duration of an entire SMTP session.
 
-The XCLIENT FORWARD command updates temporary remote client attributes
-that the MTA uses for transaction logging. These attributes are
-valid for only one message delivery attempt.  In the absence of
-forwarded attributes the MTA must use the normal remote client
+The XCLIENT FORWARD function updates temporary remote client
+attributes that the MTA uses for transaction logging. These attributes
+are valid for only one message delivery attempt.  In the absence
+of forwarded attributes the MTA must use the normal remote client
 attribute values.
 
 The general command syntax is described below.  Upper case and
@@ -52,7 +56,7 @@ case, they are in fact case insensitive.
 
     attribute = name"="value
 
-    name = ( CLIENT_NAME|CLIENT_ADDR|CLIENT_CODE|CLIENT_PROTO|CLIENT_HELO )
+    name = ( NAME|ADDR|CODE|PROTO|HELO )
 
     value = ( { empty } | xtext )
 
@@ -91,8 +95,8 @@ The following example overrides only the client hostname and network
 address, leaving unchanged all other client attributes such as the
 mail protocol or the hostname given in the HELO command:
 
-    XCLIENT OVERRIDE CLIENT_NAME=spike.porcupine.org
-    XCLIENT OVERRIDE CLIENT_ADDR=168.100.189.2
+    XCLIENT OVERRIDE NAME=spike.porcupine.org
+    XCLIENT OVERRIDE ADDR=168.100.189.2
 
 The XCLIENT FORWARD request specifies remote client attributes that
 are logged with one message delivery attempt. The attributes are
@@ -109,8 +113,8 @@ The following example updates all forwarded client attributes that
 are defined in this document, leaving none at their default unknown
 value:
 
-    XCLIENT FORWARD CLIENT_NAME=spike.porcupine.org CLIENT_ADDR=168.100.189.2
-    XCLIENT FORWARD CLIENT_HELO=spike.porcupine.org CLIENT_PROTO=ESMTP
+    XCLIENT FORWARD NAME=spike.porcupine.org ADDR=168.100.189.2
+    XCLIENT FORWARD HELO=spike.porcupine.org PROTO=ESMTP
 
 Note 1: attributes specified with successive XCLIENT commands
 accumulate.
@@ -126,32 +130,33 @@ specify that an attribute value is unavailable, the value must be
 empty; the client must not send its own internal representation of
 unavailable information.
 
-The CLIENT_CODE attribute 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
-automatically set to the unknown value.
+The NAME_CODE attribute specifies NAME hostname lookup status
+information.  Values are OK (success), TEMP (temporary lookup
+failure) or PERM (permanent lookup failure). When CODE is set to
+any value other than OK, the NAME attribute is automatically set
+to the unknown value.
 
-The CLIENT_NAME attribute 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 implicitly set to PERM. When a valid domain name is
-specified, CLIENT_CODE is implicitly set to OK. The server may
-process a syntactically invalid domain name as if it were unknown.
+The NAME attribute specifies a name space (typically, DNS) and
+an MTA name within that name space.
+and not a numerical address.  When a null client name is specified
+(i.e.  the client name is unknown), the CODE attribute is implicitly
+set to PERM. When a valid domain name is specified, CODE is implicitly
+set to OK. The server may process a syntactically invalid domain
+name as if it were unknown.
 
-The CLIENT_ADDR attribute must specify a numerical network address
-without [].
+The ADDR attribute must specify a numerical network address without
+[].
 
-The CLIENT_PROTO attribute should be a string of up to 64 printable
+The PROTO attribute should be a string of up to 64 printable
 characters, where printable is defined by the ANSI C isascii() and
 isprint() predicates.
 
-The CLIENT_HELO attribute should be a syntactically valid HELO
+The HELO attribute should be a syntactically valid HELO
 parameter value.
 
-Note 3: syntactically valid CLIENT_NAME and CLIENT_HELO 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 3: syntactically valid NAME and HELO 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 4: attribute values may end up in Received: or other message
 headers.  The receiving MTA may substitute characters in order to
index 7d3943241c6539b4c42791dd0cfc98461baf8d51..e44ec0abc4aa06acf63f539ad5a4d023696e1470 100644 (file)
@@ -19,7 +19,7 @@
 # To reject all SMTP connections from unauthenticated clients,
 # specify smtpd_delay_reject=yes (which is the default) and use:
 #
-#      smtpd_client_restrictions = permit_sasl_authenticated
+#      smtpd_client_restrictions = permit_sasl_authenticated, reject
 #
 # In order to enable server-side authentication, build Postfix with
 # SASL support, and install a configuration file /usr/lib/sasl/smtpd.conf
index e55b5ca20931617fa280d7f5c422218fd1547d9a..6812f14aac07c36837a4a2f7c4cd838eba1a6eef 100644 (file)
@@ -76,16 +76,16 @@ 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.
+# The smtp_send_xforward_command parameter controls whether the Postfix
+# SMTP client will send an XFORWARD command to the SMTP server, when
+# the ESMTP HELO response of the remote host indicates XFORWARD 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
+smtp_send_xforward_command = no
 
 # The smtp_line_length_limit parameter controls the length of
 # message header and body lines that Postfix will send via SMTP.
@@ -237,10 +237,9 @@ smtp_connect_timeout = 30s
 #
 smtp_helo_timeout = 300s
 
-# The smtp_xclient_timeout parameter specifies the SMTP client timeout
-# for sending the SMTP XCLIENT command, and for receiving the server
+# The smtp_xforward_timeout parameter specifies the SMTP client timeout
+# for sending the SMTP XFORWARD command, and for receiving the server
 # response.
-# for receiving the SMTP greeting banner.
 #
 # In case of problems the client does NOT try the next address on
 # the mail exchanger list.
@@ -248,7 +247,7 @@ smtp_helo_timeout = 300s
 # Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
 # The default time unit is s (seconds).
 #
-smtp_xclient_timeout = 300s
+smtp_xforward_timeout = 300s
 
 # The smtp_mail_timeout parameter specifies the SMTP client timeout
 # for sending the SMTP MAIL FROM command, and for receiving the server
index 0770765024675d8a635bc40aa748e61371347914..720d3d99d19edb4f733fb66ccce4ffdbdb64148a 100644 (file)
@@ -78,25 +78,25 @@ unknown_local_recipient_reject_code = 550
 #
 
 # The smtpd_sender_login_maps parameter specifies the (SASL) login
-# name that owns a sender (MAIL FROM) address.
+# names that own sender (MAIL FROM) addresses.
 #
 # Specify zero or more maptype:mapname entries. Maps are created with
 # postmap(1) or with equivalent means. The maps are searched in the
 # specified order. Regexp tables are allowed.
 #
-# Each map entry specifies a sender address and the login name that
-# owns the address. The search order is:
+# Each map entry specifies a sender address and a list of login names
+# that owns the address. The search order is:
 #
-# 1)  user@domain owner
+# 1)  user@domain      owner, owner, ...
 #
 # This form has the highest precedence.
 #
-# 2)  user        owner
+# 2)  user             owner, owner, ...
 #
 # This matches user@site when site is equal to $myorigin, when site
 # is listed in $mydestination, or when it is listed in $inet_interfaces.
 #
-# 3)  @domain     owner
+# 3)  @domain          owner, owner, ...
 #
 # This matches every address in the specified domain, and has the
 # lowest precedence.
@@ -158,8 +158,8 @@ smtpd_client_connection_limit_exceptions = $mynetworks
 # are allowed to specify the XCLIENT extension to SMTP.
 #
 # 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.
+# logging and access control. Typical use is for SMTP-based content
+# filters, fetchmail-like programs, or SMTP server access rule testing.
 #
 # By default, no clients are allowed to specify XCLIENT.
 #
@@ -174,6 +174,25 @@ smtpd_client_connection_limit_exceptions = $mynetworks
 #
 smtpd_authorized_xclient_hosts =
 
+# The smtpd_authorized_xforward_hosts parameter specifies what clients
+# are allowed to specify the XFORWARD extension to SMTP.
+#
+# This command forwards information that is used to improve logging
+# after SMTP-based content filters.
+#
+# By default, no clients are allowed to specify XFORWARD.
+#
+# 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_xforward_hosts =
+
 # The smtpd_authorized_verp_clients parameter specifies what clients
 # are allowed to specify the SMTP XVERP command. This command requests
 # that mail be delivered one recipient at a time with a per recipient
@@ -487,11 +506,22 @@ smtpd_helo_restrictions =
 #      look up sender address MX hosts (or name servers) and apply the
 #      specified access table to those hosts.
 #      Note: the OK result is not allowed here for security reasons.
-#   reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies
-#      a MAIL FROM address owner, but the client is not (SASL) logged in as
-#      that MAIL FROM address owner; or if the client is (SASL) logged in, but
-#      the client login name doesn't own the MAIL FROM address according to
-#      $smtpd_sender_login_maps (see above).
+#   reject_sender_login_mismatch: 
+#      reject if $smtpd_sender_login_maps specifies a MAIL FROM
+#      address owner, but the client is not (SASL) logged in as
+#      that MAIL FROM address owner; or if the client is (SASL)
+#      logged in, but the client login name doesn't own the MAIL
+#      FROM address.
+#   reject_authenticated_sender_login_mismatch:
+#      reject if the client is (SASL) logged in, but the client
+#      login name doesn't own the MAIL FROM address according to
+#      $smtpd_sender_login_maps (see above). This still allows
+#      unauthenticated clients to impersonate the sender.
+#   reject_unauthenticated_sender_login_mismatch:
+#      reject if $smtpd_sender_login_maps specifies a MAIL FROM
+#      address owner, but the client is not (SASL) logged in.
+#      This prevents unauthenticated clients from impersonating
+#      the sender.
 #   reject_non_fqdn_sender: reject sender address that is not in FQDN form
 #   check_policy_service transport:endpoint: delegate the decision to
 #      an external policy server. See SMTPD_POLICY_README for details.
@@ -545,7 +575,7 @@ smtpd_sender_restrictions =
 #        $virtual_alias_domains, or $virtual_mailbox_domains.
 #      - to destinations matching $relay_domains or subdomain thereof,
 #        except for addresses with sender-specified routing.
-#   reject_unauth_destination: reject mail unless it is sent
+#  *reject_unauth_destination: reject mail unless it is sent
 #      - to destinations matching $inet_interfaces, $mydestination,
 #        $virtual_alias_domains, or $virtual_mailbox_domains.
 #      - to destinations matching $relay_domains or subdomain thereof,
index eb8f02874970456a5c906f94001556f7f7c6ef72..0a3c3287aa04c4d732bfda9de3700084292c1245 100644 (file)
@@ -249,8 +249,8 @@ 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
+       <b>smtp_xforward_timeout</b>
+              Timeout  for  sending the <b>XFORWARD</b> command, and for
               receiving the server response.
 
        <b>smtp_mail_timeout</b>
@@ -281,8 +281,8 @@ SMTP(8)                                                   SMTP(8)
               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
+       <b>smtp_send_xforward_command</b>
+              If the SMTP server announces XFORWARD 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-
index 9aefc27f1825780c91478550f93e2cfb449ba1e4..160306934a249a78ef45dad6ded377d75a134551 100644 (file)
@@ -163,7 +163,13 @@ SMTPD(8)                                                 SMTPD(8)
               Maps  that  specify the SASL login name that owns a
               MAIL   FROM   sender   address.   Used    by    the
               <b>reject_sender_login_mismatch</b>  sender  anti-spoofing
-              restriction.
+              restriction, as well as by its  component  restric-
+              tions    <b>reject_authenticated_sender_login_mismatch</b>
+              (an authenticated client  can't  use  a  MAIL  FROM
+              sender  address  that is owned by someone else) and
+              <b>reject_unauthenticated_sender_login_mismatch</b>     (a
+              client  must  be  authenticated in order to use the
+              MAIL FROM sender address).
 
 <b>Miscellaneous</b>
        <b>smtpd_authorized_verp_clients</b>
@@ -173,29 +179,35 @@ SMTPD(8)                                                 SMTPD(8)
        <b>smtpd_authorized_xclient_hosts</b>
               Hostnames, domain names and/or addresses of clients
               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.
+              This   command  overrides  client  information  for
+              access  control  and  logging  purposes,  with  the
+              exception   of  the  <b>smtpd_authorized_xclient_hosts</b>
+              access control itself.
+
+       <b>smtpd_authorized_xforward_hosts</b>
+              Hostnames, domain names and/or addresses of clients
+              that  are  authorized  to use the XFORWARD command.
+              This command accepts client and message identofying
+              information for logging purposes.
 
        <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>
@@ -204,18 +216,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>
@@ -223,57 +235,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>
@@ -281,9 +293,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>
@@ -293,21 +305,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.
 
@@ -318,17 +330,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>
@@ -337,17 +349,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>
@@ -355,19 +367,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>
@@ -375,96 +387,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>
@@ -472,7 +484,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>
@@ -481,15 +493,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>
@@ -500,7 +512,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 4392efa21e9b501196bf163bf60a077a7d753e03..afa38f2d062bd5d6150867739899173a66f7c1f3 100644 (file)
@@ -829,11 +829,30 @@ response code to rejected requests (default:  <b>504</b>).
 <dt> <b>reject_sender_login_mismatch</b>
 
 <dd> Reject the request when <a href="#smtpd_sender_login_maps">
-$smtpd_sender_owner_maps</a> specifies an owner for the MAIL FROM
+$smtpd_sender_login_maps</a> specifies an owner for the MAIL FROM
 address, but the client is not (SASL) logged in as that MAIL FROM
 address owner; or when the client is (SASL) logged in, but the
-client login name doesn't own the MAIL FROM address according to
-<a href="#smtpd_sender_login_maps"> $smtpd_sender_login_maps</a>.
+client login name doesn't own the MAIL FROM address.
+
+<p>
+
+<a name="reject_authenticated_sender_login_mismatch">
+
+<dt> <b>reject_authenticated_sender_login_mismatch</b>
+
+<dd> Reject the request when the client is (SASL) logged in but
+the client login name doesn't own the MAIL FROM address according
+to <a href="#smtpd_sender_login_maps">$smtpd_sender_login_maps</a>.
+
+<p>
+
+<a name="reject_unauthenticated_sender_login_mismatch">
+
+<dt> <b>reject_unauthenticated_sender_login_mismatch</b>
+
+<dd> Reject the request when <a href="#smtpd_sender_login_maps">
+$smtpd_sender_login_maps</a> specifies an owner for the address,
+but the client is not (SASL) logged in.
 
 <p>
 
@@ -1583,8 +1602,13 @@ tables listed in <b>$relay_domains.</b>
 <dt> <b>smtpd_sender_login_maps</b>
 
 <dd>This parameter specifies ownership of MAIL FROM addresses, as
-used by the <a href="#reject_sender_login_mismatch">
-reject_sender_login_mismatch</a> sender address restriction.
+used by the <a
+href="#reject_sender_login_mismatch">reject_sender_login_mismatch</a>
+anti-spoofing restriction and by its component sender address
+restrictions:  <a href="#reject_authenticated_sender_login_mismatch">
+reject_authenticated_sender_login_mismatch</a> and <a
+href="#reject_unauthenticated_sender_login_mismatch">
+reject_unauthenticated_sender_login_mismatch</a>.
 
 <p>
 
@@ -1604,30 +1628,31 @@ specified order. Regexp tables are allowed.
 
 <p>
 
-Each map entry specifies a sender address and the login name that
-owns the address. The search order is:
+Each map entry specifies a sender address and a list of login names
+(separated by whitespace and/or commas) that owns the address. The
+search order is:
 
 <p>
 
 <dl>
 
-<dt><i>user@domain owner</i>
+<dt><i>user@domain</i> &nbsp; <i>owner, owner, ...</i>
 
 <dd>This form has the highest precedence.
 
 <p>
 
-<dt><i>user        owner</i>
+<dt><i>user</i> &nbsp; <i>owner, owner, ...</i>
 
-<dd>This matches <i>user@site</i> when <i>site</i> is equal to <a
-href="basic.html#myorigin"> $myorigin</a>, when <i>site</i> is
+<dd>This matches <i>user@site</i> when <i>site</i> is equal to
+<a href="basic.html#myorigin"> $myorigin</a>, when <i>site</i> is
 listed in <a href="basic.html#mydestination"> $mydestination</a>,
 or when it is listed in <a href="basic.html#inet_interfaces">
 $inet_interfaces</a>.
 
 <p>
 
-<dt><i>@domain     owner</i>
+<dt><i>@domain</i> &nbsp; <i>owner, owner, ...</i>
 
 <dd>This matches every address in the specified domain, and has
 the lowest precedence.
index c585f4945e73cd394b13b6cc6438157f31a6b383..d830dab2be8d85b85e91377579ebf0f13820759f 100644 (file)
@@ -210,8 +210,8 @@ 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
+.IP \fBsmtp_xforward_timeout\fR
+Timeout for sending the \fBXFORWARD\fR command, and for
 receiving the server response.
 .IP \fBsmtp_mail_timeout\fR
 Timeout for sending the \fBMAIL FROM\fR command, and for
@@ -234,8 +234,8 @@ 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,
+.IP \fBsmtp_send_xforward_command\fR
+If the SMTP server announces XFORWARD 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.
index f4466b7b6c141601422df2023e3bf88c6ede9f3e..c96da05071c04c6af88ad6d3ef8309ab709e7daf 100644 (file)
@@ -150,7 +150,11 @@ Disallow anonymous logins.
 .IP \fBsmtpd_sender_login_maps\fR
 Maps that specify the SASL login name that owns a MAIL FROM sender
 address. Used by the \fBreject_sender_login_mismatch\fR sender
-anti-spoofing restriction.
+anti-spoofing restriction, as well as by its component restrictions
+\fBreject_authenticated_sender_login_mismatch\fR (an authenticated
+client can't use a MAIL FROM sender address that is owned by someone
+else) and \fBreject_unauthenticated_sender_login_mismatch\fR (a client
+must be authenticated in order to use the MAIL FROM sender address).
 .SH Miscellaneous
 .ad
 .fi
@@ -159,10 +163,14 @@ Hostnames, domain names and/or addresses of clients that are
 authorized to use the XVERP extension.
 .IP \fBsmtpd_authorized_xclient_hosts\fR
 Hostnames, domain names and/or addresses of clients that are
-authorized to use the XCLIENT command.  This command changes
-client information for access control and/or logging purposes,
+authorized to use the XCLIENT command.  This command overrides
+client information for access control and logging purposes,
 with the exception of the
 \fBsmtpd_authorized_xclient_hosts\fR access control itself.
+.IP \fBsmtpd_authorized_xforward_hosts\fR
+Hostnames, domain names and/or addresses of clients that are
+authorized to use the XFORWARD command.  This command accepts
+client and message identofying information for logging purposes.
 .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 dc95fda3337003e58b79006585ce49027dd92b63..951071b9548d7aa56859aadff14e079c13335c16 100644 (file)
@@ -210,11 +210,6 @@ local_transport: $(LIB) $(LIBS)
 quote_821_local: quote_821_local.c $(LIBS)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
 
-peer_name: $(LIB)
-       mv $@.o junk
-       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
-       mv junk $@.o
-
 mail_conf_time: $(LIB) $(LIBS)
        mv $@.o junk
        $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
@@ -1079,11 +1074,6 @@ own_inet_addr.o: ../../include/vstring.h
 own_inet_addr.o: ../../include/vbuf.h
 own_inet_addr.o: mail_params.h
 own_inet_addr.o: own_inet_addr.h
-peer_name.o: peer_name.c
-peer_name.o: ../../include/sys_defs.h
-peer_name.o: ../../include/msg.h
-peer_name.o: ../../include/valid_hostname.h
-peer_name.o: peer_name.h
 pipe_command.o: pipe_command.c
 pipe_command.o: ../../include/sys_defs.h
 pipe_command.o: ../../include/msg.h
index aa81791d088b19385363ea1713bf41d9a58973ec..1bd415a1c656c670f41c7958be3e2d644282b779 100644 (file)
@@ -608,18 +608,19 @@ void    mail_params_init()
      * I have seen this happen just too often.
      */
     if (strcasecmp(var_myhostname, var_relayhost) == 0)
-       msg_fatal("myhostname == relayhost");
+       msg_fatal("%s and %s parameter settings must not be identical: %s",
+                 VAR_MYHOSTNAME, VAR_RELAYHOST, var_myhostname);
 
     /*
      * XXX These should be caught by a proper parameter parsing algorithm.
      */
     if (var_myorigin[strcspn(var_myorigin, ", \t\r\n")])
-       msg_fatal("myorigin parameter setting contains multiple values: %s",
-                 var_myorigin);
+       msg_fatal("%s parameter setting must not contain multiple values: %s",
+                 VAR_MYORIGIN, var_myorigin);
 
     if (var_relayhost[strcspn(var_relayhost, ", \t\r\n")])
-       msg_fatal("relayhost parameter setting contains multiple values: %s",
-                 var_relayhost);
+       msg_fatal("%s parameter setting must not contain multiple values: %s",
+                 VAR_RELAYHOST, var_relayhost);
 
     /*
      * One more sanity check.
index 260e61ecfba32f4e9f1801d8f5a31fcb2ca35ffe..0a7aa988ded7eba9e2c2f851cdfdd17d0b73427f 100644 (file)
@@ -845,9 +845,9 @@ 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;
+#define VAR_SMTP_SEND_XFORWARD "smtp_send_xforward_command"
+#define DEF_SMTP_SEND_XFORWARD 0
+extern bool var_smtp_send_xforward;
 
  /*
   * SMTP server. The soft error limit determines how many errors an SMTP
@@ -910,6 +910,10 @@ extern char *var_smtpd_sasl_realm;
 extern char *var_smtpd_snd_auth_maps;
 
 #define REJECT_SENDER_LOGIN_MISMATCH   "reject_sender_login_mismatch"
+#define REJECT_AUTH_SENDER_LOGIN_MISMATCH \
+                               "reject_authenticated_sender_login_mismatch"
+#define REJECT_UNAUTH_SENDER_LOGIN_MISMATCH \
+                               "reject_unauthenticated_sender_login_mismatch"
 
  /*
   * SASL authentication support, SMTP client side.
@@ -1575,12 +1579,19 @@ extern bool var_verp_bounce_off;
 extern char *var_verp_clients;
 
  /*
-  * XCLIENT, for rule testing and improved post-filter logging.
+  * XCLIENT, for rule testing and fetchmail like apps.
   */
 #define VAR_XCLIENT_HOSTS              "smtpd_authorized_xclient_hosts"
 #define DEF_XCLIENT_HOSTS              ""
 extern char *var_xclient_hosts;
 
+ /*
+  * XFORWARD, for improved post-filter logging.
+  */
+#define VAR_XFORWARD_HOSTS             "smtpd_authorized_xforward_hosts"
+#define DEF_XFORWARD_HOSTS             ""
+extern char *var_xforward_hosts;
+
  /*
   * Inbound mail flow control. This allows for a stiffer coupling between
   * receiving mail and sending mail. A sending process produces one token for
index d6018d006b52ba8f1d40597b8973385624f959ce..96bbd1cab783093b0b6221f23d86da25db0e140f 100644 (file)
@@ -155,37 +155,18 @@ extern char *mail_pathname(const char *, const char *);
   * XCLIENT in SMTP.
   */
 #define XCLIENT_CMD            "XCLIENT"       /* XCLIENT command */
-#define XCLIENT_OVERRIDE       "OVERRIDE"      /* override function */
-#define XCLIENT_FORWARD                "FORWARD"       /* forward function */
-#define XCLIENT_NAME           "CLIENT_NAME"   /* client name */
-#define XCLIENT_ADDR           "CLIENT_ADDR"   /* client address */
-#define XCLIENT_PROTO          "CLIENT_PROTO"  /* client protocol */
-#define XCLIENT_CODE           "CLIENT_CODE"   /* client name status */
-#define XCLIENT_HELO           "CLIENT_HELO"   /* client helo */
-
- /*
-  * This is how Postfix represents unknown client information within smtpd or
-  * qmqpd processes.
-  * 
-  * This is not the representation that Postfix uses in queue files, in queue
-  * manager delivery requests, nor is it the representation of information in
-  * XCLIENT commands!
-  */
-#define CLIENT_ATTR_UNKNOWN    "unknown"
-
-#define CLIENT_NAME_UNKNOWN    CLIENT_ATTR_UNKNOWN
-#define CLIENT_ADDR_UNKNOWN    CLIENT_ATTR_UNKNOWN
-#define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
-#define CLIENT_HELO_UNKNOWN    0
-#define CLIENT_PROTO_UNKNOWN   CLIENT_ATTR_UNKNOWN
-
-#define IS_AVAIL_CLIENT_ATTR(v)        ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
-
-#define IS_AVAIL_CLIENT_NAME(v)        IS_AVAIL_CLIENT_ATTR(v)
-#define IS_AVAIL_CLIENT_ADDR(v)        IS_AVAIL_CLIENT_ATTR(v)
-#define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
-#define IS_AVAIL_CLIENT_HELO(v)        (v)
-#define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v)
+#define XCLIENT_NAME           "NAME"          /* client name */
+#define XCLIENT_ADDR           "ADDR"          /* client address */
+#define XCLIENT_PROTO          "PROTO"         /* client protocol */
+#define XCLIENT_CODE           "NAME_CODE"     /* client name status */
+#define XCLIENT_HELO           "HELO"          /* client helo */
+
+#define XFORWARD_CMD           "XFORWARD"      /* XFORWARD command */
+#define XFORWARD_NAME          "NAME"          /* client name */
+#define XFORWARD_ADDR          "ADDR"          /* client address */
+#define XFORWARD_PROTO         "PROTO"         /* client protocol */
+#define XFORWARD_HELO          "HELO"          /* client helo */
+#define XFORWARD_IDENT         "IDENT"         /* message identifier */
 
 /* LICENSE
 /* .ad
index bb00522fc112d1de14bf70de3aa4cb8cdfc3204b..192f01d381d83be21b1b9622deab7a45625f5940 100644 (file)
@@ -285,33 +285,16 @@ int     mail_queue_id_ok(const char *queue_id)
 {
     const char *cp;
 
-    if (*queue_id == 0 || strlen(queue_id) > 100)
+    if (*queue_id == 0 || strlen(queue_id) > VALID_HOSTNAME_LEN)
        return (0);
 
     /*
-     * OK if in in time+inum form.
+     * OK if in in time+inum form or in host-name_domain_tld form.
      */
-    for (cp = queue_id; /* void */ ; cp++) {
-       if (*cp == 0)
-           return (1);
-       if (!ISALNUM(*cp))
-           break;
-    }
-
-    /*
-     * BAD if in time.pid form.
-     */
-    for (cp = queue_id; /* void */ ; cp++) {
-       if (*cp == 0)
+    for (cp = queue_id; *cp; cp++)
+       if (!ISALNUM(*cp) && *cp != '_' && *cp != '-')
            return (0);
-       if (!ISDIGIT(*cp) && *cp != '.')
-           break;
-    }
-
-    /*
-     * OK if in valid hostname form.
-     */
-    return (valid_hostname(queue_id, DONT_GRIPE));
+    return (1);
 }
 
 /* mail_queue_enter - make mail queue entry with locally-unique name */
index acb4ee8bcf0217a889c45da981bf09edf258b6eb..65279a01ccceca86fc75ef32d71939ea1b8bbecb 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      "20031207"
+#define MAIL_RELEASE_DATE      "20031213"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "2.0.16-" MAIL_RELEASE_DATE
diff --git a/postfix/src/global/peer_name.c b/postfix/src/global/peer_name.c
deleted file mode 100644 (file)
index 5e3affa..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*++
-/* NAME
-/*     peer_name 3
-/* SUMMARY
-/*     produce printable peer name and address
-/* SYNOPSIS
-/*     #include <peer_name.h>
-/*
-/*     typedef struct {
-/* .in +4
-/*             int     type;
-/*             char    name;
-/*             char    addr;
-/* .in -4
-/*     } PEER_NAME;
-/*
-/*     PEER_NAME *peer_name(sock)
-/*     int     sock;
-/* DESCRIPTION
-/*     The \fIpeer_name\fR() routine attempts to produce a printable
-/*     version of the peer name and address of the specified socket.
-/*     The result is in static memory that will be overwritten.
-/*     Make a copy if the result is to be used for an appreciable
-/*     amount of time.
-/*
-/*     Where information is unavailable, the name and/or address
-/*     are set to "unknown".
-/*     The \fItype\fR result field specifies how the name and address
-/*     should be interpreted:
-/* .IP PEER_TYPE_INET
-/*     The socket specifies a TCP/IP endpoint.
-/*     The result is a hostname (from the DNS, a local hosts file or
-/*     other); the address a dotted quad.
-/* .IP PEER_TYPE_LOCAL
-/*     The socket argument specifies a local transport.
-/*     The result name is "localhost"; the result address is "127.0.0.1".
-/* .IP PEER_TYPE_UNKNOWN
-/*     The socket argument does not specify a socket.
-/*     The result name is "localhost"; the result address is "127.0.0.1".
-/* 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 <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <netdb.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <valid_hostname.h>
-#include <peer_name.h>
-
-/* peer_name - produce printable peer name and address */
-
-PEER_NAME *peer_name(int sock)
-{
-    static PEER_NAME peer;
-    struct sockaddr_in sin;
-    SOCKADDR_SIZE len = sizeof(sin);
-    struct hostent *hp;
-
-    if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) {
-       switch (sin.sin_family) {
-       case AF_INET:
-           peer.type = PEER_TYPE_INET;
-           hp = gethostbyaddr((char *) &(sin.sin_addr),
-                              sizeof(sin.sin_addr), AF_INET);
-           peer.name = (hp && valid_hostname(hp->h_name, DO_GRIPE) ?
-                        hp->h_name : "unknown");
-           peer.addr = inet_ntoa(sin.sin_addr);
-           return (&peer);
-       case AF_UNSPEC:
-       case AF_UNIX:
-           peer.type = PEER_TYPE_LOCAL;
-           peer.name = "localhost";
-           peer.addr = "127.0.0.1";
-           return (&peer);
-       }
-    }
-    peer.type = PEER_TYPE_UNKNOWN;
-    peer.name = "localhost";
-    peer.addr = "127.0.0.1";
-    return (&peer);
-
-}
-
-#ifdef TEST
-
-#include <unistd.h>
-
-int     main(int unused_argc, char **unused_argv)
-{
-    PEER_NAME *peer;
-
-    peer = peer_name(STDIN_FILENO);
-    msg_info("name %s addr %s", peer->name, peer->addr);
-}
-
-#endif
diff --git a/postfix/src/global/peer_name.h b/postfix/src/global/peer_name.h
deleted file mode 100644 (file)
index f1c9637..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _PEER_NAME_H_INCLUDED_
-#define _PEER_NAME_H_INCLUDED_
-
-/*++
-/* NAME
-/*     peer_name 3h
-/* SUMMARY
-/*     produce printable peer name and address
-/* SYNOPSIS
-/*     #include <peer_name.h>
-/* DESCRIPTION
-
- /*
-  * External interface.
-  */
-typedef struct {
-    int     type;                      /* IPC type, see below */
-    char   *name;                      /* peer official name */
-    char   *addr;                      /* peer address */
-} PEER_NAME;
-
-#define PEER_TYPE_UNKNOWN      0
-#define PEER_TYPE_INET         1
-#define PEER_TYPE_LOCAL                2
-
-extern PEER_NAME *peer_name(int);
-
-/* 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
-/*--*/
-
-#endif
index 3228c09b94481ba403da8bd926184904aedfe7db..92d37f59711829fb62816606851beb7b0e9de670 100644 (file)
@@ -95,10 +95,13 @@ void    recipient_list_init(RECIPIENT_LIST *list)
 void    recipient_list_add(RECIPIENT_LIST *list, long offset,
                                   const char *orig_rcpt, const char *rcpt)
 {
+    int     new_avail;
+
     if (list->len >= list->avail) {
-       list->avail *= 2;
+       new_avail = list->avail * 2;
        list->info = (RECIPIENT *)
-           myrealloc((char *) list->info, list->avail * sizeof(RECIPIENT));
+           myrealloc((char *) list->info, new_avail * sizeof(RECIPIENT));
+       list->avail = new_avail;
     }
     list->info[list->len].orig_addr = mystrdup(orig_rcpt);
     list->info[list->len].address = mystrdup(rcpt);
index 9868c9fcab5bc2ed630d088903b189f7b0f33f02..ebe566243a113694b10aa89e1f8a675f254be105 100644 (file)
@@ -75,10 +75,13 @@ void    qmgr_rcpt_list_init(QMGR_RCPT_LIST *list)
 void    qmgr_rcpt_list_add(QMGR_RCPT_LIST *list, long offset,
                                   const char *orcpt, const char *rcpt)
 {
+    int     new_avail;
+
     if (list->len >= list->avail) {
-       list->avail *= 2;
+       new_avail = list->avail * 2;
        list->info = (QMGR_RCPT *)
-           myrealloc((char *) list->info, list->avail * sizeof(QMGR_RCPT));
+           myrealloc((char *) list->info, new_avail * sizeof(QMGR_RCPT));
+       list->avail = new_avail;
     }
     list->info[list->len].orig_rcpt = mystrdup(orcpt);
     list->info[list->len].address = mystrdup(rcpt);
index 9868c9fcab5bc2ed630d088903b189f7b0f33f02..ebe566243a113694b10aa89e1f8a675f254be105 100644 (file)
@@ -75,10 +75,13 @@ void    qmgr_rcpt_list_init(QMGR_RCPT_LIST *list)
 void    qmgr_rcpt_list_add(QMGR_RCPT_LIST *list, long offset,
                                   const char *orcpt, const char *rcpt)
 {
+    int     new_avail;
+
     if (list->len >= list->avail) {
-       list->avail *= 2;
+       new_avail = list->avail * 2;
        list->info = (QMGR_RCPT *)
-           myrealloc((char *) list->info, list->avail * sizeof(QMGR_RCPT));
+           myrealloc((char *) list->info, new_avail * sizeof(QMGR_RCPT));
+       list->avail = new_avail;
     }
     list->info[list->len].orig_rcpt = mystrdup(orcpt);
     list->info[list->len].address = mystrdup(rcpt);
index 1fcc75ca63ace680b83990141edd221dca86df14..483c6e138c85ca05f76bbabe1a0bb24c550a306f 100644 (file)
@@ -291,8 +291,9 @@ static void qmqpd_write_attributes(QMQPD_STATE *state)
     if (IS_AVAIL_CLIENT_ADDR(state->addr))
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                    MAIL_ATTR_CLIENT_ADDR, state->addr);
-    rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-               MAIL_ATTR_ORIGIN, state->namaddr);
+    if (IS_AVAIL_CLIENT_NAMADDR(state->namaddr))
+       rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                   MAIL_ATTR_ORIGIN, state->namaddr);
     rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                MAIL_ATTR_PROTO_NAME, state->protocol);
 }
index aaacb424254b26bbdcf2b3e5c8a0b34f176220af..7e5c2471b9ab1ccc4483464c3f26cd4796c9c07c 100644 (file)
@@ -48,6 +48,24 @@ typedef struct {
     VSTRING *why_rejected;             /* REJECT reason */
 } QMQPD_STATE;
 
+ /*
+  * Postfix representation unknown client information within qmqpd processes.
+  * This is not the representation that Postfix uses in queue files, in queue
+  * manager delivery requests, nor is it the representation of information in
+  * XCLIENT/XFORWARD commands!
+  */
+#define CLIENT_ATTR_UNKNOWN    "unknown"
+
+#define CLIENT_NAME_UNKNOWN    CLIENT_ATTR_UNKNOWN
+#define CLIENT_ADDR_UNKNOWN    CLIENT_ATTR_UNKNOWN
+#define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
+
+#define IS_AVAIL_CLIENT_ATTR(v)        ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
+
+#define IS_AVAIL_CLIENT_NAME(v)        IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_ADDR(v)        IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
+
  /*
   * QMQP protocol status codes.
   */
index 9f0e9f2f5ddc4a85f2f64e408b23e0214200721b..84c878dcb0eae5eafa56368cd45156fdf2e9726f 100644 (file)
@@ -105,8 +105,8 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
      * If peer went away, give up.
      */
     if (errno == ECONNRESET || errno == ECONNABORTED) {
-       state->name = mystrdup("unknown");
-       state->addr = mystrdup("unknown");
+       state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
+       state->addr = mystrdup(CLIENT_ATTR_UNKNOWN);
     }
 
     /*
@@ -117,9 +117,9 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
        hp = gethostbyaddr((char *) &(sin.sin_addr),
                           sizeof(sin.sin_addr), AF_INET);
        if (hp == 0) {
-           state->name = mystrdup("unknown");
+           state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
        } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
-           state->name = mystrdup("unknown");
+           state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
        } else {
            state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
 
@@ -128,7 +128,7 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
             */
 #define REJECT_PEER_NAME(state) { \
        myfree(state->name); \
-       state->name = mystrdup("unknown"); \
+       state->name = mystrdup(CLIENT_ATTR_UNKNOWN); \
     }
 
            hp = gethostbyname(state->name);    /* clobbers hp->name!! */
index 3400b7df3d764dd34f31e690c31def92c787cd05..256bab47a0190719243fbb348fb91624ece8b1ba 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
+/* .IP \fBsmtp_xforward_timeout\fR
+/*     Timeout for sending the \fBXFORWARD\fR command, and for
 /*     receiving the server response.
 /* .IP \fBsmtp_mail_timeout\fR
 /*     Timeout for sending the \fBMAIL FROM\fR command, and for
 /*     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,
+/* .IP \fBsmtp_send_xforward_command\fR
+/*     If the SMTP server announces XFORWARD 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.
@@ -314,7 +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;
+bool    var_smtp_send_xforward;
 
  /*
   * Global variables. smtp_errno is set by the address lookup routines and by
@@ -529,7 +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,
+       VAR_SMTP_SEND_XFORWARD, DEF_SMTP_SEND_XFORWARD, &var_smtp_send_xforward,
        0,
     };
 
index 8c9d0407442a0b82b8d6c46bfabe58a9aafb954b..f591b0cc36a2d58699115a3f1d8f56c26acc4c48 100644 (file)
@@ -64,7 +64,14 @@ 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 */
+#define SMTP_FEATURE_XFORWARD_NAME (1<<7)
+#define SMTP_FEATURE_XFORWARD_ADDR (1<<8)
+#define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
+#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
+
+#define SMTP_FEATURE_XFORWARD_MASK \
+       (SMTP_FEATURE_XFORWARD_NAME | SMTP_FEATURE_XFORWARD_ADDR \
+       | SMTP_FEATURE_XFORWARD_PROTO | SMTP_FEATURE_XFORWARD_HELO)
 
  /*
   * smtp.c
index 6471014bafefe3e780cf8e0bd2d45d683581540e..cca3983a751bb8bbaa35b55e50c2846272a8dbf0 100644 (file)
@@ -84,6 +84,7 @@
 #include <mymalloc.h>
 #include <iostuff.h>
 #include <split_at.h>
+#include <name_code.h>
 
 /* Global library. */
 
   * SMTP_STATE_DOT) must have smaller numerical values than the non-sending
   * states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
   */
-#define SMTP_STATE_XCLIENT_ADDR        0
-#define SMTP_STATE_XCLIENT_HELO        1
+#define SMTP_STATE_XFORWARD_ADDR 0
+#define SMTP_STATE_XFORWARD_HELO 1
 #define SMTP_STATE_MAIL                2
 #define SMTP_STATE_RCPT                3
 #define SMTP_STATE_DATA                4
@@ -146,8 +147,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 XFORWARD address and name",
+    "sending XFORWARD helo_name and protocol",
     "sending MAIL FROM",
     "sending RCPT TO",
     "sending DATA command",
@@ -157,8 +158,8 @@ char   *xfer_states[SMTP_STATE_LAST] = {
 };
 
 char   *xfer_request[SMTP_STATE_LAST] = {
-    "XCLIENT command",
-    "XCLIENT command",
+    "XFORWARD name/address command",
+    "XFORWARD helo/protocol command",
     "MAIL FROM command",
     "RCPT TO command",
     "DATA command",
@@ -179,6 +180,13 @@ int     smtp_helo(SMTP_STATE *state)
     char   *words;
     char   *word;
     int     n;
+    static NAME_CODE xforward_features[] = {
+       XFORWARD_NAME, SMTP_FEATURE_XFORWARD_NAME,
+       XFORWARD_ADDR, SMTP_FEATURE_XFORWARD_ADDR,
+       XFORWARD_PROTO, SMTP_FEATURE_XFORWARD_PROTO,
+       XFORWARD_HELO, SMTP_FEATURE_XFORWARD_HELO,
+       0, 0,
+    };
 
     /*
      * Prepare for disaster.
@@ -259,9 +267,11 @@ 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) {
+           else if (strcasecmp(word, "XFORWARD") == 0) {
+               while ((word = mystrtok(&words, " \t")) != 0)
+                   state->features |= name_code(xforward_features,
+                                                NAME_CODE_FLAG_NONE, word);
+           } else if (strcasecmp(word, "SIZE") == 0) {
                state->features |= SMTP_FEATURE_SIZE;
                if ((word = mystrtok(&words, " \t")) != 0) {
                    if (!alldig(word))
@@ -484,15 +494,15 @@ int     smtp_xfer(SMTP_STATE *state)
      * commands rejected, DATA rejected) it forces the sender to abort the
      * SMTP dialog with RSET and QUIT.
      * 
-     * Use the XCLIENT command to forward client attributes only when a minimal
+     * Use the XFORWARD command to forward client attributes only when a minimal
      * amount of information is available.
      */
     nrcpt = 0;
-    if (var_smtp_send_xclient
-       && (state->features & SMTP_FEATURE_XCLIENT)
+    if (var_smtp_send_xforward
+       && (state->features & SMTP_FEATURE_XFORWARD_MASK)
        && (DEL_REQ_ATTR_AVAIL(request->client_name)
            || DEL_REQ_ATTR_AVAIL(request->client_addr)))
-       recv_state = send_state = SMTP_STATE_XCLIENT_ADDR;
+       recv_state = send_state = SMTP_STATE_XFORWARD_ADDR;
     else
        recv_state = send_state = SMTP_STATE_MAIL;
     next_rcpt = send_rcpt = recv_rcpt = 0;
@@ -512,29 +522,37 @@ int     smtp_xfer(SMTP_STATE *state)
            msg_panic("%s: bad sender state %d", myname, send_state);
 
            /*
-            * Build the XCLIENT command. With properly sanitized
+            * Build the XFORWARD command. With properly sanitized
             * information, the command length stays within the 512 byte
             * command line length limit.
             */
-       case SMTP_STATE_XCLIENT_ADDR:
-           vstring_strcpy(next_command,
-                     XCLIENT_CMD " " XCLIENT_FORWARD " " XCLIENT_NAME "=");
-           if (DEL_REQ_ATTR_AVAIL(request->client_name))
-               xtext_quote_append(next_command, request->client_name, "");
-           vstring_strcat(next_command, " " XCLIENT_ADDR "=");
-           if (DEL_REQ_ATTR_AVAIL(request->client_addr))
-               xtext_quote_append(next_command, request->client_addr, "");
-           next_state = SMTP_STATE_XCLIENT_HELO;
+       case SMTP_STATE_XFORWARD_ADDR:
+           vstring_strcpy(next_command, XFORWARD_CMD);
+           if (state->features & SMTP_FEATURE_XFORWARD_NAME) {
+               vstring_strcat(next_command, " " XCLIENT_NAME "=");
+               if (DEL_REQ_ATTR_AVAIL(request->client_name))
+                   xtext_quote_append(next_command, request->client_name, "");
+           }
+           if (state->features & SMTP_FEATURE_XFORWARD_ADDR) {
+               vstring_strcat(next_command, " " XFORWARD_ADDR "=");
+               if (DEL_REQ_ATTR_AVAIL(request->client_addr))
+                   xtext_quote_append(next_command, request->client_addr, "");
+           }
+           next_state = SMTP_STATE_XFORWARD_HELO;
            break;
 
-       case SMTP_STATE_XCLIENT_HELO:
-           vstring_strcpy(next_command,
-                     XCLIENT_CMD " " XCLIENT_FORWARD " " XCLIENT_HELO "=");
-           if (DEL_REQ_ATTR_AVAIL(request->client_helo))
-               xtext_quote_append(next_command, request->client_helo, "");
-           vstring_strcat(next_command, " " XCLIENT_PROTO "=");
-           if (DEL_REQ_ATTR_AVAIL(request->client_proto))
-               xtext_quote_append(next_command, request->client_proto, "");
+       case SMTP_STATE_XFORWARD_HELO:
+           vstring_strcpy(next_command, XFORWARD_CMD);
+           if (state->features & SMTP_FEATURE_XFORWARD_HELO) {
+               vstring_strcat(next_command, " " XCLIENT_HELO "=");
+               if (DEL_REQ_ATTR_AVAIL(request->client_helo))
+                   xtext_quote_append(next_command, request->client_helo, "");
+           }
+           if (state->features & SMTP_FEATURE_XFORWARD_ADDR) {
+               vstring_strcat(next_command, " " XFORWARD_PROTO "=");
+               if (DEL_REQ_ATTR_AVAIL(request->client_proto))
+                   xtext_quote_append(next_command, request->client_proto, "");
+           }
            next_state = SMTP_STATE_MAIL;
            break;
 
@@ -647,7 +665,7 @@ int     smtp_xfer(SMTP_STATE *state)
                /*
                 * Sanity check.
                 */
-               if (recv_state < SMTP_STATE_XCLIENT_ADDR
+               if (recv_state < SMTP_STATE_XFORWARD_ADDR
                    || recv_state > SMTP_STATE_QUIT)
                    msg_panic("%s: bad receiver state %d (sender state %d)",
                              myname, recv_state, send_state);
@@ -669,13 +687,23 @@ int     smtp_xfer(SMTP_STATE *state)
                switch (recv_state) {
 
                    /*
-                    * Process the XCLIENT response.
+                    * Process the XFORWARD response.
                     */
-               case SMTP_STATE_XCLIENT_ADDR:
-                   recv_state = SMTP_STATE_XCLIENT_HELO;
+               case SMTP_STATE_XFORWARD_ADDR:
+                   if (resp->code / 100 != 2)
+                       msg_warn("host %s said: %s (in reply to %s)",
+                                session->namaddr,
+                                translit(resp->str, "\n", " "),
+                                xfer_request[SMTP_STATE_MAIL]);
+                   recv_state = SMTP_STATE_XFORWARD_HELO;
                    break;
 
-               case SMTP_STATE_XCLIENT_HELO:
+               case SMTP_STATE_XFORWARD_HELO:
+                   if (resp->code / 100 != 2)
+                       msg_warn("host %s said: %s (in reply to %s)",
+                                session->namaddr,
+                                translit(resp->str, "\n", " "),
+                                xfer_request[SMTP_STATE_MAIL]);
                    recv_state = SMTP_STATE_MAIL;
                    break;
 
index 6014a9f2595d64427ced88af9b9bb7ccee348250..ba9c6bcbc9a6b11c21c76e4f68c304a8a7f3ecc9 100644 (file)
@@ -1,10 +1,10 @@
 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_xclient.c
+       smtpd_xforward.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_xclient.o
+       smtpd_xforward.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
@@ -30,7 +30,7 @@ update: ../../libexec/$(PROG)
 ../../libexec/$(PROG): $(PROG)
        cp $(PROG) ../../libexec
 
-SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o smtpd_xclient.o
+SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o smtpd_xforward.o
 
 smtpd_token: smtpd_token.c $(LIBS)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
@@ -122,6 +122,7 @@ smtpd.o: ../../include/argv.h
 smtpd.o: ../../include/watchdog.h
 smtpd.o: ../../include/iostuff.h
 smtpd.o: ../../include/split_at.h
+smtpd.o: ../../include/name_code.h
 smtpd.o: ../../include/mail_params.h
 smtpd.o: ../../include/record.h
 smtpd.o: ../../include/rec_type.h
@@ -338,16 +339,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
+smtpd_xforward.o: smtpd_xforward.c
+smtpd_xforward.o: ../../include/sys_defs.h
+smtpd_xforward.o: ../../include/mymalloc.h
+smtpd_xforward.o: ../../include/msg.h
+smtpd_xforward.o: ../../include/mail_proto.h
+smtpd_xforward.o: ../../include/vstream.h
+smtpd_xforward.o: ../../include/vbuf.h
+smtpd_xforward.o: ../../include/iostuff.h
+smtpd_xforward.o: ../../include/attr.h
+smtpd_xforward.o: smtpd.h
+smtpd_xforward.o: ../../include/vstring.h
+smtpd_xforward.o: ../../include/argv.h
+smtpd_xforward.o: ../../include/mail_stream.h
index 07d69080281299944d5dc3e2e0f194e13f830213..b2e3db103f422ce73a4a109c73f1920e04042061 100644 (file)
 /* .IP \fBsmtpd_sender_login_maps\fR
 /*     Maps that specify the SASL login name that owns a MAIL FROM sender
 /*     address. Used by the \fBreject_sender_login_mismatch\fR sender
-/*     anti-spoofing restriction.
+/*     anti-spoofing restriction, as well as by its component restrictions
+/*     \fBreject_authenticated_sender_login_mismatch\fR (an authenticated
+/*     client can't use a MAIL FROM sender address that is owned by someone
+/*     else) and \fBreject_unauthenticated_sender_login_mismatch\fR (a client
+/*     must be authenticated in order to use the MAIL FROM sender address).
 /* .SH Miscellaneous
 /* .ad
 /* .fi
 /*     authorized to use the XVERP extension.
 /* .IP \fBsmtpd_authorized_xclient_hosts\fR
 /*     Hostnames, domain names and/or addresses of clients that are
-/*     authorized to use the XCLIENT command.  This command changes
-/*     client information for access control and/or logging purposes,
+/*     authorized to use the XCLIENT command.  This command overrides
+/*     client information for access control and logging purposes,
 /*     with the exception of the
 /*     \fBsmtpd_authorized_xclient_hosts\fR access control itself.
+/* .IP \fBsmtpd_authorized_xforward_hosts\fR
+/*     Hostnames, domain names and/or addresses of clients that are
+/*     authorized to use the XFORWARD command.  This command accepts
+/*     client and message identofying information for logging purposes.
 /* .IP \fBdebug_peer_level\fR
 /*     Increment in verbose logging level when a remote host matches a
 /*     pattern in the \fBdebug_peer_list\fR parameter.
@@ -554,6 +562,7 @@ int     var_smtpd_policy_tmout;
 int     var_smtpd_policy_idle;
 int     var_smtpd_policy_ttl;
 char   *var_xclient_hosts;
+char   *var_xforward_hosts;
 int     var_smtpd_crate_limit;
 int     var_smtpd_cconn_limit;
 char   *var_smtpd_hoggers;
@@ -579,6 +588,12 @@ static NAMADR_LIST *verp_clients;
 static NAMADR_LIST *xclient_hosts;
 static int xclient_allowed;
 
+ /*
+  * XFORWARD command. Access control is cached.
+  */
+static NAMADR_LIST *xforward_hosts;
+static int xforward_allowed;
+
  /*
   * Client connection and rate limiting.
   */
@@ -736,7 +751,14 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "250-%s", VERP_CMD);
     /* XCLIENT must not override its own access control. */
     if (xclient_allowed)
-       smtpd_chat_reply(state, "250-%s", XCLIENT_CMD);
+       smtpd_chat_reply(state, "250-" XCLIENT_CMD
+                        " " XCLIENT_NAME " " XCLIENT_ADDR
+                        " " XCLIENT_CODE " " XCLIENT_PROTO
+                        " " XCLIENT_HELO);
+    if (xforward_allowed)
+       smtpd_chat_reply(state, "250-" XFORWARD_CMD
+                        " " XFORWARD_NAME " " XFORWARD_ADDR
+                        " " XFORWARD_PROTO " " XFORWARD_HELO);
     smtpd_chat_reply(state, "250 8BITMIME");
     return (0);
 }
@@ -1147,8 +1169,8 @@ static void mail_reset(SMTPD_STATE *state)
        (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT");
        smtpd_proxy_close(state);
     }
-    if (state->xclient.used)
-       smtpd_xclient_reset(state);
+    if (state->xforward.flags)
+       smtpd_xforward_reset(state);
 }
 
 /* rcpt_cmd - process RCPT TO command */
@@ -1336,7 +1358,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
            rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", state->saved_flags);
        rec_fputs(state->cleanup, REC_TYPE_MESG, "");
     }
-    if (!state->proxy || state->xclient.used == 0) {
+    if (!state->proxy || state->xforward.flags == 0) {
        out_fprintf(out_stream, REC_TYPE_NORM,
                    "Received: from %s (%s [%s])",
                    state->helo_name ? state->helo_name : state->name,
@@ -1701,76 +1723,26 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
     return (0);
 }
 
- /*
-  * Lookup tables with xclient/normal attribute offsets. Maybe we should not
-  * try so hard to make XOVERRIDE and XFORWARD attribute lists identical.
-  */
-#define FUNC_OVERRIDE  0
-#define FUNC_FORWARD   1
-
-struct attr_offset {
-    int     name[2];
-    int     addr[2];
-    int     namaddr[2];
-    int     peer_code[2];
-    int     protocol[2];
-    int     helo_name[2];
-};
-
-#define ATTR_OFFSETS(member) \
-       offsetof(SMTPD_STATE, member), offsetof(SMTPD_STATE, xclient.member)
-
-static const struct attr_offset attr_offset = {
-    ATTR_OFFSETS(name),
-    ATTR_OFFSETS(addr),
-    ATTR_OFFSETS(namaddr),
-    ATTR_OFFSETS(peer_code),
-    ATTR_OFFSETS(protocol),
-    ATTR_OFFSETS(helo_name)
-};
-
-#define PTR_ATTR(state, func, attr) (((char *) state) + attr_offset.attr[func])
-#define STR_ATTR(state, func, attr) *((char **) PTR_ATTR(state, func, attr))
-#define INT_ATTR(state, func, attr) *((int *) PTR_ATTR(state, func, attr))
-
-#define RST_STR_ATTR(state, func, attr) { \
-       if (STR_ATTR(state, func, attr)) \
-           myfree(STR_ATTR(state, func, attr)); \
-       STR_ATTR(state, func, attr) = 0; \
-    }
-
-#define UPD_STR_ATTR(state, func, attr, value) { \
-       if (STR_ATTR(state, func, attr)) \
-           myfree(STR_ATTR(state, func, attr)); \
-       STR_ATTR(state, func, attr) = mystrdup(value); \
-    }
-
-#define UPD_INT_ATTR(state, func, attr, value) { \
-       INT_ATTR(state, func, attr) = (value); \
-    }
-
-/* xclient_cmd - process XCLIENT */
+/* xclient_cmd - override client attributes */
 
 static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
 {
     int     arg_no;
-    char   *raw_value;
-    char   *cooked_value;
-    char   *arg_val;
+    char   *attr_value;
+    char   *attr_name;
     int     update_namaddr = 0;
-    int     function;
     int     code;
-    static NAME_CODE xclient_functions[] = {
-       XCLIENT_OVERRIDE, FUNC_OVERRIDE,
-       XCLIENT_FORWARD, FUNC_FORWARD,
-       0, -1,
-    };
     static NAME_CODE xclient_codes[] = {
        "OK", SMTPD_PEER_CODE_OK,
        "PERM", SMTPD_PEER_CODE_PERM,
        "TEMP", SMTPD_PEER_CODE_TEMP,
        0, -1,
     };
+    static NAME_CODE xclient_proto[] = {
+       MAIL_PROTO_SMTP, 1,
+       MAIL_PROTO_ESMTP, 2,
+       0, -1,
+    };
 
     /*
      * Sanity checks. The XCLIENT command does not override its own access
@@ -1781,9 +1753,9 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "503 Error: MAIL transaction in progress");
        return (-1);
     }
-    if (argc < 3) {
+    if (argc < 2) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
-       smtpd_chat_reply(state, "501 Syntax: %s function name=value...",
+       smtpd_chat_reply(state, "501 Syntax: %s name=value...",
                         XCLIENT_CMD);
        return (-1);
     }
@@ -1792,164 +1764,133 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "554 Error: insufficient authorization");
        return (-1);
     }
-#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
+#define STREQ(x,y)     (strcasecmp((x), (y)) == 0)
+#define UPDATE_STR(s, v) do { if (s) myfree(s); s = (v) ? mystrdup(v) : 0; } while(0)
 
     /*
-     * Function name: what attributes to update. Complain about unrecognized
-     * request names. The set of requests is unlikely to change.
+     * Iterate over all NAME=VALUE attributes.
      */
-    arg_val = argv[1].strval;
-    printable(arg_val, '?');
-    if ((function = name_code(xclient_functions, arg_val)) < 0) {
-       state->error_mask |= MAIL_ERROR_PROTOCOL;
-       smtpd_chat_reply(state, "501 Bad %s function: %s",
-                        XCLIENT_CMD, arg_val);
-       return (-1);
-    }
-    if (function == FUNC_FORWARD && state->xclient.used == 0)
-       smtpd_xclient_preset(state);
-
-    /*
-     * Iterate over all NAME=VALUE attributes. An empty value means the
-     * information was not provided by the client and that we must not fall
-     * back to the non-XCLIENT value.
-     */
-    for (arg_no = 2; arg_no < argc; arg_no++) {
-       arg_val = argv[arg_no].strval;
+    for (arg_no = 1; arg_no < argc; arg_no++) {
+       attr_name = argv[arg_no].strval;
 
        /*
-        * Decode the attribute value 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.
+        * For safety's sake mask non-printable characters in the raw and
+        * decoded values; we don't want to handle unexploded munitions.
+        * Complain when they send an attribute that we didn't announce.
+        * 
+        * An implementation must allow clients to send XCLIENT before the
+        * HELO/EHLO greeting.
         * 
         * The client can send multiple XCLIENT attributes in a single command,
         * or multiple XCLIENT commands with fewer attributes.
-        * 
-        * Note: XCLIENT OVERRIDE overrides only the specified remote client
-        * attributes (for testing), while XCLIENT FORWARD overrides all
-        * remote client attributes (for consistency).
         */
-       if ((raw_value = split_at(arg_val, '=')) == 0) {
+       if ((attr_value = split_at(attr_name, '=')) == 0) {
            state->error_mask |= MAIL_ERROR_PROTOCOL;
            smtpd_chat_reply(state, "501 Error: name=value expected");
            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, '?');
+       printable(attr_value, '?');
 
        /*
-        * CLIENT_NAME=hostname. Also updates the client hostname lookup
-        * status code. Treat a numerical hostname as an unavailable name.
+        * NAME=hostname. Also updates the client hostname lookup status
+        * code. Treat a numerical hostname as an unavailable name.
         */
-       if (STREQ(arg_val, XCLIENT_NAME)) {
-           if (*raw_value && !valid_hostaddr(cooked_value, DONT_GRIPE)) {
-               if (!valid_hostname(cooked_value, DONT_GRIPE)) {
+       if (STREQ(attr_name, XCLIENT_NAME)) {
+           if (*attr_value && !valid_hostaddr(attr_value, DONT_GRIPE)) {
+               if (!valid_hostname(attr_value, DONT_GRIPE)) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
                    smtpd_chat_reply(state, "501 Bad %s syntax: %s",
-                                    XCLIENT_NAME, raw_value);
+                                    XCLIENT_NAME, attr_value);
                    return (-1);
                }
-               UPD_STR_ATTR(state, function, name, cooked_value);
-               UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_OK);
+               UPDATE_STR(state->name, attr_value);
+               state->peer_code = SMTPD_PEER_CODE_OK;
            } else {
-               UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
-               UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_PERM);
+               UPDATE_STR(state->name, CLIENT_NAME_UNKNOWN);
+               state->peer_code = SMTPD_PEER_CODE_PERM;
            }
            update_namaddr = 1;
        }
 
        /*
-        * CLIENT_ADDR=client network address.
+        * ADDR=client network address.
         */
-       else if (STREQ(arg_val, XCLIENT_ADDR)) {
-           if (*raw_value) {
-               if (!valid_hostaddr(cooked_value, DONT_GRIPE)) {
+       else if (STREQ(attr_name, XCLIENT_ADDR)) {
+           if (*attr_value) {
+               if (!valid_hostaddr(attr_value, DONT_GRIPE)) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
                    smtpd_chat_reply(state, "501 Bad %s syntax: %s",
-                                    XCLIENT_ADDR, raw_value);
+                                    XCLIENT_ADDR, attr_value);
                    return (-1);
                }
-               UPD_STR_ATTR(state, function, addr, cooked_value);
+               UPDATE_STR(state->addr, attr_value);
            } else {
-               UPD_STR_ATTR(state, function, addr, CLIENT_ADDR_UNKNOWN);
+               UPDATE_STR(state->addr, CLIENT_ADDR_UNKNOWN);
            }
            update_namaddr = 1;
        }
 
        /*
-        * CLIENT_CODE=hostname lookup status. Reset the client hostname if
-        * the hostname lookup status is not OK.
+        * CODE=hostname lookup status. Reset the client hostname if the
+        * hostname lookup status is not OK.
         */
-       else if (STREQ(arg_val, XCLIENT_CODE)) {
-           if (*raw_value) {
-               if ((code = name_code(xclient_codes, cooked_value)) < 0) {
+       else if (STREQ(attr_name, XCLIENT_CODE)) {
+           if (*attr_value) {
+               if ((code = name_code(xclient_codes, NAME_CODE_FLAG_NONE, attr_value)) < 0) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
                    smtpd_chat_reply(state, "501 Bad %s value: %s",
-                                    XCLIENT_CODE, raw_value);
+                                    XCLIENT_CODE, attr_value);
                    return (-1);
                }
-               UPD_INT_ATTR(state, function, peer_code, code);
+               state->peer_code = code;
                if (code != SMTPD_PEER_CODE_OK) {
-                   UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
+                   UPDATE_STR(state->name, CLIENT_NAME_UNKNOWN);
                    update_namaddr = 1;
                }
            }
        }
 
        /*
-        * CLIENT_HELO=hostname. Disallow characters that could mess up our
-        * own Received: message headers but allow [].
+        * HELO=hostname. Disallow characters that could mess up our own
+        * Received: message headers but allow [].
         */
-       else if (STREQ(arg_val, XCLIENT_HELO)) {
-           if (*raw_value) {
-               if (strlen(cooked_value) > VALID_HOSTNAME_LEN) {
+       else if (STREQ(attr_name, XCLIENT_HELO)) {
+           if (*attr_value) {
+               if (strlen(attr_value) > VALID_HOSTNAME_LEN) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
                    smtpd_chat_reply(state, "501 Bad %s syntax: %s",
-                                    XCLIENT_HELO, raw_value);
+                                    XCLIENT_HELO, attr_value);
                    return (-1);
                }
-               neuter(cooked_value, "<>()\\\";:@", '?');
-               UPD_STR_ATTR(state, function, helo_name, cooked_value);
+               neuter(attr_value, "<>()\\\";:@", '?');
+               UPDATE_STR(state->helo_name, attr_value);
            } else {
-               RST_STR_ATTR(state, function, helo_name);
+               UPDATE_STR(state->helo_name, CLIENT_HELO_UNKNOWN);
            }
        }
 
        /*
-        * CLIENT_PROTO=protocol name. Disallow characters that could mess up
-        * our own Received: message headers.
+        * PROTO=protocol name. Disallow characters that could mess up our
+        * own Received: message headers.
         */
-       else if (STREQ(arg_val, XCLIENT_PROTO)) {
-           if (*raw_value) {
-               if (*cooked_value == 0 || strlen(cooked_value) > 64) {
-                   state->error_mask |= MAIL_ERROR_PROTOCOL;
-                   smtpd_chat_reply(state, "501 Bad %s syntax: %s",
-                                    XCLIENT_PROTO, raw_value);
-                   return (-1);
-               }
-               neuter(cooked_value, "[]<>()\\\";:@", '?');
-               UPD_STR_ATTR(state, function, protocol, cooked_value);
-           } else {
-               UPD_STR_ATTR(state, function, protocol, CLIENT_PROTO_UNKNOWN);
+       else if (STREQ(attr_name, XCLIENT_PROTO)) {
+           if (name_code(xclient_proto, NAME_CODE_FLAG_NONE, attr_value) < 0) {
+               state->error_mask |= MAIL_ERROR_PROTOCOL;
+               smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                XCLIENT_PROTO, attr_value);
+               return (-1);
            }
+           UPDATE_STR(state->protocol, attr_value);
        }
 
        /*
-        * Unknown attribute name. Don't complain, and log a warning. Logging
-        * is safe because only authorized clients can issue XCLIENT
-        * commands.
+        * Unknown attribute name. Complain.
         */
        else {
-           msg_warn("unknown %s attribute from %s: %s=%s",
-                    XCLIENT_CMD, state->namaddr, arg_val, cooked_value);
+           state->error_mask |= MAIL_ERROR_PROTOCOL;
+           smtpd_chat_reply(state, "501 Bad %s attribute name: %s",
+                            XCLIENT_CMD, attr_name);
+           return (-1);
        }
     }
 
@@ -1957,11 +1898,173 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      * Update the combined name and address when either has changed.
      */
     if (update_namaddr) {
-       if (STR_ATTR(state, function, namaddr))
-           myfree(STR_ATTR(state, function, namaddr));
-       STR_ATTR(state, function, namaddr) =
-           concatenate(STR_ATTR(state, function, name), "[",
-                       STR_ATTR(state, function, addr), "]",
+       if (state->namaddr)
+           myfree(state->namaddr);
+       state->namaddr =
+           concatenate(state->name, "[", state->addr, "]", (char *) 0);
+    }
+    smtpd_chat_reply(state, "250 Ok");
+    return (0);
+}
+
+/* xforward_cmd - forward logging attributes */
+
+static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
+{
+    int     arg_no;
+    char   *attr_value;
+    char   *attr_name;
+    int     updated = 0;
+    static NAME_CODE xforward_flags[] = {
+       XFORWARD_NAME, SMTPD_XFORWARD_FLAG_NAME,
+       XFORWARD_ADDR, SMTPD_XFORWARD_FLAG_ADDR,
+       XFORWARD_PROTO, SMTPD_XFORWARD_FLAG_PROTO,
+       XFORWARD_HELO, SMTPD_XFORWARD_FLAG_HELO,
+       0, 0,
+    };
+    int     flag;
+
+    /*
+     * Sanity checks.
+     */
+    if (IN_MAIL_TRANSACTION(state)) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "503 Error: MAIL transaction in progress");
+       return (-1);
+    }
+    if (argc < 2) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "501 Syntax: %s name=value...",
+                        XFORWARD_CMD);
+       return (-1);
+    }
+    if (!xforward_allowed) {
+       state->error_mask |= MAIL_ERROR_POLICY;
+       smtpd_chat_reply(state, "554 Error: insufficient authorization");
+       return (-1);
+    }
+
+    /*
+     * Initialize.
+     */
+    if (state->xforward.flags == 0)
+       smtpd_xforward_preset(state);
+
+    /*
+     * Iterate over all NAME=VALUE attributes.
+     */
+    for (arg_no = 1; arg_no < argc; arg_no++) {
+       attr_name = argv[arg_no].strval;
+
+       /*
+        * For safety's sake mask non-printable characters in the raw and
+        * decoded values; we don't want to handle unexploded munitions.
+        * Complain when they send an attribute that we didn't announce.
+        * 
+        * The client can send multiple XFORWARD attributes in a single command,
+        * or multiple XFORWARD commands with fewer attributes.
+        */
+       if ((attr_value = split_at(attr_name, '=')) == 0) {
+           state->error_mask |= MAIL_ERROR_PROTOCOL;
+           smtpd_chat_reply(state, "501 Error: name=value expected");
+           return (-1);
+       }
+       printable(attr_value, '?');
+
+       flag = name_code(xforward_flags, NAME_CODE_FLAG_NONE, attr_name);
+       switch (flag) {
+
+           /*
+            * NAME=hostname. Also updates the client hostname lookup status
+            * code. Treat a numerical hostname as an unavailable name.
+            */
+       case SMTPD_XFORWARD_FLAG_NAME:
+           if (*attr_value && !valid_hostaddr(attr_value, DONT_GRIPE)) {
+               if (!valid_hostname(attr_value, DONT_GRIPE)) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                    XFORWARD_NAME, attr_value);
+                   return (-1);
+               }
+           } else {
+               attr_value = CLIENT_NAME_UNKNOWN;
+           }
+           UPDATE_STR(state->xforward.name, attr_value);
+           break;
+
+           /*
+            * ADDR=client network address.
+            */
+       case SMTPD_XFORWARD_FLAG_ADDR:
+           if (*attr_value) {
+               if (!valid_hostaddr(attr_value, DONT_GRIPE)) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                    XFORWARD_ADDR, attr_value);
+                   return (-1);
+               }
+           } else {
+               attr_value = CLIENT_ADDR_UNKNOWN;
+           }
+           UPDATE_STR(state->xforward.addr, attr_value);
+           break;
+
+           /*
+            * HELO=hostname. Disallow characters that could mess up our own
+            * Received: message headers but allow [].
+            */
+       case SMTPD_XFORWARD_FLAG_HELO:
+           if (*attr_value) {
+               if (strlen(attr_value) > VALID_HOSTNAME_LEN) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                    XFORWARD_HELO, attr_value);
+                   return (-1);
+               }
+               neuter(attr_value, "<>()\\\";:@", '?');
+           } else {
+               attr_value = CLIENT_HELO_UNKNOWN;
+           }
+           UPDATE_STR(state->xforward.helo_name, attr_value);
+           break;
+
+           /*
+            * PROTO=protocol name. Neutralize characters that could mess up
+            * our own Received: message headers.
+            */
+       case SMTPD_XFORWARD_FLAG_PROTO:
+           if (strlen(attr_value) > 64) {
+               state->error_mask |= MAIL_ERROR_PROTOCOL;
+               smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                XFORWARD_PROTO, attr_value);
+               return (-1);
+           }
+           neuter(attr_value, "<>()\\\";:@", '?');
+           UPDATE_STR(state->xforward.protocol, attr_value);
+           break;
+
+           /*
+            * Unknown attribute name. Complain.
+            */
+       default:
+           state->error_mask |= MAIL_ERROR_PROTOCOL;
+           smtpd_chat_reply(state, "501 Bad %s attribute name: %s",
+                            XFORWARD_CMD, attr_name);
+           return (-1);
+       }
+       updated |= flag;
+    }
+    state->xforward.flags |= updated;
+
+    /*
+     * Update the combined name and address when either has changed.
+     */
+    if (updated & (SMTPD_XFORWARD_FLAG_NAME | SMTPD_XFORWARD_FLAG_ADDR)) {
+       if (state->xforward.namaddr)
+           myfree(state->xforward.namaddr);
+       state->xforward.namaddr =
+           concatenate(state->xforward.name, "[",
+                       state->xforward.addr, "]",
                        (char *) 0);
     }
     smtpd_chat_reply(state, "250 Ok");
@@ -2001,7 +2104,7 @@ typedef struct SMTPD_CMD {
 } SMTPD_CMD;
 
 #define SMTPD_CMD_FLAG_LIMIT    (1<<0) /* limit usage */
-#define SMTPD_CMD_FLAG_FORBIDDEN       (1<<1)  /* RFC 2822 mail header */
+#define SMTPD_CMD_FLAG_FORBID  (1<<1)  /* RFC 2822 mail header */
 
 static SMTPD_CMD smtpd_cmd_table[] = {
     "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
@@ -2020,13 +2123,14 @@ static SMTPD_CMD smtpd_cmd_table[] = {
     "ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
     "QUIT", quit_cmd, 0,
     "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,
-    "Subject:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
-    "From:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
-    "CONNECT", 0, SMTPD_CMD_FLAG_FORBIDDEN,
-    "User-Agent:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
+    "XFORWARD", xforward_cmd, SMTPD_CMD_FLAG_LIMIT,
+    "Received:", 0, SMTPD_CMD_FLAG_FORBID,
+    "Reply-To:", 0, SMTPD_CMD_FLAG_FORBID,
+    "Message-ID:", 0, SMTPD_CMD_FLAG_FORBID,
+    "Subject:", 0, SMTPD_CMD_FLAG_FORBID,
+    "From:", 0, SMTPD_CMD_FLAG_FORBID,
+    "CONNECT", 0, SMTPD_CMD_FLAG_FORBID,
+    "User-Agent:", 0, SMTPD_CMD_FLAG_FORBID,
     0,
 };
 
@@ -2147,7 +2251,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
                state->error_count++;
                continue;
            }
-           if (cmdp->flags & SMTPD_CMD_FLAG_FORBIDDEN) {
+           if (cmdp->flags & SMTPD_CMD_FLAG_FORBID) {
                msg_warn("%s sent non-SMTP command: %.100s",
                         state->namaddr, vstring_str(state->buffer));
                smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
@@ -2240,6 +2344,12 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
     xclient_allowed =
        namadr_list_match(xclient_hosts, state.name, state.addr);
 
+    /*
+     * Overriding XFORWARD access control makes no sense, either.
+     */
+    xforward_allowed =
+       namadr_list_match(xforward_hosts, state.name, state.addr);
+
     /*
      * See if we need to turn on verbose logging for this client.
      */
@@ -2283,6 +2393,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);
     xclient_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xclient_hosts);
+    xforward_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xforward_hosts);
     hogger_list = namadr_list_init(MATCH_FLAG_NONE, var_smtpd_hoggers);
     if (getuid() == 0 || getuid() == var_owner_uid)
        smtpd_check_init();
@@ -2421,6 +2532,7 @@ int     main(int argc, char **argv)
        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_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0,
+       VAR_XFORWARD_HOSTS, DEF_XFORWARD_HOSTS, &var_xforward_hosts, 0, 0,
        VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0,
        0,
     };
index b6bbe570952187610c0a2b0ef76a2a024b3302c8..831fa72a646ff54ee9fd4177d7b1d3083c7c03f9 100644 (file)
@@ -45,15 +45,26 @@ typedef struct SMTPD_DEFER {
     int     class;                     /* error notification class */
 } SMTPD_DEFER;
 
-typedef struct SMTPD_XCLIENT_ATTR {
-    int     used;                      /* status */
+typedef struct SMTPD_XFORWARD_ATTR {
+    int     flags;                     /* see below */
     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;
+    char   *ident;                     /* message identifier */
+} SMTPD_XFORWARD_ATTR;
+
+#define SMTPD_XFORWARD_FLAG_INIT (1<<0)        /* preset done */
+#define SMTPD_XFORWARD_FLAG_NAME (1<<1)        /* client name received */
+#define SMTPD_XFORWARD_FLAG_ADDR (1<<2)        /* client address received */
+#define SMTPD_XFORWARD_FLAG_PROTO (1<<3)/* protocol received */
+#define SMTPD_XFORWARD_FLAG_HELO (1<<4)        /* client helo received */
+#define SMTPD_XFORWARD_FLAG_IDENT (1<<5)/* message identifier received */
+
+#define SMTPD_XFORWARD_FLAG_CLIENT_MASK \
+       (SMTPD_XFORWARD_FLAG_NAME | SMTPD_XFORWARD_FLAG_ADDR \
+       | SMTPD_XFORWARD_FLAG_PROTO | SMTPD_XFORWARD_FLAG_HELO)
 
 typedef struct SMTPD_STATE {
     int     err;
@@ -113,8 +124,8 @@ typedef struct SMTPD_STATE {
     VSTREAM *proxy;                    /* proxy handle */
     VSTRING *proxy_buffer;             /* proxy query/reply buffer */
     char   *proxy_mail;                        /* owned by mail_cmd() */
-    int     proxy_features;            /* proxy ESMTP features */
-    SMTPD_XCLIENT_ATTR xclient;                /* override access control */
+    int     proxy_xforward_features;   /* proxy XFORWARD features */
+    SMTPD_XFORWARD_ATTR xforward;      /* override access control */
 } SMTPD_STATE;
 
 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
@@ -127,6 +138,30 @@ extern void smtpd_state_reset(SMTPD_STATE *);
 #define SMTPD_AFTER_CONNECT    "CONNECT"
 #define SMTPD_AFTER_DOT                "END-OF-MESSAGE"
 
+ /*
+  * Postfix representation of unknown client information within smtpd
+  * processes. This is not the representation that Postfix uses in queue
+  * files, in queue manager delivery requests, nor is it the representation
+  * of information in XCLIENT/XFORWARD commands!
+  */
+#define CLIENT_ATTR_UNKNOWN    "unknown"
+
+#define CLIENT_NAME_UNKNOWN    CLIENT_ATTR_UNKNOWN
+#define CLIENT_ADDR_UNKNOWN    CLIENT_ATTR_UNKNOWN
+#define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
+#define CLIENT_HELO_UNKNOWN    0
+#define CLIENT_PROTO_UNKNOWN   CLIENT_ATTR_UNKNOWN
+#define CLIENT_IDENT_UNKNOWN   0
+
+#define IS_AVAIL_CLIENT_ATTR(v)        ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
+
+#define IS_AVAIL_CLIENT_NAME(v)        IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_ADDR(v)        IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_HELO(v)        ((v) != 0)
+#define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_IDENT(v) ((v) != 0)
+
  /*
   * If running in stand-alone mode, do not try to talk to Postfix daemons but
   * write to queue file instead.
@@ -162,23 +197,37 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
   * 
   * Note 2: outside the SMTP server, the representation of unknown/known
   * attribute values is different in queue files, in queue manager delivery
-  * requests, and in over-the-network XCLIENT commands.
+  * requests, and in over-the-network XFORWARD commands.
   */
-#define SMTPD_FEATURE_XCLIENT (1<<0)   /* proxy announces XCLIENT */
-
-#define MAYBE_FORWARD(s, a) \
-       ((s)->xclient.used ? (s)->xclient.a : (s)->a)
+#define SMTPD_PROXY_XFORWARD_NAME (1<<0)       /* client name */
+#define SMTPD_PROXY_XFORWARD_ADDR (1<<1)       /* client address */
+#define SMTPD_PROXY_XFORWARD_PROTO (1<<2)      /* protocol */
+#define SMTPD_PROXY_XFORWARD_HELO (1<<3)       /* client helo */
+#define SMTPD_PROXY_XFORWARD_IDENT (1<<4)      /* message identifier */
 
-#define FORWARD_ADDR(s)                MAYBE_FORWARD((s), addr)
-#define FORWARD_NAME(s)                MAYBE_FORWARD((s), name)
-#define FORWARD_NAMADDR(s)     MAYBE_FORWARD((s), namaddr)
-#define FORWARD_CODE(s)                MAYBE_FORWARD((s), peer_code)
-#define FORWARD_PROTO(s)       MAYBE_FORWARD((s), protocol)
-#define FORWARD_HELO(s)                MAYBE_FORWARD((s), helo_name)
-
-extern void smtpd_xclient_init(SMTPD_STATE *state);
-extern void smtpd_xclient_preset(SMTPD_STATE *state);
-extern void smtpd_xclient_reset(SMTPD_STATE *state);
+ /*
+  * If forwarding client information, don't mix direct client information
+  * from the current SMTP session with forwarded client information from an
+  * up-stream session.
+  */
+#define FORWARD_CLIENT_ATTR(s, a) \
+       (((s)->xforward.flags & SMTPD_XFORWARD_FLAG_CLIENT_MASK) ? \
+           (s)->xforward.a : (s)->a)
+
+#define FORWARD_IDENT_ATTR(s) \
+       (((s)->xforward.flags & SMTPD_XFORWARD_FLAG_IDENT) ? \
+           (s)->queue_id : (s)->ident)
+
+#define FORWARD_ADDR(s)                FORWARD_CLIENT_ATTR((s), addr)
+#define FORWARD_NAME(s)                FORWARD_CLIENT_ATTR((s), name)
+#define FORWARD_NAMADDR(s)     FORWARD_CLIENT_ATTR((s), namaddr)
+#define FORWARD_PROTO(s)       FORWARD_CLIENT_ATTR((s), protocol)
+#define FORWARD_HELO(s)                FORWARD_CLIENT_ATTR((s), helo_name)
+#define FORWARD_IDENT(s)       FORWARD_IDENT_ATTR(s)
+
+extern void smtpd_xforward_init(SMTPD_STATE *state);
+extern void smtpd_xforward_preset(SMTPD_STATE *state);
+extern void smtpd_xforward_reset(SMTPD_STATE *state);
 
  /*
   * Transparency: before mail is queued, do we check for unknown recipients,
index 22da5f045d6e995c88d00a85a37def2c64d438dd..3bcdcbcaa59089a7147f19ba864d95160b55e15b 100644 (file)
@@ -784,6 +784,9 @@ void    smtpd_check_init(void)
     htable_enter(smtpd_rest_classes, "check_relay_domains",
            smtpd_check_parse("permit_mydomain reject_unauth_destination"));
 #endif
+    htable_enter(smtpd_rest_classes, REJECT_SENDER_LOGIN_MISMATCH,
+                (char *) smtpd_check_parse(REJECT_AUTH_SENDER_LOGIN_MISMATCH
+                                 " " REJECT_UNAUTH_SENDER_LOGIN_MISMATCH));
 
     /*
      * People screw up the relay restrictions too often. Require that they
@@ -2849,42 +2852,70 @@ static int reject_maps_rbl(SMTPD_STATE *state)
     return (result);
 }
 
-/* reject_sender_login_mismatch - reject login/sender ownership mismatch */
+#ifdef USE_SASL
 
-static int reject_sender_login_mismatch(SMTPD_STATE *state, const char *sender)
+/* reject_auth_sender_login_mismatch - logged in client must own sender address */
+
+static int reject_auth_sender_login_mismatch(SMTPD_STATE *state, const char *sender)
 {
     const RESOLVE_REPLY *reply;
-    const char *login = 0;
-    const char *owner = 0;
+    const char *owners;
+    char   *saved_owners;
+    char   *cp;
+    char   *name;
+    int     found = 0;
 
     /*
-     * If the sender address is owned by a login name, or if the client has
-     * logged in, then require that the client is logged in as the owner of
-     * the sender address.
+     * Reject if the client is logged in and does not own the sender address.
      */
-    reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, sender);
-    if (reply->flags & RESOLVE_FLAG_FAIL)
-       reject_dict_retry(state, sender);
-    owner = check_mail_addr_find(state, sender, smtpd_sender_login_maps,
-                                STR(reply->recipient), (char **) 0);
-#ifdef USE_SASL_AUTH
-    if (var_smtpd_sasl_enable && state->sasl_username != 0)
-       login = state->sasl_username;
-#endif
-    if (login) {
-       if (owner == 0 || strcasecmp(login, owner) != 0)
+    if (var_smtpd_sasl_enable && state->sasl_username != 0) {
+       reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, sender);
+       if (reply->flags & RESOLVE_FLAG_FAIL)
+           reject_dict_retry(state, sender);
+       if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps,
+                               STR(reply->recipient), (char **) 0)) != 0) {
+           cp = saved_owners = mystrdup(owners);
+           while ((name = mystrtok(&cp, ", \t\r\n")) != 0) {
+               if (strcasecmp(state->sasl_username, name) == 0) {
+                   found = 1;
+                   break;
+               }
+           }
+           myfree(saved_owners);
+       }
+       if (!found)
            return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
                  "553 <%s>: Sender address rejected: not owned by user %s",
-                                      sender, login));
-    } else {
-       if (owner)
+                                      sender, state->sasl_username));
+    }
+    return (SMTPD_CHECK_DUNNO);
+}
+
+/* reject_unauth_sender_login_mismatch - sender requires client is logged in */
+
+static int reject_unauth_sender_login_mismatch(SMTPD_STATE *state, const char *sender)
+{
+    const RESOLVE_REPLY *reply;
+    const char *login = 0;
+
+    /*
+     * Reject if the client is not logged in and the sender address has an
+     * owner.
+     */
+    if (var_smtpd_sasl_enable && state->sasl_username == 0) {
+       reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, sender);
+       if (reply->flags & RESOLVE_FLAG_FAIL)
+           reject_dict_retry(state, sender);
+       if (check_mail_addr_find(state, sender, smtpd_sender_login_maps,
+                                STR(reply->recipient), (char **) 0) != 0)
            return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
-               "553 <%s>: Sender address rejected: not logged in as owner",
-                                      sender));
+              "553 <%s>: Sender address rejected: not logged in", sender));
     }
     return (SMTPD_CHECK_DUNNO);
 }
 
+#endif
+
 /* check_policy_service - check delegated policy service */
 
 static int check_policy_service(SMTPD_STATE *state, const char *server,
@@ -3204,9 +3235,22 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
            if (state->sender && *state->sender)
                status = reject_non_fqdn_address(state, state->sender,
                                          state->sender, SMTPD_NAME_SENDER);
-       } else if (strcasecmp(name, REJECT_SENDER_LOGIN_MISMATCH) == 0) {
-           if (state->sender && *state->sender)
-               status = reject_sender_login_mismatch(state, state->sender);
+       } else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) {
+#ifdef USE_SASL
+           if (var_smtpd_sasl_enable) {
+               if (state->sender && *state->sender)
+                   status = reject_auth_sender_login_mismatch(state, state->sender);
+           } else
+#endif
+               msg_warn("restriction `%s' ignored: no SASL support", name);
+       } else if (strcasecmp(name, REJECT_UNAUTH_SENDER_LOGIN_MISMATCH) == 0) {
+#ifdef USE_SASL
+           if (var_smtpd_sasl_enable) {
+               if (state->sender && *state->sender)
+                   status = reject_unauth_sender_login_mismatch(state, state->sender);
+           } else
+#endif
+               msg_warn("restriction `%s' ignored: no SASL support", name);
        } else if (is_map_command(state, name, CHECK_SENDER_NS_ACL, &cpp)) {
            if (state->sender && *state->sender) {
                status = check_server_access(state, *cpp, state->sender,
index 103d2080c56a12c370d6a79550097f0421725715..074e4e14c342d665f2163696d56d39568a7fafa3 100644 (file)
@@ -52,7 +52,7 @@
 /*     mail.
 /*
 /*     smtpd_proxy_open() connects to the proxy service, sends EHLO, sends
-/*     client information with the XCLIENT command if possible, sends
+/*     client information with the XFORWARD 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.
 #include <vstring.h>
 #include <stringops.h>
 #include <connect.h>
+#include <name_code.h>
 
 /* Global library. */
 
 #define LEN(x) VSTRING_LEN(x)
 #define SMTPD_PROXY_CONNECT ((char *) 0)
 
+/* smtpd_xforward_flush - flush forwarding information */
+
+static int smtpd_xforward_flush(SMTPD_STATE *state, VSTRING *buf)
+{
+    int     ret;
+
+    if (VSTRING_LEN(buf) > 0) {
+       ret = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK,
+                             XFORWARD_CMD "%s", STR(buf));
+       VSTRING_RESET(buf);
+       return (ret);
+    }
+    return (0);
+}
+
+/* smtpd_xforward - send forwarding information */
+
+static int smtpd_xforward(SMTPD_STATE *state, VSTRING *buf, const char *name,
+                                 int value_available, const char *value)
+{
+    size_t  new_len;
+    int     ret;
+
+#define CONSTR_LEN(s)  (sizeof(s) - 1)
+#define PAYLOAD_LIMIT  (512 - CONSTR_LEN("250 " XFORWARD_CMD "\r\n"))
+
+    /*
+     * How much space does this attribute need?
+     */
+    if (!value_available)
+       value = "";
+    new_len = strlen(name) + strlen(value) + 2;        /* SPACE name = value */
+    if (new_len > PAYLOAD_LIMIT)
+       msg_warn("%s payload %s=%.10s... exceeds SMTP protocol limit",
+                XFORWARD_CMD, name, value);
+
+    /*
+     * Flush the buffer if we need to, and store the attribute.
+     */
+    if (VSTRING_LEN(buf) > 0 && VSTRING_LEN(buf) + new_len > PAYLOAD_LIMIT)
+       if ((ret = smtpd_xforward_flush(state, buf)) < 0)
+           return (ret);
+    vstring_sprintf_append(buf, " %s=%s", name, value);
+
+    return (0);
+}
+
 /* smtpd_proxy_open - open proxy connection */
 
 int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
@@ -178,9 +226,17 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
 {
     int     fd;
     char   *lines;
-    char   *line;
+    char   *words;
     VSTRING *buf;
     int     bad;
+    char   *word;
+    static NAME_CODE xforward_features[] = {
+       XFORWARD_NAME, SMTPD_PROXY_XFORWARD_NAME,
+       XFORWARD_ADDR, SMTPD_PROXY_XFORWARD_ADDR,
+       XFORWARD_PROTO, SMTPD_PROXY_XFORWARD_PROTO,
+       XFORWARD_HELO, SMTPD_PROXY_XFORWARD_HELO,
+       0, 0,
+    };
 
     /*
      * This buffer persists beyond the end of a proxy session so we can
@@ -236,41 +292,41 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     /*
      * Parse the EHLO reply and see if we can forward logging information.
      */
-    state->proxy_features = 0;
+    state->proxy_xforward_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, XCLIENT_CMD) == 0)
-           state->proxy_features |= SMTPD_FEATURE_XCLIENT;
+    while ((words = mystrtok(&lines, "\n")) != 0) {
+       if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t")) != 0) {
+           if (strcasecmp(word, XFORWARD_CMD) == 0)
+               while ((word = mystrtok(&words, " \t")) != 0)
+                   state->proxy_xforward_features |=
+                       name_code(xforward_features, NAME_CODE_FLAG_NONE, word);
+       }
+    }
 
     /*
-     * Send all XCLIENT attributes, but only if we have some minimal amount
-     * of remote client information. Transform internal forms to external
-     * forms and encode the result as xtext.
+     * Send XFORWARD attributes. For robustness, explicitly specify what SMTP
+     * session attributes are known and unknown.
      */
-    if ((state->proxy_features & SMTPD_FEATURE_XCLIENT)
-       && (IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state))
-           || IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)))) {
+    if (state->proxy_xforward_features) {
        buf = vstring_alloc(100);
-       vstring_strcpy(buf, XCLIENT_CMD " " XCLIENT_FORWARD
-                      " " XCLIENT_NAME "=");
-       if (IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state)))
-           xtext_quote_append(buf, FORWARD_NAME(state), "");
-       vstring_strcat(buf, " " XCLIENT_ADDR "=");
-       if (IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)))
-           xtext_quote_append(buf, FORWARD_ADDR(state), "");
-       bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
-       if (bad == 0) {
-           vstring_strcpy(buf, XCLIENT_CMD " " XCLIENT_FORWARD
-                          " " XCLIENT_HELO "=");
-           if (IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state)))
-               xtext_quote_append(buf, FORWARD_HELO(state), "");
-           vstring_strcat(buf, " " XCLIENT_PROTO "=");
-           if (IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state)))
-               xtext_quote_append(buf, FORWARD_PROTO(state), "");
-           bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
-       }
+       bad = 0;
+       if ((state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_NAME)
+           && !(bad = smtpd_xforward(state, buf, XFORWARD_NAME,
+                                 IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state)),
+                                     FORWARD_NAME(state)))
+           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_ADDR)
+           && !(bad = smtpd_xforward(state, buf, XFORWARD_ADDR,
+                                 IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)),
+                                     FORWARD_ADDR(state)))
+           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_HELO)
+           && !(bad = smtpd_xforward(state, buf, XFORWARD_HELO,
+                                 IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state)),
+                                     FORWARD_HELO(state)))
+           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_PROTO)
+           && !(bad = smtpd_xforward(state, buf, XFORWARD_PROTO,
+                               IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state)),
+                                     FORWARD_PROTO(state))))
+           bad = smtpd_xforward_flush(state, buf);
        vstring_free(buf);
        if (bad) {
            vstring_sprintf(state->proxy_buffer,
index 1071d05b81abf1058c60586e6307ed4b9ad2b4d1..d64601deacf7edd20be2f747b9e994c51192be66 100644 (file)
@@ -103,7 +103,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->proxy = 0;
     state->proxy_buffer = 0;
     state->proxy_mail = 0;
-    state->proxy_features = 0;
+    state->proxy_xforward_features = 0;
     state->saved_filter = 0;
     state->saved_redirect = 0;
     state->saved_flags = 0;
@@ -121,9 +121,9 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     smtpd_peer_init(state);
 
     /*
-     * Initialize xclient information.
+     * Initialize xforward information.
      */
-    smtpd_xclient_init(state);
+    smtpd_xforward_init(state);
 
     /*
      * Initialize the conversation history.
diff --git a/postfix/src/smtpd/smtpd_xclient.c b/postfix/src/smtpd/smtpd_xclient.c
deleted file mode 100644 (file)
index f868811..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*++
-/* 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)
-/*     SMTPD_STATE *state;
-/* DESCRIPTION
-/*     smtpd_xclient_init() zeroes the attributes for storage of XCLIENT
-/*     FORWARD command parameters.
-/*
-/*     smtpd_xclient_preset() takes the result from smtpd_xclient_init()
-/*     and sets all fields to the same "unknown" value that regular
-/*     client attributes would have.
-/*
-/*     smtpd_xclient_reset() restores the state from smtpd_xclient_init().
-/* 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.used = 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_preset - set xclient attributes to "unknown" */
-
-void    smtpd_xclient_preset(SMTPD_STATE *state)
-{
-
-    /*
-     * This is a temporary solution. Unknown forwarded attributes get the
-     * same values as unknown normal attributes, so that we don't break
-     * assumptions in pre-existing code.
-     */
-    state->xclient.used = 1;
-    state->xclient.name = mystrdup(CLIENT_NAME_UNKNOWN);
-    state->xclient.addr = mystrdup(CLIENT_ADDR_UNKNOWN);
-    state->xclient.namaddr = mystrdup(CLIENT_NAMADDR_UNKNOWN);
-    state->xclient.protocol = mystrdup(CLIENT_PROTO_UNKNOWN);
-}
-
-/* smtpd_xclient_reset - reset XCLIENT attributes */
-
-void    smtpd_xclient_reset(SMTPD_STATE *state)
-{
-#define FREE_AND_WIPE(s) { if (s) myfree(s); s = 0; }
-
-    state->xclient.used = 0;
-    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);
-}
diff --git a/postfix/src/smtpd/smtpd_xforward.c b/postfix/src/smtpd/smtpd_xforward.c
new file mode 100644 (file)
index 0000000..280c00a
--- /dev/null
@@ -0,0 +1,103 @@
+/*++
+/* NAME
+/*     smtpd_xforward 3
+/* SUMMARY
+/*     maintain XCLIENT information
+/* SYNOPSIS
+/*     #include "smtpd.h"
+/*
+/*     void    smtpd_xforward_init(state)
+/*     SMTPD_STATE *state;
+/*
+/*     void    smtpd_xforward_reset(state)
+/*     SMTPD_STATE *state;
+/* DESCRIPTION
+/*     smtpd_xforward_init() zeroes the attributes for storage of
+/*     XFORWARD command parameters.
+/*
+/*     smtpd_xforward_preset() takes the result from smtpd_xforward_init()
+/*     and sets all fields to the same "unknown" value that regular
+/*     client attributes would have.
+/*
+/*     smtpd_xforward_reset() restores the state from smtpd_xforward_init().
+/* 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_xforward_init - initialize XCLIENT attributes */
+
+void    smtpd_xforward_init(SMTPD_STATE *state)
+{
+    state->xforward.flags = 0;
+    state->xforward.name = 0;
+    state->xforward.addr = 0;
+    state->xforward.namaddr = 0;
+    state->xforward.protocol = 0;
+    state->xforward.helo_name = 0;
+    state->xforward.ident = 0;
+}
+
+/* smtpd_xforward_preset - set xforward attributes to "unknown" */
+
+void    smtpd_xforward_preset(SMTPD_STATE *state)
+{
+
+    /*
+     * Sanity checks.
+     */
+    if (state->xforward.flags)
+       msg_panic("smtpd_xforward_preset: bad flags: 0x%x",
+                 state->xforward.flags);
+
+    /*
+     * This is a temporary solution. Unknown forwarded attributes get the
+     * same values as unknown normal attributes, so that we don't break
+     * assumptions in pre-existing code.
+     */
+    state->xforward.flags = SMTPD_XFORWARD_FLAG_INIT;
+    state->xforward.name = mystrdup(CLIENT_NAME_UNKNOWN);
+    state->xforward.addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+    state->xforward.namaddr = mystrdup(CLIENT_NAMADDR_UNKNOWN);
+    /* Leave helo at zero. */
+    state->xforward.protocol = mystrdup(CLIENT_PROTO_UNKNOWN);
+    /* Leave ident at zero. */
+}
+
+/* smtpd_xforward_reset - reset XCLIENT attributes */
+
+void    smtpd_xforward_reset(SMTPD_STATE *state)
+{
+#define FREE_AND_WIPE(s) { if (s) myfree(s); s = 0; }
+
+    state->xforward.flags = 0;
+    FREE_AND_WIPE(state->xforward.name);
+    FREE_AND_WIPE(state->xforward.addr);
+    FREE_AND_WIPE(state->xforward.namaddr);
+    FREE_AND_WIPE(state->xforward.protocol);
+    FREE_AND_WIPE(state->xforward.helo_name);
+    FREE_AND_WIPE(state->xforward.ident);
+}
index fdb2f8690d26bfdd978ba3728d2ca3f76b4dc635..cc50623409c496968bda83075e36efdc7730f69b 100644 (file)
@@ -793,8 +793,10 @@ int     main(int argc, char **argv)
            count++;
            break;
        case 'C':
-           if ((connect_count = atoi(optarg)) <= 0)
+           if ((connect_count = atoi(optarg)) <= 0) {
+               msg_error("bad connection count: %s", optarg);
                usage(argv[0]);
+           }
            break;
        case 'd':
            disconnect = 0;
@@ -803,8 +805,10 @@ int     main(int argc, char **argv)
            sender = optarg;
            break;
        case 'l':
-           if ((message_length = atoi(optarg)) <= 0)
+           if ((message_length = atoi(optarg)) <= 0) {
+               msg_error("bad message length: %s", optarg);
                usage(argv[0]);
+           }
            message_data = mymalloc(message_length);
            memset(message_data, 'X', message_length);
            for (i = 80; i < message_length; i += 80) {
@@ -817,24 +821,36 @@ int     main(int argc, char **argv)
            talk_lmtp = 1;
            break;
        case 'm':
-           if ((message_count = atoi(optarg)) <= 0)
+           if ((message_count = atoi(optarg)) <= 0) {
+               msg_error("bad message count: %s", optarg);
                usage(argv[0]);
+           }
            break;
        case 'o':
            send_helo_first = 0;
            send_headers = 0;
            break;
        case 'r':
-           if ((recipients = atoi(optarg)) <= 0)
+           if ((recipients = atoi(optarg)) <= 0) {
+               msg_error("bad recipient count: %s", optarg);
                usage(argv[0]);
+           }
            break;
        case 'R':
-           if (fixed_delay > 0 || (random_delay = atoi(optarg)) <= 0)
+           if (fixed_delay > 0) {
+               msg_error("do not use -w and -R options at the same time");
+               usage(argv[0]);
+           }
+           if ((random_delay = atoi(optarg)) <= 0) {
+               msg_error("bad random delay: %s", optarg);
                usage(argv[0]);
+           }
            break;
        case 's':
-           if ((sessions = atoi(optarg)) <= 0)
+           if ((sessions = atoi(optarg)) <= 0) {
+               msg_error("bad session count: %s", optarg);
                usage(argv[0]);
+           }
            break;
        case 'S':
            subject = optarg;
@@ -846,8 +862,14 @@ int     main(int argc, char **argv)
            msg_verbose++;
            break;
        case 'w':
-           if (random_delay > 0 || (fixed_delay = atoi(optarg)) <= 0)
+           if (random_delay > 0) {
+               msg_error("do not use -w and -R options at the same time");
                usage(argv[0]);
+           }
+           if ((fixed_delay = atoi(optarg)) <= 0) {
+               msg_error("bad fixed delay: %s", optarg);
+               usage(argv[0]);
+           }
            break;
        default:
            usage(argv[0]);
index ff94f0328595a7441cc7336ac47cff5ab2e0c1f4..bf3fb84ce294b553189e4eab75e155ec41a55466 100644 (file)
@@ -95,13 +95,16 @@ ARGV   *argv_free(ARGV *argvp)
 ARGV   *argv_alloc(int len)
 {
     ARGV   *argvp;
+    int     sane_len;
 
     /*
      * Make sure that always argvp->argc < argvp->len.
      */
     argvp = (ARGV *) mymalloc(sizeof(*argvp));
-    argvp->len = (len < 2 ? 2 : len);
-    argvp->argv = (char **) mymalloc((argvp->len + 1) * sizeof(char *));
+    argvp->len = 0;
+    sane_len = (len < 2 ? 2 : len);
+    argvp->argv = (char **) mymalloc((sane_len + 1) * sizeof(char *));
+    argvp->len = sane_len;
     argvp->argc = 0;
     argvp->argv[0] = 0;
     return (argvp);
@@ -111,10 +114,12 @@ ARGV   *argv_alloc(int len)
 
 static void argv_extend(ARGV *argvp)
 {
-    argvp->len *= 2;
+    int     new_len;
+
+    new_len = argvp->len * 2;
     argvp->argv = (char **)
-       myrealloc((char *) argvp->argv,
-                 (argvp->len + 1) * sizeof(char *));
+       myrealloc((char *) argvp->argv, (new_len + 1) * sizeof(char *));
+    argvp->len = new_len;
 }
 
 /* argv_add - add string to vector */
index fa1cbd3990087202767b87488c6bf0d1977d738a..49ae833d568698c92ccd8dd24e14ab7e6aa58f4d 100644 (file)
 
 void    inet_addr_list_init(INET_ADDR_LIST *list)
 {
+    int     init_size;
+
     list->used = 0;
-    list->size = 2;
-    list->addrs = (struct in_addr *)
-       mymalloc(sizeof(*list->addrs) * list->size);
+    list->size = 0;
+    init_size = 2;
+    list->addrs = (struct in_addr *) mymalloc(sizeof(*list->addrs) * init_size);
+    list->size = init_size;
 }
 
 /* inet_addr_list_append - append address to internet address list */
@@ -72,15 +75,17 @@ void    inet_addr_list_init(INET_ADDR_LIST *list)
 void    inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
 {
     char   *myname = "inet_addr_list_append";
+    int     new_size;
 
     if (msg_verbose > 1)
        msg_info("%s: %s", myname, inet_ntoa(*addr));
 
-    if (list->used >= list->size)
-       list->size *= 2;
-    list->addrs = (struct in_addr *)
-       myrealloc((char *) list->addrs,
-                 sizeof(*list->addrs) * list->size);
+    if (list->used >= list->size) {
+       new_size = list->size * 2;
+       list->addrs = (struct in_addr *)
+           myrealloc((char *) list->addrs, sizeof(*list->addrs) * new_size);
+       list->size = new_size;
+    }
     list->addrs[list->used++] = *addr;
 }
 
index 1d117fe02098e8ab1dd61cf0dd2ea314d2caf756..774e12d10ce95994715c79c1c556e814b843d4cd 100644 (file)
@@ -86,8 +86,9 @@ INTV   *intv_alloc(int len)
      * Initialize.
      */
     intvp = (INTV *) mymalloc(sizeof(*intvp));
+    intvp->len = 0;
+    intvp->intv = (int *) mymalloc(len * sizeof(intvp->intv[0]));
     intvp->len = len;
-    intvp->intv = (int *) mymalloc(intvp->len * sizeof(intvp->intv[0]));
     intvp->intc = 0;
     return (intvp);
 }
@@ -97,6 +98,7 @@ INTV   *intv_alloc(int len)
 void    intv_add(INTV *intvp, int count,...)
 {
     va_list ap;
+    int     new_len;
 
     /*
      * Make sure that always intvp->intc < intvp->len.
@@ -104,9 +106,10 @@ void    intv_add(INTV *intvp, int count,...)
     va_start(ap, count);
     while (count-- > 0) {
        if (intvp->intc >= intvp->len) {
-           intvp->len *= 2;
+           new_len = intvp->len * 2;
            intvp->intv = (int *) myrealloc((char *) intvp->intv,
-                                            intvp->len * sizeof(int));
+                                           new_len * sizeof(int));
+           intvp->len = new_len;
        }
        intvp->intv[intvp->intc++] = va_arg(ap, int);
     }
index fa3df03bdd824b3934b3449186976485024ebd5e..ed03d2ad0af7e55870974671271531d56002ec70 100644 (file)
 char   *mvect_alloc(MVECT *vect, int elsize, int nelm,
                void (*init_fn) (char *, int), void (*wipe_fn) (char *, int))
 {
-    vect->nelm = nelm;
-    vect->elsize = elsize;
     vect->init_fn = init_fn;
     vect->wipe_fn = wipe_fn;
-    vect->ptr = mymalloc(vect->elsize * vect->nelm);
+    vect->nelm = 0;
+    vect->ptr = mymalloc(elsize * nelm);
+    vect->nelm = nelm;
+    vect->elsize = elsize;
     if (vect->init_fn)
        vect->init_fn(vect->ptr, vect->nelm);
     return (vect->ptr);
@@ -86,12 +87,14 @@ char   *mvect_realloc(MVECT *vect, int nelm)
 {
     int     old_len = vect->nelm;
     int     incr = nelm - old_len;
+    int     new_nelm;
 
     if (incr > 0) {
        if (incr < old_len)
            incr = old_len;
-       vect->nelm += incr;
-       vect->ptr = myrealloc(vect->ptr, vect->elsize * vect->nelm);
+       new_nelm = vect->nelm + incr;
+       vect->ptr = myrealloc(vect->ptr, vect->elsize * new_nelm);
+       vect->nelm = new_nelm;
        if (vect->init_fn)
            vect->init_fn(vect->ptr + old_len * vect->elsize, incr);
     }
index ece60c0b381731deb6ca75b29615b211c5bf37d5..cf32cc6e91edc52a0aa94a81bf67e40d7d4c81fa 100644 (file)
@@ -13,8 +13,9 @@
 /* .in -4
 /*     } NAME_CODE;
 /*
-/*     int     name_code(table, name)
+/*     int     name_code(table, flags, name)
 /*     NAME_CODE *table;
+/*     int     flags;
 /*     const char *name;
 /*
 /*     const char *str_name_code(table, code)
 /*     corresponds to "name not found".
 /*
 /*     name_code() looks up the code that corresponds with the name.
-/*     The lookup is case insensitive.
+/*     The lookup is case insensitive. The flags argument specifies
+/*     zero or more of the following:
+/* .IP NAME_CODE_FLAG_STRICT_CASE
+/*     String lookups are case sensitive.
+/* .PP
+/*     For convenience the constant NAME_CODE_FLAG_NONE requests
+/*     no special processing.
 /*
 /*     str_name_code() translates a number to its equivalend string.
 /* DIAGNOSTICS
 
 /* name_code - look up code by name */
 
-int     name_code(NAME_CODE *table, const char *name)
+int     name_code(NAME_CODE *table, int flags, const char *name)
 {
     NAME_CODE *np;
+    int     (*lookup) (const char *, const char *);
+
+    if (flags & NAME_CODE_FLAG_STRICT_CASE)
+       lookup = strcmp;
+    else
+       lookup = strcasecmp;
 
     for (np = table; np->name; np++)
-       if (strcasecmp(name, np->name) == 0)
+       if (lookup(name, np->name) == 0)
            break;
     return (np->code);
 }
index 6722eee6b66d56c4f4807edd957dc2789da812e9..dd251b7aac04dd25a72be35d484d06c9c06c05e3 100644 (file)
@@ -19,7 +19,10 @@ typedef struct {
     int     code;
 } NAME_CODE;
 
-extern int name_code(NAME_CODE *, const char *);
+#define NAME_CODE_FLAG_NONE            0
+#define NAME_CODE_FLAG_STRICT_CASE     (1<<0)
+
+extern int name_code(NAME_CODE *, int, const char *);
 extern const char *str_name_code(NAME_CODE *, int);
 
 /* LICENSE
index 43ffae1e266f3dcdd913b2cf23e25ae86b6016bf..ff926dd813aed762e4f6e533f10f82b8adfdeabb 100644 (file)
 static void vstring_extend(VBUF *bp, int incr)
 {
     unsigned used = bp->ptr - bp->data;
+    int     new_len;
 
     /*
      * Note: vp->vbuf.len is the current buffer size (both on entry and on
@@ -261,8 +262,9 @@ static void vstring_extend(VBUF *bp, int incr)
      * strings we might want to abandon the length doubling strategy, and go
      * to fixed increments.
      */
-    bp->len += (bp->len > incr ? bp->len : incr);
-    bp->data = (unsigned char *) myrealloc((char *) bp->data, bp->len);
+    new_len = bp->len + (bp->len > incr ? bp->len : incr);
+    bp->data = (unsigned char *) myrealloc((char *) bp->data, new_len);
+    bp->len = new_len;
     bp->ptr = bp->data + used;
     bp->cnt = bp->len - used;
 }
@@ -305,6 +307,7 @@ VSTRING *vstring_alloc(int len)
        msg_panic("vstring_alloc: bad length %d", len);
     vp = (VSTRING *) mymalloc(sizeof(*vp));
     vp->vbuf.flags = 0;
+    vp->vbuf.len = 0;
     vp->vbuf.data = (unsigned char *) mymalloc(len);
     vp->vbuf.len = len;
     VSTRING_RESET(vp);