From: Wietse Venema Date: Wed, 21 Nov 2001 05:00:00 +0000 (-0500) Subject: snapshot-20011121 X-Git-Tag: v1.1.0~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31b984ac5b20d324b997ace2411fa54ef378128c;p=thirdparty%2Fpostfix.git snapshot-20011121 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 85da31269..8dee622e0 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5576,6 +5576,44 @@ Apologies for any names omitted. Bugfix: missing terminator in new attribute-based function call caused signal 11. File: src/cleanup/cleanup.c. + Lame workaround for ESTALE errors with mail delivery over + NFS. Additional bandages were added to the local delivery + agent. However, Wietse maintains that Postfix offers no + guarantee for reliable delivery over NFS. + + Feature: put "warn_if_reject" before an smtpd restriction, + and that restriction logs warnings without rejecting mail. + This makes it easier to test configurations "live" without + having to lose mail. File: smtpd/smtpd_check.c. + +20011107 + + Workaround: in order to get mail past PIX firewall bugs, + the Postfix SMTP client now blocks until the socket send + buffer is empty before sending the final ".". Files: + util/sock_empty_wait.c, smtp/smtp_proto.c. Changed into + sleep(10) on 20011119. Sleep suggested by Hobbit. + +20011108 + + Feature: added string-null encoding for internal protocols. + Files: util/attr_print0.c, util/attr_scan0.c. + + Feature: configurable parent domain matching for domain + and hostname/address match lists: either .domain or the + domain name itself. Files: util/match_ops.c util/match_list.c + + Feature: added pretend-to-be-behind-PIX mode to the smtp-sink + test program, in order to stress test some PIX bug workaround + code. + +20011109 + + Workaround: Linux and Solaris systems have no reasonable + way to block until a socket drains. On these systems Postfix + simply waits for 10 seconds, in order to work around PIX + "." bugs. File: util/sock_empty_wait.c. + 20011114 Bugfix: reset the smtpd command transaction log between @@ -5583,20 +5621,49 @@ Apologies for any names omitted. 20011115 + Feature: mailbox_command_maps no longer requires that every + user has an entry. If the user does not have a command + entry, the local delivery agent tries the other delivery + methods (mailbox_command, home_mailbox). File: local/mailbox.c. + Bugfix: reset the smtpd command transaction log between non-deliveries. File: smtpd/smtpd.c. 20011116 - Bugfix: consolidated all the command transaction log - resets and eliminated one other case (Victor Duchovny, - Morgan Stanley). File: smtpd/smtpd.c. + Bugfix: consolidated all the command transaction log resets + and eliminated one missing reset (Victor Duchovny, Morgan + Stanley). File: smtpd/smtpd.c. + +20011118 + + Cleanup: replaced unnecessary match_list wrapper code by + macros. Files: global/{string,domain,namadr}_list.[hc]. + +20011119 + + Feature: configurable parent domain matching strategy for + transport map lookups. File: trivial-rewrite/transport.c. + + New parent_domain_matches_subdomains parameter. This lists + all the Postfix features where a domain name matches itself + and all its subdomains (instead of requiring ".domain.name" + for subdomain matches). Planning for future backwards + compatibility :-) File: global/match_parent_style.c. + + Workaround: simplified the PIX "." bug to always + sleep for 10 seconds. File: smtp/smtp_proto.c. 20011120 Workaround: disable attribute string length restriction so that trivial-rewrite does not refuse to rewrite broken mail - headers. File: util/attr_scan.c. + headers. Files: util/attr_scan*.c. + +20011121 + + Bugfix: missing long integer support in the new IPC protocols. + Files: util/attr_scan*.c, util/attr_print*.c. Open problems: @@ -5609,6 +5676,8 @@ Open problems: Medium: smtpd access maps don't understand the recipient delimiter setting. + Low: default domain for appending to unqualified recipients. + Low: The $process_id_directory setting is not used anywhere in Postfix. Problem reported by Michael Smith, texas.net. This should be documented, or better, the code should warn diff --git a/postfix/INSTALL b/postfix/INSTALL index 3d6748521..8c5419b22 100644 --- a/postfix/INSTALL +++ b/postfix/INSTALL @@ -213,8 +213,8 @@ In order to install or upgrade Postfix: - Run the INSTALL.sh script as the super-user: - # make install (interactive version, first time install) - # make install LF> at the end of mail to be lost. The workaround +has no effect for other mail deliveries. + +mailbox_command_maps allows you to configure the external delivery +command per user (local delivery agent only). This feature has +precedence over mailbox_command and home_mailbox settings. Major changes with snapshot-20011103 ==================================== diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index 43220c108..cc39b935b 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -152,9 +152,9 @@ mail_owner = postfix # Specify "mynetworks_style = host" when Postfix should "trust" # only the local machine. # -# mynetworks_style = class -# mynetworks_style = subnet -# mynetworks_style = host +#mynetworks_style = class +#mynetworks_style = subnet +#mynetworks_style = host # Alternatively, you can specify the mynetworks list by hand, in # which case Postfix ignores the mynetworks_style setting. @@ -217,10 +217,10 @@ mail_owner = postfix # # If you're connected via UUCP, see also the default_transport parameter. # -# relayhost = $mydomain -# relayhost = gateway.my.domain -# relayhost = uucphost -# relayhost = [an.ip.add.ress] +#relayhost = $mydomain +#relayhost = gateway.my.domain +#relayhost = uucphost +#relayhost = [an.ip.add.ress] # REJECTING UNKNOWN LOCAL USERS # @@ -319,7 +319,7 @@ mail_owner = postfix # Basically, the software tries user+foo and .forward+foo before # trying user and .forward. # -# recipient_delimiter = + +#recipient_delimiter = + # DELIVERY TO MAILBOX # @@ -335,8 +335,8 @@ mail_owner = postfix # UNIX-style mailboxes are kept. The default setting depends on the # system type. # -# mail_spool_directory = /var/mail -# mail_spool_directory = /var/spool/mail +#mail_spool_directory = /var/mail +#mail_spool_directory = /var/spool/mail # The mailbox_command parameter specifies the optional external # command to use instead of mailbox delivery. The command is run as @@ -399,9 +399,9 @@ mail_owner = postfix # # luser_relay works only for the default Postfix local delivery agent. # -# luser_relay = $user@other.host -# luser_relay = $local@other.host -# luser_relay = admin+$local +#luser_relay = $user@other.host +#luser_relay = $local@other.host +#luser_relay = admin+$local # JUNK MAIL CONTROLS # @@ -481,8 +481,8 @@ debug_peer_level = 2 # increase the verbose logging level by the amount specified in the # debug_peer_level parameter. # -# debug_peer_list = 127.0.0.1 -# debug_peer_list = some.domain +#debug_peer_list = 127.0.0.1 +#debug_peer_list = some.domain # The debugger_command specifies the external command that is executed # when a Postfix daemon program is run with the -D option. diff --git a/postfix/conf/sample-aliases.cf b/postfix/conf/sample-aliases.cf index 80dd4a6e8..6ebebb66d 100644 --- a/postfix/conf/sample-aliases.cf +++ b/postfix/conf/sample-aliases.cf @@ -13,8 +13,8 @@ # specify multiple tables, not necessarily all under control by # Postfix. # -# alias_database = dbm:/etc/aliases -# alias_database = dbm:/etc/mail/aliases +#alias_database = dbm:/etc/aliases +#alias_database = dbm:/etc/mail/aliases alias_database = hash:/etc/aliases # The alias_maps parameter specifies the list of alias databases used @@ -30,6 +30,6 @@ alias_database = hash:/etc/aliases # It will take a minute or so before changes become visible. Use # "postfix reload" to eliminate the delay. # -# alias_maps = dbm:/etc/aliases, nis:mail.aliases -# alias_maps = hash:/etc/aliases +#alias_maps = dbm:/etc/aliases, nis:mail.aliases +#alias_maps = hash:/etc/aliases alias_maps = hash:/etc/aliases diff --git a/postfix/conf/sample-auth.cf b/postfix/conf/sample-auth.cf index be003437d..00920bde7 100644 --- a/postfix/conf/sample-auth.cf +++ b/postfix/conf/sample-auth.cf @@ -70,7 +70,7 @@ smtpd_sasl_security_options = noanonymous # By default, the local authentication realm name is the name of the # machine. # -# smtpd_sasl_local_domain = $mydomain +#smtpd_sasl_local_domain = $mydomain smtpd_sasl_local_domain = $myhostname # SMTP CLIENT CONTROLS diff --git a/postfix/conf/sample-canonical.cf b/postfix/conf/sample-canonical.cf index 1e3b0a57c..474976b70 100644 --- a/postfix/conf/sample-canonical.cf +++ b/postfix/conf/sample-canonical.cf @@ -17,10 +17,10 @@ # will become visible after a minute or so. Use "postfix reload" # to eliminate the delay. # -# canonical_maps = dbm:/etc/postfix/canonical -# canonical_maps = hash:/etc/postfix/canonical -# canonical_maps = hash:/etc/postfix/canonical, nis:canonical -# canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical +#canonical_maps = dbm:/etc/postfix/canonical +#canonical_maps = hash:/etc/postfix/canonical +#canonical_maps = hash:/etc/postfix/canonical, nis:canonical +#canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical canonical_maps = # The recipient_canonical_maps parameter specifies optional address @@ -30,7 +30,7 @@ canonical_maps = # # $recipient_canonical_maps is used before $canonical_maps lookups. # -# recipient_canonical_maps = hash:/etc/postfix/recipient_canonical +#recipient_canonical_maps = hash:/etc/postfix/recipient_canonical recipient_canonical_maps = # The sender_canonical_maps parameter specifies optional address @@ -44,5 +44,5 @@ recipient_canonical_maps = # # $sender_canonical_maps is used before $canonical_maps lookups. # -# sender_canonical_maps = hash:/etc/postfix/sender_canonical +#sender_canonical_maps = hash:/etc/postfix/sender_canonical sender_canonical_maps = diff --git a/postfix/conf/sample-debug.cf b/postfix/conf/sample-debug.cf index c8a8e97a6..5f850ddc7 100644 --- a/postfix/conf/sample-debug.cf +++ b/postfix/conf/sample-debug.cf @@ -16,8 +16,8 @@ debug_peer_level = 2 # increase the verbose logging level by the amount specified in the # debug_peer_level parameter. # -# debug_peer_list = 127.0.0.1 -# debug_peer_list = some.domain +#debug_peer_list = 127.0.0.1 +#debug_peer_list = some.domain debug_peer_list = # The debugger_command specifies the external command that is executed diff --git a/postfix/conf/sample-lmtp.cf b/postfix/conf/sample-lmtp.cf index 64419a35b..9e2699ccc 100644 --- a/postfix/conf/sample-lmtp.cf +++ b/postfix/conf/sample-lmtp.cf @@ -68,7 +68,7 @@ lmtp_destination_recipient_limit = $default_destination_recipient_limit # Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). # The default time unit is s (seconds). # -# lmtp_connect_timeout = 30s +#lmtp_connect_timeout = 30s lmtp_connect_timeout = 0s # The lmtp_lhlo_timeout parameter specifies the LMTP client timeout diff --git a/postfix/conf/sample-local.cf b/postfix/conf/sample-local.cf index 69f87dda1..a64e531f9 100644 --- a/postfix/conf/sample-local.cf +++ b/postfix/conf/sample-local.cf @@ -6,6 +6,10 @@ # # See the sample-aliases.cf file for parameters that are specific to # alias database lookup. +# +# Mailbox delivery is controlled by a series of parameters. The +# precedence, from highest to lowest priority: mailbox_transport, +# mailbox_command_maps, mailbox_command, home_mailbox. # The biff parameter specifies whether or not to contact the biff # server. This server sends "new mail" notifications to users who @@ -15,7 +19,7 @@ # with lots of interactive users, this "protocol" can be a real # performance pig. Specify "biff = no" to disable. # -# biff = no +#biff = no biff = yes # The require_home_directory parameter controls whether a local @@ -84,14 +88,14 @@ forward_path = $home/.forward$recipient_delimiter$extension,$home/.forward # external commands. The default is to disallow delivery to "|command" # in :include: files. # -# allow_mail_to_commands = alias,forward,include +#allow_mail_to_commands = alias,forward,include allow_mail_to_commands = alias,forward # The allow_mail_to_files parameter restricts mail delivery to external # file. The default is to disallow delivery to /file/name in :include: # files. # -# allow_mail_to_files = alias,forward,include +#allow_mail_to_files = alias,forward,include allow_mail_to_files = alias,forward # The default_privs parameter specifies the default rights used by @@ -110,8 +114,8 @@ default_privs = nobody # mailbox file is /var/spool/mail/user or /var/mail/user. Specify # "Maildir/" for qmail-style delivery (the / is required). # -# home_mailbox = Mailbox -# home_mailbox = Maildir/ +#home_mailbox = Mailbox +#home_mailbox = Maildir/ home_mailbox = # The luser_relay parameter specifies an optional destination address @@ -127,16 +131,16 @@ home_mailbox = # # luser_relay works only for the default Postfix local delivery agent. # -# luser_relay = $user@other.host -# luser_relay = $local@other.host -# luser_relay = admin+$local +#luser_relay = $user@other.host +#luser_relay = $local@other.host +#luser_relay = admin+$local # The mail_spool_directory parameter specifies the directory where # UNIX-style mailboxes are kept. The default setting depends on the # system type. # -# mail_spool_directory = /var/mail -# mail_spool_directory = /var/spool/mail +#mail_spool_directory = /var/mail +#mail_spool_directory = /var/spool/mail # The mailbox_command parameter specifies the optional external # command to use instead of mailbox delivery. The command is run @@ -157,16 +161,17 @@ home_mailbox = # IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN # ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER. # -# mailbox_command = /some/where/procmail -# mailbox_command = /some/where/procmail -a "$EXTENSION" +#mailbox_command = /some/where/procmail +#mailbox_command = /some/where/procmail -a "$EXTENSION" mailbox_command = # The mailbox_command_maps allows you to specify a per-user mailbox # command. The maps are keyed by username (not including the domain). -# Specify one or more maps. If this feature is used then every user -# must have a matching entry. +# Specify one or more maps. If a user is not found in the maps then +# lower precedence delivery mechanisms take effect. See the top of +# this file for the precedences of mailbox delivery mechanisms. # -# mailbox_command_maps = hash:/etc/postfix/mailbox_commands +#mailbox_command_maps = hash:/etc/postfix/mailbox_commands # The mailbox_transport specifies the optional transport in master.cf # to use after processing aliases and .forward files. This parameter @@ -178,8 +183,8 @@ mailbox_command = # :nexthop part is optional. For more details see the sample transport # configuration file. # -# mailbox_transport = lmtp:unix:/file/name -# mailbox_transport = cyrus +#mailbox_transport = lmtp:unix:/file/name +#mailbox_transport = cyrus mailbox_transport = # The fallback_transport specifies the optional transport in master.cf @@ -191,8 +196,8 @@ mailbox_transport = # :nexthop part is optional. For more details see the sample transport # configuration file. # -# fallback_transport = lmtp:unix:/file/name -# fallback_transport = cyrus +#fallback_transport = lmtp:unix:/file/name +#fallback_transport = cyrus fallback_transport = # @@ -236,5 +241,5 @@ local_destination_recipient_limit = 1 # and command. Turning off the Delivered-To: header when forwarding # mail is not recommended. # -# prepend_delivered_header = command, file, forward -# prepend_delivered_header = forward +#prepend_delivered_header = command, file, forward +#prepend_delivered_header = forward diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf index 4b2d7d502..f75632166 100644 --- a/postfix/conf/sample-misc.cf +++ b/postfix/conf/sample-misc.cf @@ -24,8 +24,8 @@ daemon_timeout = 18000s # systems the default type is either `dbm' or `hash'. The default is # determined when the Postfix system is built. # -# default_database_type = hash -# default_database_type = dbm +#default_database_type = hash +#default_database_type = dbm # The default_transport parameter specifies the default message # delivery transport to use when no transport is explicitly given in @@ -36,7 +36,7 @@ daemon_timeout = 18000s # transport or nexthop are optional. For more details see the sample # transports file. # -# default_transport = uucp:relayhostname +#default_transport = uucp:relayhostname default_transport = smtp # The double_bounce_sender parameter specifies the sender address @@ -98,7 +98,7 @@ hopcount_limit = 50 # # Specify a list of names separated by whitespace or comma. # -# import_environment = MAIL_CONFIG TZ XAUTHORITY DISPLAY HOME PURIFYOPTIONS +#import_environment = MAIL_CONFIG TZ XAUTHORITY DISPLAY HOME PURIFYOPTIONS import_environment = MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY # The inet_interfaces parameter specifies the network interface @@ -127,7 +127,7 @@ ipc_idle = 100s # Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). # The default time unit is s (seconds). # -#ipc_timeout = 3600s +ipc_timeout = 3600s # The mail_name parameter specifies the mail system name that is used # in Received: headers, in the SMTP greeting banner, and in bounced @@ -187,8 +187,8 @@ max_use = 100 # a name matches a lookup key. Continue long lines by starting the # next line with whitespace. # -# mydestination = $myhostname, localhost.$mydomain $mydomain -# mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain +#mydestination = $myhostname, localhost.$mydomain $mydomain +#mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain mydestination = $myhostname, localhost.$mydomain # The mydomain parameter specifies the local internet domain name. @@ -212,7 +212,7 @@ mydestination = $myhostname, localhost.$mydomain # a domain-wide alias database that aliases each user to # user@that.users.mailhost. # -# myorigin = $mydomain +#myorigin = $mydomain myorigin = $myhostname # The mynetworks parameter specifies the list of "trusted" SMTP @@ -237,9 +237,9 @@ myorigin = $myhostname # Specify "mynetworks_style = host" when Postfix should "trust" # only the local machine. # -# mynetworks_style = class -# mynetworks_style = subnet -# mynetworks_style = host +#mynetworks_style = class +#mynetworks_style = subnet +#mynetworks_style = host # Alternatively, you can specify the mynetworks list by hand, in # which case Postfix ignores the mynetworks_style setting. @@ -259,8 +259,8 @@ myorigin = $myhostname # policy (anti-UCE violations) and protocol error (broken mailers) # reports. # -# notify_classes = bounce,delay,policy,protocol,resource,software -# notify_classes = 2bounce,resource,software +#notify_classes = bounce,delay,policy,protocol,resource,software +#notify_classes = 2bounce,resource,software notify_classes = resource,software # The following parameters specify who gets postmaster notices if @@ -272,6 +272,16 @@ bounce_notice_recipient = postmaster delay_notice_recipient = postmaster error_notice_recipient = postmaster +# The parent_domain_matches_subdomains parameter specifies what +# Postfix features use "domain.name matches sub.domain.name" style +# pattern matching instead of requiring ".domain.name". This is +# planned backwards compatibility: eventually, all Postfix features +# are expected to require ".domain.name" style patterns. +# +parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains, + mynetworks,permit_mx_backup_networks,qmqpd_authorized_clients, + relay_domains,smtpd_access_maps + # The process_id_directory specifies a lock file directory relative # to the Postfix queue directory. This facility is used by the master # daemon to lock out other master daemon instances. @@ -297,7 +307,7 @@ queue_directory = /var/spool/postfix # Basically, the software tries user+foo and .forward+foo before # trying user and .forward. # -# recipient_delimiter = + +#recipient_delimiter = + recipient_delimiter = # The propagate_unmatched_extensions parameter specifies what lookup @@ -332,10 +342,10 @@ recipient_delimiter = # # If you're connected via UUCP, see also the default_transport parameter. # -# relayhost = $mydomain -# relayhost = gateway.my.domain -# relayhost = uucphost -# relayhost = [an.ip.add.ress] +#relayhost = $mydomain +#relayhost = gateway.my.domain +#relayhost = uucphost +#relayhost = [an.ip.add.ress] relayhost = # The relocated_maps parameter specifies optional tables with contact @@ -347,7 +357,7 @@ relayhost = # Specify the types and names of databases to use. After change, # run "postmap /etc/postfix/relocated", then "postfix reload". # -# relocated_maps = hash:/etc/postfix/relocated +#relocated_maps = hash:/etc/postfix/relocated relocated_maps = # The syslog_facility parameter controls where Postfix logging is @@ -390,4 +400,4 @@ trigger_timeout = 10s # Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). # The default time unit is h (hours). # -# delay_warning_time = 0h +#delay_warning_time = 0h diff --git a/postfix/conf/sample-relocated.cf b/postfix/conf/sample-relocated.cf index 1c83ca538..611134b0a 100644 --- a/postfix/conf/sample-relocated.cf +++ b/postfix/conf/sample-relocated.cf @@ -14,8 +14,8 @@ # build the necessary DBM or DB file after change, then "postfix # reload" to make the changes visible. # -# relocated_maps = dbm:/etc/postfix/relocated -# relocated_maps = hash:/etc/postfix/relocated -# relocated_maps = hash:/etc/postfix/relocated, nis:virtual -# relocated_maps = hash:/etc/postfix/relocated, netinfo:/relocated +#relocated_maps = dbm:/etc/postfix/relocated +#relocated_maps = hash:/etc/postfix/relocated +#relocated_maps = hash:/etc/postfix/relocated, nis:virtual +#relocated_maps = hash:/etc/postfix/relocated, netinfo:/relocated relocated_maps = diff --git a/postfix/conf/sample-rewrite.cf b/postfix/conf/sample-rewrite.cf index deed2785f..c4d5e1ea1 100644 --- a/postfix/conf/sample-rewrite.cf +++ b/postfix/conf/sample-rewrite.cf @@ -7,7 +7,7 @@ # The allow_percent_hack parameter controls the rewriting of the form # "user%domain" to "user@domain". This is enabled by default. # -# allow_percent_hack = no +#allow_percent_hack = no allow_percent_hack = yes # The append_at_myorigin controls the rewriting of the form "user" to @@ -18,7 +18,7 @@ append_at_myorigin = yes # The append_dot_mydomain controls the rewriting of the form # "user@host" to "user@host.$mydomain". This is enabled by default. # -# append_dot_mydomain = no +#append_dot_mydomain = no append_dot_mydomain = yes # The empty_address_recipient specifies the destination for mail from @@ -45,7 +45,7 @@ masquerade_classes = envelope_sender, header_sender, header_recipient # # By default, address masquerading is disabled. # -# masquerade_domains = $mydomain +#masquerade_domains = $mydomain masquerade_domains = # The masquerade_exceptions parameter gives an optional list of user @@ -61,5 +61,5 @@ masquerade_exceptions = # "site!user" to "user@site". This is necessary if your machine is # connected to UUCP networks. It is enabled by default. # -# swap_bangpath = no +#swap_bangpath = no swap_bangpath = yes diff --git a/postfix/conf/sample-smtp.cf b/postfix/conf/sample-smtp.cf index b1ffef725..888c49449 100644 --- a/postfix/conf/sample-smtp.cf +++ b/postfix/conf/sample-smtp.cf @@ -138,7 +138,7 @@ smtp_destination_recipient_limit = $default_destination_recipient_limit # Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). # The default time unit is s (seconds). # -# smtp_connect_timeout = 30s +#smtp_connect_timeout = 30s smtp_connect_timeout = 0s # The smtp_helo_timeout parameter specifies the SMTP client timeout diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index ed084a942..b59488679 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -18,18 +18,17 @@ # status code in the SMTP greeting banner. Some people like to see # the mail version advertised. By default, Postfix shows no version. # -# You MUST specify the $myhostname at the start of the text. When -# the SMTP client sees its own hostname at the start of an SMTP -# greeting banner it will report a mailer loop. That's better than -# having a machine meltdown. +# You MUST specify the $myhostname at the start of the text. # -# smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) +#smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) smtpd_banner = $myhostname ESMTP $mail_name # The smtpd_etrn_restrictions parameter restricts what clients are -# allowed to issue the ETRN command. The present Postfix ETRN differs -# from other ETRN implementations in that it flushes mail for all -# destinations. This will change in the future. +# allowed to issue the ETRN command. +# +# The Postfix ETRN command is available only for destinations that +# that are eligible for the Postfix "fast flush" service. See the +# sample-flush.cf file for details. # # The default is to allow ETRN from any host. The following restrictions # are available: @@ -45,6 +44,7 @@ smtpd_banner = $myhostname ESMTP $mail_name # is listed under $maps_rbl_domains. # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. +# warn_if_reject: next restriction logs a warning instead of rejecting. smtpd_etrn_restrictions = # The smtpd_recipient_limit parameter restricts the number of recipients @@ -123,9 +123,9 @@ smtpd_hard_error_limit = 100 # Specify "mynetworks_style = host" when Postfix should "trust" # only the local machine. # -# mynetworks_style = class +#mynetworks_style = class mynetworks_style = subnet -# mynetworks_style = host +#mynetworks_style = host # Alternatively, you can specify the mynetworks list by hand, in # which case Postfix ignores the mynetworks_style setting. @@ -158,6 +158,7 @@ mynetworks_style = subnet # reject_maps_rbl: reject if the client is listed under $maps_rbl_domains. # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. +# warn_if_reject: next restriction logs a warning instead of rejecting. # # Restrictions are applied in the order as specified; the first # restriction that matches wins. @@ -173,7 +174,7 @@ smtpd_client_restrictions = # that SMTP clients must introduce themselves at the beginning of an # SMTP session. # -# smtpd_helo_required = yes +#smtpd_helo_required = yes smtpd_helo_required = no # The smtpd_helo_restrictions parameter specifies optional restrictions @@ -195,6 +196,7 @@ smtpd_helo_required = no # check_client_access maptype:mapname: see smtpd_client_restrictions. # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. +# warn_if_reject: next restriction logs a warning instead of rejecting. # # Restrictions are applied in the order as specified; the first # restriction that matches wins. @@ -202,8 +204,8 @@ smtpd_helo_required = no # Specify a list of restrictions, separated by commas and/or whitespace. # Continue long lines by starting the next line with whitespace. # -# smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname -# smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname +#smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname +#smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname smtpd_helo_restrictions = # The smtpd_sender_restrictions parameter specifies optional restrictions @@ -228,6 +230,7 @@ smtpd_helo_restrictions = # reject_non_fqdn_sender: reject sender address that is not in FQDN form # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. +# warn_if_reject: next restriction logs a warning instead of rejecting. # # Restrictions are applied in the order as specified; the first # restriction that matches wins. @@ -235,8 +238,8 @@ smtpd_helo_restrictions = # Specify a list of restrictions, separated by commas and/or whitespace. # Continue long lines by starting the next line with whitespace. # -# smtpd_sender_restrictions = reject_unknown_sender_domain -# smtpd_sender_restrictions = reject_unknown_sender_domain, hash:/etc/postfix/access +#smtpd_sender_restrictions = reject_unknown_sender_domain +#smtpd_sender_restrictions = reject_unknown_sender_domain, hash:/etc/postfix/access smtpd_sender_restrictions = # The smtpd_recipient_restrictions parameter specifies restrictions on @@ -298,6 +301,7 @@ smtpd_sender_restrictions = # reject_non_fqdn_recipient: reject recipient address that is not in FQDN form # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. +# warn_if_reject: next restriction logs a warning instead of rejecting. # # Restrictions are applied in the order as specified; the first # restriction that matches wins. diff --git a/postfix/conf/sample-transport.cf b/postfix/conf/sample-transport.cf index 8ecd2b56b..79d6f87d0 100644 --- a/postfix/conf/sample-transport.cf +++ b/postfix/conf/sample-transport.cf @@ -11,8 +11,8 @@ # to use. If you use this feature, run "postmap /etc/postfix/transport" # after change, then "postfix reload". # -# transport_maps = dbm:/etc/postfix/transport -# transport_maps = hash:/etc/postfix/transport -# transport_maps = hash:/etc/postfix/transport, nis:transport -# transport_maps = hash:/etc/postfix/transport, netinfo:/transport +#transport_maps = dbm:/etc/postfix/transport +#transport_maps = hash:/etc/postfix/transport +#transport_maps = hash:/etc/postfix/transport, nis:transport +#transport_maps = hash:/etc/postfix/transport, netinfo:/transport transport_maps = diff --git a/postfix/conf/sample-virtual.cf b/postfix/conf/sample-virtual.cf index d660d6b79..f11ccc317 100644 --- a/postfix/conf/sample-virtual.cf +++ b/postfix/conf/sample-virtual.cf @@ -16,8 +16,8 @@ # It may take a minute or so before the change becomes visible. # Use "postfix reload" to eliminate the delay. # -# virtual_maps = dbm:/etc/postfix/virtual -# virtual_maps = hash:/etc/postfix/virtual -# virtual_maps = hash:/etc/postfix/virtual, nis:virtual -# virtual_maps = hash:/etc/postfix/virtual, netinfo:/virtual +#virtual_maps = dbm:/etc/postfix/virtual +#virtual_maps = hash:/etc/postfix/virtual +#virtual_maps = hash:/etc/postfix/virtual, nis:virtual +#virtual_maps = hash:/etc/postfix/virtual, netinfo:/virtual virtual_maps = diff --git a/postfix/html/flush.8.html b/postfix/html/flush.8.html index dbd2fb0f0..19b8ab68c 100644 --- a/postfix/html/flush.8.html +++ b/postfix/html/flush.8.html @@ -136,6 +136,11 @@ FLUSH(8) FLUSH(8) updated in this amount of time (default time unit: days). + parent_domain_matches_subdomains (versions >= 20011119) + List of Postfix features that use domain.name pat- + terns to match sub.domain.name (as opposed to + requiring .domain.name patterns). + SEE ALSO smtpd(8) Postfix SMTP server qmgr(8) Postfix queue manager diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 511567d6f..5864c13cb 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -210,6 +210,11 @@ SMTPD(8) SMTPD(8) delays. UCE control restrictions + parent_domain_matches_subdomains (versions >= 20011119) + List of Postfix features that use domain.name pat- + terns to match sub.domain.name (as opposed to + requiring .domain.name patterns). + smtpd_client_restrictions Restrict what clients may connect to this mail sys- tem. diff --git a/postfix/html/transport.5.html b/postfix/html/transport.5.html index 10cda5432..14a5367f3 100644 --- a/postfix/html/transport.5.html +++ b/postfix/html/transport.5.html @@ -143,6 +143,11 @@ TRANSPORT(5) TRANSPORT(5) details and for default values. Use the postfix reload command after a configuration change. + parent_domain_matches_subdomains (versions >= 20011119) + List of Postfix features that use domain.name pat- + terns to match sub.domain.name (as opposed to + requiring .domain.name patterns). + transport_maps List of transport lookup tables. diff --git a/postfix/html/trivial-rewrite.8.html b/postfix/html/trivial-rewrite.8.html index d926f0e60..f2bf17443 100644 --- a/postfix/html/trivial-rewrite.8.html +++ b/postfix/html/trivial-rewrite.8.html @@ -110,6 +110,11 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) Syntax is transport:nexthop; see transport(5) for details. The :nexthop part is optional. + parent_domain_matches_subdomains (versions >= 20011119) + List of Postfix features that use domain.name pat- + terns to match sub.domain.name (as opposed to + requiring .domain.name patterns). + relayhost The default host to send non-local mail to when no entry is matched in the transport(5) table. diff --git a/postfix/html/uce.html b/postfix/html/uce.html index f2cb60483..4b4eb37b4 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -237,6 +237,8 @@ rejected requests (default: 554).
reject +
warn_if_reject +
reject_unauth_pipelining
See generic restrictions. @@ -406,6 +408,8 @@ the response code for REJECT results (default: 554).
reject +
warn_if_reject +
reject_unauth_pipelining
See generic restrictions. @@ -570,6 +574,8 @@ response code to rejected requests (default: 504).
reject +
warn_if_reject +
reject_unauth_pipelining
See generic restrictions. @@ -839,6 +845,8 @@ response code to rejected requests (default: 504).
reject +
warn_if_reject +
reject_unauth_pipelining
See generic restrictions. @@ -937,6 +945,8 @@ the result code for rejected requests (default: 554).
reject +
warn_if_reject +
reject_unauth_pipelining
See generic restrictions. @@ -979,6 +989,17 @@ specifies the response code to rejected requests (default:

+ + +

warn_if_reject (Postfix versions 20011119 and later) +
Change the meaning of the next restriction, so that it logs +a warning instead of rejecting a request (look for logfile records +that contain "reject_warning"). This is useful for testing new +restrictions in a "live" environment without risking unnecessary +loss of mail. + +

+

reject_unauth_pipelining
Reject the request when diff --git a/postfix/html/virtual.8.html b/postfix/html/virtual.8.html index 3af78864a..a3f3571b5 100644 --- a/postfix/html/virtual.8.html +++ b/postfix/html/virtual.8.html @@ -73,9 +73,10 @@ VIRTUAL(8) VIRTUAL(8) tual_owner_maps or virtual_uid_maps. SECURITY - The virtual delivery agent is not security sensitive, provided - that the lookup tables with recipient information are adequately - protected. This program is not designed to run chrooted. + The virtual delivery agent is not security sensitive, pro- + vided that the lookup tables with recipient user/group ID + information are adequately protected. This program is not + designed to run chrooted. STANDARDS RFC 822 (ARPA Internet Text Messages) @@ -85,120 +86,120 @@ VIRTUAL(8) VIRTUAL(8) recipient is over disk quota. In all other cases, mail for an existing recipient is deferred and a warning is logged. - Problems and transactions are logged to syslogd(8). Cor- - rupted message files are marked so that the queue manager + Problems and transactions are logged to syslogd(8). Cor- + rupted message files are marked so that the queue manager can move them to the corrupt queue afterwards. - Depending on the setting of the notify_classes parameter, - the postmaster is notified of bounces and of other trou- + Depending on the setting of the notify_classes parameter, + the postmaster is notified of bounces and of other trou- ble. BUGS This delivery agent silently ignores address extensions. Postfix should have lookup tables that can return multiple - result attributes. In order to avoid the inconvenience of + result attributes. In order to avoid the inconvenience of maintaining three tables, use an LDAP or MYSQL database. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax - details and for default values. Use the postfix reload + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. Mailbox delivery virtual_mailbox_base - Specifies a path that is prepended to all mailbox - or maildir paths. This is a safety measure to - ensure that an out of control map in virtual_mail- - box_maps doesn't litter the filesystem with mail- - boxes. While it could be set to "/", this setting + Specifies a path that is prepended to all mailbox + or maildir paths. This is a safety measure to + ensure that an out of control map in virtual_mail- + box_maps doesn't litter the filesystem with mail- + boxes. While it could be set to "/", this setting isn't recommended. virtual_mailbox_maps (regexp maps disallowed) Recipients are looked up in these maps to determine - the path to their mailbox or maildir. If the - returned path ends in a slash ("/"), maildir-style - delivery is carried out, otherwise the path is + the path to their mailbox or maildir. If the + returned path ends in a slash ("/"), maildir-style + delivery is carried out, otherwise the path is assumed to specify a UNIX-style mailbox file. - Note that virtual_mailbox_base is unconditionally + Note that virtual_mailbox_base is unconditionally prepended to this path. virtual_minimum_uid - Specifies a minimum uid that will be accepted as a - return from a virtual_owner_maps or vir- - tual_uid_maps lookup. Returned values less than - this will be rejected, and the message will be + Specifies a minimum uid that will be accepted as a + return from a virtual_owner_maps or vir- + tual_uid_maps lookup. Returned values less than + this will be rejected, and the message will be deferred. virtual_uid_maps (regexp maps disallowed) Recipients are looked up in these maps to determine - the user ID to be used when writing to the target + the user ID to be used when writing to the target mailbox. virtual_gid_maps (regexp maps disallowed) Recipients are looked up in these maps to determine - the group ID to be used when writing to the target + the group ID to be used when writing to the target mailbox. Locking controls virtual_mailbox_lock - How to lock UNIX-style mailboxes: one or more of - flock, fcntl or dotlock. The dotlock method - requires that the recipient UID or GID has write + How to lock UNIX-style mailboxes: one or more of + flock, fcntl or dotlock. The dotlock method + requires that the recipient UID or GID has write access to the parent directory of the mailbox file. - This setting is ignored with maildir style deliv- + This setting is ignored with maildir style deliv- ery, because such deliveries are safe without explicit locks. - Use the command postconf -m to find out what lock- + Use the command postconf -l to find out what lock- ing methods are available on your system. deliver_lock_attempts - Limit the number of attempts to acquire an exclu- + Limit the number of attempts to acquire an exclu- sive lock on a UNIX-style mailbox file. deliver_lock_delay Time (default: seconds) between successive attempts - to acquire an exclusive lock on a UNIX-style mail- - box file. The actual delay is slightly randomized. + to acquire an exclusive lock on a UNIX-style mail- + box file. The actual delay is slightly randomized. stale_lock_time - Limit the time after which a stale lockfile is - removed (applicable to UNIX-style mailboxes only). + Limit the time after which a stale lockfile is + removed (applicable to UNIX-style mailboxes only). Resource controls virtual_destination_concurrency_limit Limit the number of parallel deliveries to the same domain via the virtual delivery agent. The default limit is taken from the default_destination_concur- - rency_limit parameter. The limit is enforced by + rency_limit parameter. The limit is enforced by the Postfix queue manager. virtual_destination_recipient_limit Limit the number of recipients per message delivery - via the virtual delivery agent. The default limit - is taken from the default_destination_recipi- - ent_limit parameter. The limit is enforced by the + via the virtual delivery agent. The default limit + is taken from the default_destination_recipi- + ent_limit parameter. The limit is enforced by the Postfix queue manager. virtual_mailbox_limit - The maximal size in bytes of a mailbox or maildir + The maximal size in bytes of a mailbox or maildir file. Set to zero to disable the limit. HISTORY - This agent was originally based on the Postfix local + This agent was originally based on the Postfix local delivery agent. Modifications mainly consisted of removing - code that either was not applicable or that was not safe - in this context: aliases, ~user/.forward files, delivery + code that either was not applicable or that was not safe + in this context: aliases, ~user/.forward files, delivery to "|command" or to /file/name. - The Delivered-To: header appears in the qmail system by + The Delivered-To: header appears in the qmail system by Daniel Bernstein. - The maildir structure appears in the qmail system by + The maildir structure appears in the qmail system by Daniel Bernstein. SEE ALSO @@ -207,7 +208,7 @@ VIRTUAL(8) VIRTUAL(8) qmgr(8) queue manager LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/makedefs b/postfix/makedefs index 083f99f4b..2c9a7f27e 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -230,7 +230,7 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543 RANLIB=echo SYSLIBS="-lresolv -lsocket -lnsl" ;; -Rhapsody.5*|Darwin.1.*) +Rhapsody.5*|Darwin.*) SYSTYPE=RHAPSODY5 # Use the native compiler by default : ${CC=cc} diff --git a/postfix/man/man5/transport.5 b/postfix/man/man5/transport.5 index 386d763f3..d45ec5ba4 100644 --- a/postfix/man/man5/transport.5 +++ b/postfix/man/man5/transport.5 @@ -150,6 +150,10 @@ The following \fBmain.cf\fR parameters are especially relevant to this topic. See the Postfix \fBmain.cf\fR file for syntax details and for default values. Use the \fBpostfix reload\fR command after a configuration change. +.IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +List of Postfix features that use \fIdomain.name\fR patterns +to match \fIsub.domain.name\fR (as opposed to +requiring \fI.domain.name\fR patterns). .IP \fBtransport_maps\fR List of transport lookup tables. .PP diff --git a/postfix/man/man8/flush.8 b/postfix/man/man8/flush.8 index f11f4854b..49d6eca37 100644 --- a/postfix/man/man8/flush.8 +++ b/postfix/man/man8/flush.8 @@ -126,6 +126,10 @@ a send request for the corresponding destination. .IP \fBfast_flush_purge_time\fR Remove an empty "fast flush" logfile that was not updated in this amount of time (default time unit: days). +.IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +List of Postfix features that use \fIdomain.name\fR patterns +to match \fIsub.domain.name\fR (as opposed to +requiring \fI.domain.name\fR patterns). .SH SEE ALSO .na .nf diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 182338e7f..edad7fd82 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -183,6 +183,10 @@ it is penalized with tarpit delays. .SH "UCE control restrictions" .ad .fi +.IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +List of Postfix features that use \fIdomain.name\fR patterns +to match \fIsub.domain.name\fR (as opposed to +requiring \fI.domain.name\fR patterns). .IP \fBsmtpd_client_restrictions\fR Restrict what clients may connect to this mail system. .IP \fBsmtpd_helo_required\fR diff --git a/postfix/man/man8/trivial-rewrite.8 b/postfix/man/man8/trivial-rewrite.8 index bf110a702..410b72a3b 100644 --- a/postfix/man/man8/trivial-rewrite.8 +++ b/postfix/man/man8/trivial-rewrite.8 @@ -108,6 +108,10 @@ The default transport is \fBsmtp\fR. .sp Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5) for details. The :\fInexthop\fR part is optional. +.IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +List of Postfix features that use \fIdomain.name\fR patterns +to match \fIsub.domain.name\fR (as opposed to +requiring \fI.domain.name\fR patterns). .IP \fBrelayhost\fR The default host to send non-local mail to when no entry is matched in the \fBtransport\fR(5) table. diff --git a/postfix/man/man8/virtual.8 b/postfix/man/man8/virtual.8 index 52b1fbe75..b76c1a752 100644 --- a/postfix/man/man8/virtual.8 +++ b/postfix/man/man8/virtual.8 @@ -86,9 +86,11 @@ numerical user ID values that may be specified in any .SH SECURITY .na .nf +.ad +.fi The virtual delivery agent is not security sensitive, provided -that the lookup tables with recipient information are adequately -protected. This program is not designed to run chrooted. +that the lookup tables with recipient user/group ID information are +adequately protected. This program is not designed to run chrooted. .SH STANDARDS .na .nf @@ -162,7 +164,7 @@ directory of the mailbox file. This setting is ignored with \fBmaildir\fR style delivery, because such deliveries are safe without explicit locks. -Use the command \fBpostconf -m\fR to find out what locking methods +Use the command \fBpostconf -l\fR to find out what locking methods are available on your system. .IP \fBdeliver_lock_attempts\fR Limit the number of attempts to acquire an exclusive lock diff --git a/postfix/proto/transport b/postfix/proto/transport index 70c1a5843..ff2c109d1 100644 --- a/postfix/proto/transport +++ b/postfix/proto/transport @@ -136,6 +136,10 @@ # this topic. See the Postfix \fBmain.cf\fR file for syntax details # and for default values. Use the \fBpostfix reload\fR command after # a configuration change. +# .IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +# List of Postfix features that use \fIdomain.name\fR patterns +# to match \fIsub.domain.name\fR (as opposed to +# requiring \fI.domain.name\fR patterns). # .IP \fBtransport_maps\fR # List of transport lookup tables. # .PP diff --git a/postfix/src/flush/Makefile.in b/postfix/src/flush/Makefile.in index fc0819df1..835aea378 100644 --- a/postfix/src/flush/Makefile.in +++ b/postfix/src/flush/Makefile.in @@ -78,4 +78,7 @@ flush.o: ../../include/mail_conf.h flush.o: ../../include/mail_scan_dir.h flush.o: ../../include/maps.h flush.o: ../../include/domain_list.h +flush.o: ../../include/match_list.h +flush.o: ../../include/match_ops.h +flush.o: ../../include/match_parent_style.h flush.o: ../../include/mail_server.h diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index 67a8814c8..71258a1a4 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -110,6 +110,10 @@ /* .IP \fBfast_flush_purge_time\fR /* Remove an empty "fast flush" logfile that was not updated in /* this amount of time (default time unit: days). +/* .IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +/* List of Postfix features that use \fIdomain.name\fR patterns +/* to match \fIsub.domain.name\fR (as opposed to +/* requiring \fI.domain.name\fR patterns). /* SEE ALSO /* smtpd(8) Postfix SMTP server /* qmgr(8) Postfix queue manager @@ -160,6 +164,7 @@ #include #include #include +#include /* Single server skeleton. */ @@ -636,7 +641,8 @@ static void flush_service(VSTREAM *client_stream, char *unused_service, static void pre_jail_init(char *unused_name, char **unused_argv) { - flush_domains = domain_list_init(var_fflush_domains); + flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS), + var_fflush_domains); } /* main - pass control to the single-threaded skeleton */ diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index c7548ebd1..92773fe68 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -19,7 +19,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \ timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \ tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \ - verp_sender.c + verp_sender.c match_parent_style.c OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ debug_peer.o debug_process.o defer.o deliver_completed.o \ deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \ @@ -40,7 +40,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \ tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \ - verp_sender.o + verp_sender.o match_parent_style.o HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ config.h debug_peer.h debug_process.h defer.h deliver_completed.h \ deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \ @@ -56,7 +56,8 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ recipient_list.h record.h resolve_clnt.h resolve_local.h \ rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \ sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \ - mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h + mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \ + match_parent_style.h TESTSRC = rec2stream.c stream2rec.c recdump.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ @@ -318,7 +319,10 @@ debug_peer.o: ../../include/sys_defs.h debug_peer.o: ../../include/msg.h debug_peer.o: mail_params.h debug_peer.o: namadr_list.h +debug_peer.o: ../../include/match_list.h +debug_peer.o: ../../include/match_ops.h debug_peer.o: debug_peer.h +debug_peer.o: match_parent_style.h debug_process.o: debug_process.c debug_process.o: ../../include/sys_defs.h debug_process.o: ../../include/msg.h @@ -388,8 +392,8 @@ deliver_request.o: deliver_request.h domain_list.o: domain_list.c domain_list.o: ../../include/sys_defs.h domain_list.o: ../../include/match_list.h -domain_list.o: ../../include/match_ops.h domain_list.o: domain_list.h +domain_list.o: ../../include/match_ops.h dot_lockfile.o: dot_lockfile.c dot_lockfile.o: ../../include/sys_defs.h dot_lockfile.o: ../../include/vstring.h @@ -721,6 +725,13 @@ mark_corrupt.o: ../../include/vbuf.h mark_corrupt.o: mail_queue.h mark_corrupt.o: ../../include/vstring.h mark_corrupt.o: mark_corrupt.h +match_parent_style.o: match_parent_style.c +match_parent_style.o: ../../include/sys_defs.h +match_parent_style.o: string_list.h +match_parent_style.o: ../../include/match_list.h +match_parent_style.o: ../../include/match_ops.h +match_parent_style.o: mail_params.h +match_parent_style.o: match_parent_style.h mbox_conf.o: mbox_conf.c mbox_conf.o: ../../include/sys_defs.h mbox_conf.o: ../../include/name_mask.h @@ -799,8 +810,8 @@ mypwd.o: mypwd.h namadr_list.o: namadr_list.c namadr_list.o: ../../include/sys_defs.h namadr_list.o: ../../include/match_list.h -namadr_list.o: ../../include/match_ops.h namadr_list.o: namadr_list.h +namadr_list.o: ../../include/match_ops.h off_cvt.o: off_cvt.c off_cvt.o: ../../include/sys_defs.h off_cvt.o: ../../include/msg.h @@ -935,9 +946,12 @@ resolve_local.o: ../../include/sys_defs.h resolve_local.o: ../../include/msg.h resolve_local.o: ../../include/mymalloc.h resolve_local.o: string_list.h +resolve_local.o: ../../include/match_list.h +resolve_local.o: ../../include/match_ops.h resolve_local.o: mail_params.h resolve_local.o: own_inet_addr.h resolve_local.o: resolve_local.h +resolve_local.o: match_parent_style.h rewrite_clnt.o: rewrite_clnt.c rewrite_clnt.o: ../../include/sys_defs.h rewrite_clnt.o: ../../include/msg.h @@ -985,8 +999,8 @@ stream2rec.o: rec_type.h string_list.o: string_list.c string_list.o: ../../include/sys_defs.h string_list.o: ../../include/match_list.h -string_list.o: ../../include/match_ops.h string_list.o: string_list.h +string_list.o: ../../include/match_ops.h sys_exits.o: sys_exits.c sys_exits.o: ../../include/sys_defs.h sys_exits.o: ../../include/msg.h diff --git a/postfix/src/global/debug_peer.c b/postfix/src/global/debug_peer.c index 29170bad5..c7096c973 100644 --- a/postfix/src/global/debug_peer.c +++ b/postfix/src/global/debug_peer.c @@ -69,6 +69,7 @@ #include #include #include +#include /* Application-specific. */ @@ -97,7 +98,9 @@ void debug_peer_init(void) * Finally. */ if (*var_debug_peer_list) - debug_peer_list = namadr_list_init(var_debug_peer_list); + debug_peer_list = + namadr_list_init(match_parent_style(VAR_DEBUG_PEER_LIST), + var_debug_peer_list); } /* debug_peer_check - see if this peer needs verbose logging */ diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index cf4a614c2..f428d551e 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -97,14 +97,14 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, request->flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, request->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, request->queue_id, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, request->data_offset, - ATTR_TYPE_NUM, MAIL_ATTR_SIZE, request->data_size, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, request->data_offset, + ATTR_TYPE_LONG, MAIL_ATTR_SIZE, request->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, ATTR_TYPE_STR, MAIL_ATTR_SENDER, request->sender, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, request->errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, request->return_receipt, - ATTR_TYPE_NUM, MAIL_ATTR_TIME, request->arrival_time, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, offs, + ATTR_TYPE_LONG, MAIL_ATTR_TIME, request->arrival_time, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offs, ATTR_TYPE_STR, MAIL_ATTR_RECIP, addr, ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0, ATTR_TYPE_END); diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index 344276a1d..35c83e780 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -196,13 +196,13 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, &request->data_offset, - ATTR_TYPE_NUM, MAIL_ATTR_SIZE, &request->data_size, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &request->data_offset, + ATTR_TYPE_LONG, MAIL_ATTR_SIZE, &request->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, ATTR_TYPE_STR, MAIL_ATTR_SENDER, address, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt, - ATTR_TYPE_NUM, MAIL_ATTR_TIME, &request->arrival_time, + ATTR_TYPE_LONG, MAIL_ATTR_TIME, &request->arrival_time, ATTR_TYPE_END) != 10) return (-1); if (mail_open_ok(vstring_str(queue_name), @@ -222,7 +222,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) */ for (;;) { if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, &offset, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &offset, ATTR_TYPE_END) != 1) return (-1); if (offset == 0) diff --git a/postfix/src/global/domain_list.c b/postfix/src/global/domain_list.c index 1322642d0..d4ea536b2 100644 --- a/postfix/src/global/domain_list.c +++ b/postfix/src/global/domain_list.c @@ -6,7 +6,8 @@ /* SYNOPSIS /* #include /* -/* DOMAIN_LIST *domain_list_init(pattern_list) +/* DOMAIN_LIST *domain_list_init(flags, pattern_list) +/* int flags; /* const char *pattern_list; /* /* int domain_list_match(list, name) @@ -16,6 +17,8 @@ /* void domain_list_free(list) /* DOMAIN_LIST *list; /* DESCRIPTION +/* This is a convenience wrapper around the match_list module. +/* /* This module implements tests for list membership of a host or /* domain name. /* @@ -30,9 +33,17 @@ /* insensitive. In order to reverse the result, precede a non-file /* name pattern with an exclamation point (!). /* -/* domain_list_init() performs initializations. The argument is a -/* list of domain patterns, or the name of a file containing domain -/* patterns. +/* domain_list_init() performs initializations. The first argument +/* is the bit-wise OR of zero or more of the following: +/* .RS +/* .IP MATCH_FLAG_PARENT +/* The hostname pattern foo.com matches itself and any name below +/* the domain foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. +/* .RE +/* Specify MATCH_FLAG_NONE to request none of the above. +/* The second argument is a list of domain patterns, or the name of +/* a file containing domain patterns. /* /* domain_list_match() matches the specified host or domain name /* against the specified pattern list. @@ -62,33 +73,11 @@ /* Utility library. */ #include -#include /* Global library. */ #include "domain_list.h" -/* domain_list_init - initialize domain list */ - -DOMAIN_LIST *domain_list_init(const char *patterns) -{ - return (match_list_init(patterns, 1, match_hostname)); -} - -/* domain_list_match - match host against domain list */ - -int domain_list_match(DOMAIN_LIST *list, const char *name) -{ - return (match_list_match(list, name)); -} - -/* domain_list_free - release storage */ - -void domain_list_free(DOMAIN_LIST *list) -{ - match_list_free(list); -} - #ifdef TEST #include @@ -120,7 +109,7 @@ main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = domain_list_init(argv[optind]); + list = domain_list_init(MATCH_FLAG_PARENT, argv[optind]); host = argv[optind + 1]; vstream_printf("%s: %s\n", host, domain_list_match(list, host) ? "YES" : "NO"); diff --git a/postfix/src/global/domain_list.h b/postfix/src/global/domain_list.h index b36f516b4..23f60c789 100644 --- a/postfix/src/global/domain_list.h +++ b/postfix/src/global/domain_list.h @@ -11,14 +11,20 @@ /* DESCRIPTION /* .nf + /* + * Utility library. + */ +#include +#include + /* * External interface. */ -typedef struct MATCH_LIST DOMAIN_LIST; +#define DOMAIN_LIST MATCH_LIST -extern DOMAIN_LIST *domain_list_init(const char *); -extern int domain_list_match(DOMAIN_LIST *, const char *); -extern void domain_list_free(DOMAIN_LIST *); +#define domain_list_init(f, p) match_list_init((f), (p), 1, match_hostname) +#define domain_list_match match_list_match +#define domain_list_free match_list_free /* LICENSE /* .ad diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 98da1b2d7..803996ffc 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -64,6 +64,7 @@ /* char *var_mynetworks_style; /* char *var_verp_delims; /* char *var_verp_filter; +/* char *var_par_dom_match; /* /* char *var_import_environ; /* char *var_export_environ; @@ -187,6 +188,7 @@ char *var_mynetworks_style; char *var_verp_delims; char *var_verp_filter; int var_in_flow_delay; +char *var_par_dom_match; char *var_import_environ; char *var_export_environ; @@ -312,6 +314,7 @@ void mail_params_init() VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0, VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2, VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0, + VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0, 0, }; static CONFIG_STR_FN_TABLE function_str_defaults_2[] = { diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 21b8ef185..c65cee5ee 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1140,6 +1140,8 @@ extern int var_access_map_code; #define CHECK_RECIP_ACL "check_recipient_access" #define CHECK_ETRN_ACL "check_etrn_access" +#define WARN_IF_REJECT "warn_if_reject" + #define REJECT_MAPS_RBL "reject_maps_rbl" #define VAR_MAPS_RBL_CODE "maps_rbl_reject_code" #define DEF_MAPS_RBL_CODE 554 @@ -1319,6 +1321,21 @@ extern bool var_verp_bounce_off; #define DEF_IN_FLOW_DELAY "1s" extern int var_in_flow_delay; + /* + * Backwards compatibility: foo.com matches itself and names below foo.com. + */ +#define VAR_PAR_DOM_MATCH "parent_domain_matches_subdomains" +#define DEF_PAR_DOM_MATCH VAR_DEBUG_PEER_LIST "," \ + VAR_FFLUSH_DOMAINS "," \ + VAR_MYNETWORKS "," \ + VAR_PERM_MX_NETWORKS "," \ + VAR_QMQPD_CLIENTS "," \ + VAR_RELAY_DOMAINS "," \ + SMTPD_ACCESS_MAPS +extern char *var_par_dom_match; + +#define SMTPD_ACCESS_MAPS "smtpd_access_maps" + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 9ee1b16fe..8d16673aa 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20011120" +#define DEF_MAIL_VERSION "Snapshot-20011121" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/global/match_parent_style.c b/postfix/src/global/match_parent_style.c new file mode 100644 index 000000000..a914f616f --- /dev/null +++ b/postfix/src/global/match_parent_style.c @@ -0,0 +1,72 @@ +/*++ +/* NAME +/* match_parent_style 3 +/* SUMMARY +/* parent domain matching control +/* SYNOPSIS +/* #include +/* +/* int match_parent_style(name) +/* const char *name; +/* DESCRIPTION +/* This module queries configuration parameters for the policy that +/* controls how wild-card parent domain names are used by various +/* postfix lookup mechanisms. +/* +/* match_parent_style() looks up "name" in the +/* parent_domain_matches_subdomain configuration parameter +/* and returns either MATCH_FLAG_PARENT or MATCH_PARENT_NONE. +/* DIAGNOSTICS +/* Fatal error: out of memory, name listed under both parent wild card +/* matching policies. +/* SEE ALSO +/* string_list(3) plain string matching +/* domain_list(3) match host name patterns +/* namadr_list(3) match host name/address patterns +/* 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 + +/* Utility library. */ + +/* Global library. */ + +#include +#include +#include + +/* Application-specific. */ + +static STRING_LIST *match_par_dom_list; + +int match_parent_style(const char *name) +{ + int result; + + /* + * Initialize on the fly. + */ + if (match_par_dom_list == 0) + match_par_dom_list = + string_list_init(MATCH_FLAG_NONE, var_par_dom_match); + + /* + * Look up the parent domain matching policy. + */ + if (string_list_match(match_par_dom_list, name)) + result = MATCH_FLAG_PARENT; + else + result = 0; + return (result); +} diff --git a/postfix/src/global/match_parent_style.h b/postfix/src/global/match_parent_style.h new file mode 100644 index 000000000..7b51eddf7 --- /dev/null +++ b/postfix/src/global/match_parent_style.h @@ -0,0 +1,35 @@ +#ifndef _MATCH_PARENT_STYLE_H_INCLUDED_ +#define _MATCH_PARENT_STYLE_H_INCLUDED_ + +/*++ +/* NAME +/* match_parent_style 3h +/* SUMMARY +/* parent domain matching control +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +extern int match_parent_style(const char *); + +/* 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 diff --git a/postfix/src/global/namadr_list.c b/postfix/src/global/namadr_list.c index 0e6b1bba7..c5169d87e 100644 --- a/postfix/src/global/namadr_list.c +++ b/postfix/src/global/namadr_list.c @@ -6,7 +6,8 @@ /* SYNOPSIS /* #include /* -/* NAMADR_LIST *namadr_list_init(pattern_list) +/* NAMADR_LIST *namadr_list_init(flags, pattern_list) +/* int flags; /* const char *pattern_list; /* /* int namadr_list_match(list, name, addr) @@ -17,6 +18,8 @@ /* void namadr_list_free(list) /* NAMADR_LIST *list; /* DESCRIPTION +/* This is a convenience wrapper around the match_list module. +/* /* This module implements tests for list membership of a /* hostname or network address. /* @@ -35,9 +38,18 @@ /* a pattern, or when any of its parent domains matches a /* pattern. The matching process is case insensitive. /* -/* namadr_list_init() performs initializations. The argument -/* is a list of patterns, or the absolute pathname of a file -/* with patterns. +/* namadr_list_init() performs initializations. The first +/* argument is the bit-wise OR of zero or more of the +/* following: +/* .RS +/* .IP MATCH_FLAG_PARENT +/* The hostname pattern foo.com matches itself and any name below +/* the domain foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. +/* .RE +/* Specify MATCH_FLAG_NONE to request none of the above. +/* The second argument is a list of patterns, or the absolute +/* pathname of a file with patterns. /* /* namadr_list_match() matches the specified host name and /* address against the specified list of patterns. @@ -67,33 +79,11 @@ /* Utility library. */ #include -#include /* Global library. */ #include "namadr_list.h" -/* namadr_list_init - initialize domain list */ - -NAMADR_LIST *namadr_list_init(const char *patterns) -{ - return (match_list_init(patterns, 2, match_hostaddr, match_hostname)); -} - -/* namadr_list_match - match host against set of namadr_list patterns */ - -int namadr_list_match(NAMADR_LIST *list, const char *name, const char *addr) -{ - return (match_list_match(list, addr, name)); -} - -/* namadr_list_free - release storage */ - -void namadr_list_free(NAMADR_LIST *list) -{ - match_list_free(list); -} - #ifdef TEST #include @@ -126,7 +116,7 @@ main(int argc, char **argv) } if (argc != optind + 3) usage(argv[0]); - list = namadr_list_init(argv[optind]); + list = namadr_list_init(MATCH_FLAG_PARENT, argv[optind]); host = argv[optind + 1]; addr = argv[optind + 2]; vstream_printf("%s/%s: %s\n", host, addr, diff --git a/postfix/src/global/namadr_list.h b/postfix/src/global/namadr_list.h index 186cd66c1..9bf90d768 100644 --- a/postfix/src/global/namadr_list.h +++ b/postfix/src/global/namadr_list.h @@ -7,18 +7,25 @@ /* SUMMARY /* name/address membership /* SYNOPSIS -/* #include +/* #include /* DESCRIPTION /* .nf + /* + * Utility library. + */ +#include +#include + /* * External interface. */ -typedef struct MATCH_LIST NAMADR_LIST; +#define NAMADR_LIST MATCH_LIST -extern NAMADR_LIST *namadr_list_init(const char *); -extern int namadr_list_match(NAMADR_LIST *, const char *, const char *); -extern void namadr_list_free(NAMADR_LIST *); +#define namadr_list_init(f, p) \ + match_list_init((f), (p), 2, match_hostname, match_hostaddr) +#define namadr_list_match match_list_match +#define namadr_list_free match_list_free /* LICENSE /* .ad diff --git a/postfix/src/global/resolve_local.c b/postfix/src/global/resolve_local.c index 42fbae7b3..94a5a4dbf 100644 --- a/postfix/src/global/resolve_local.c +++ b/postfix/src/global/resolve_local.c @@ -58,6 +58,7 @@ #include #include #include +#include /* Application-specific */ @@ -69,7 +70,7 @@ void resolve_local_init(void) { if (resolve_local_list) msg_panic("resolve_local_init: duplicate initialization"); - resolve_local_list = string_list_init(var_mydest); + resolve_local_list = string_list_init(MATCH_FLAG_NONE, var_mydest); } /* resolve_local - match address against list of local destinations */ diff --git a/postfix/src/global/string_list.c b/postfix/src/global/string_list.c index bcb457e77..522ff26a1 100644 --- a/postfix/src/global/string_list.c +++ b/postfix/src/global/string_list.c @@ -6,7 +6,8 @@ /* SYNOPSIS /* #include /* -/* STRING_LIST *string_list_init(pattern_list) +/* STRING_LIST *string_list_init(flags, pattern_list) +/* int flags; /* const char *pattern_list; /* /* int string_list_match(list, name) @@ -16,6 +17,8 @@ /* void string_list_free(list) /* STRING_LIST *list; /* DESCRIPTION +/* This is a convenience wrapper around the match_list module. +/* /* This module implements tests for list membership of a string. /* /* Patterns are separated by whitespace and/or commas. A pattern @@ -28,8 +31,8 @@ /* In order to reverse the result, precede a non-file name pattern /* with an exclamation point (!). /* -/* string_list_init() performs initializations. The argument is a -/* list of string patterns. +/* string_list_init() performs initializations. The flags argument +/* is ignored; pattern_list specifies a list of string patterns. /* /* string_list_match() matches the specified string against the /* compiled pattern list. @@ -58,33 +61,11 @@ /* Utility library. */ #include -#include /* Global library. */ #include "string_list.h" -/* string_list_init - initialize string list */ - -STRING_LIST *string_list_init(const char *patterns) -{ - return (match_list_init(patterns, 1, match_string)); -} - -/* string_list_match - match string against list */ - -int string_list_match(STRING_LIST * list, const char *string) -{ - return (match_list_match(list, string)); -} - -/* string_list_free - release storage */ - -void string_list_free(STRING_LIST * list) -{ - match_list_free(list); -} - #ifdef TEST #include @@ -117,7 +98,7 @@ main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = string_list_init(argv[optind]); + list = string_list_init(MATCH_FLAG_NONE, argv[optind]); string = argv[optind + 1]; vstream_printf("%s: %s\n", string, string_list_match(list, string) ? "YES" : "NO"); diff --git a/postfix/src/global/string_list.h b/postfix/src/global/string_list.h index 946ecf1d2..daa9541d2 100644 --- a/postfix/src/global/string_list.h +++ b/postfix/src/global/string_list.h @@ -11,14 +11,20 @@ /* DESCRIPTION /* .nf + /* + * Utility library. + */ +#include +#include + /* * External interface. */ -typedef struct MATCH_LIST STRING_LIST; +#define STRING_LIST MATCH_LIST -extern STRING_LIST *string_list_init(const char *); -extern int string_list_match(STRING_LIST *, const char *); -extern void string_list_free(STRING_LIST *); +#define string_list_init(f, p) match_list_init((f), (p), 1, match_string) +#define string_list_match match_list_match +#define string_list_free match_list_free /* LICENSE /* .ad diff --git a/postfix/src/lmtp/Makefile.in b/postfix/src/lmtp/Makefile.in index 29c313c24..cb8f5637f 100644 --- a/postfix/src/lmtp/Makefile.in +++ b/postfix/src/lmtp/Makefile.in @@ -176,6 +176,8 @@ lmtp_sasl_glue.o: ../../include/split_at.h lmtp_sasl_glue.o: ../../include/name_mask.h lmtp_sasl_glue.o: ../../include/mail_params.h lmtp_sasl_glue.o: ../../include/string_list.h +lmtp_sasl_glue.o: ../../include/match_list.h +lmtp_sasl_glue.o: ../../include/match_ops.h lmtp_sasl_glue.o: ../../include/maps.h lmtp_sasl_glue.o: ../../include/dict.h lmtp_sasl_glue.o: ../../include/vstream.h diff --git a/postfix/src/local/file.c b/postfix/src/local/file.c index e3a530ba8..610b1a61d 100644 --- a/postfix/src/local/file.c +++ b/postfix/src/local/file.c @@ -170,7 +170,7 @@ int deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path) * As the mail system, bounce, defer delivery, or report success. */ if (status != 0) { - status = (errno == EAGAIN || errno == ENOSPC ? + status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ? defer_append : bounce_append) (BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr), "cannot append message to destination file %s: %s", diff --git a/postfix/src/local/mailbox.c b/postfix/src/local/mailbox.c index 667a65e19..a07d11389 100644 --- a/postfix/src/local/mailbox.c +++ b/postfix/src/local/mailbox.c @@ -203,7 +203,7 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) * As the mail system, bounce, defer delivery, or report success. */ if (status != 0) { - status = (errno == EAGAIN || errno == ENOSPC ? + status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ? defer_append : bounce_append) (BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr), "cannot access mailbox %s for user %s. %s", @@ -283,18 +283,14 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) */ #define LAST_CHAR(s) (s[strlen(s) - 1]) - if (*var_mailbox_cmd_maps) { - if (cmd_maps == 0) - cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps, - DICT_FLAG_LOCK); - if ((map_command = maps_find(cmd_maps, state.msg_attr.user, - DICT_FLAG_FIXED)) != 0) { - status = deliver_command(state, usr_attr, map_command); - } else { - msg_warn("user %s not found in %s", - state.msg_attr.user, var_mailbox_cmd_maps); - return (NO); - } + if (*var_mailbox_cmd_maps && cmd_maps == 0) + cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps, + DICT_FLAG_LOCK); + + if (*var_mailbox_cmd_maps + && (map_command = maps_find(cmd_maps, state.msg_attr.user, + DICT_FLAG_FIXED)) != 0) { + status = deliver_command(state, usr_attr, map_command); } else if (*var_mailbox_command) { status = deliver_command(state, usr_attr, var_mailbox_command); } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') { diff --git a/postfix/src/local/maildir.c b/postfix/src/local/maildir.c index e9bd0de85..195e0bfdb 100644 --- a/postfix/src/local/maildir.c +++ b/postfix/src/local/maildir.c @@ -153,7 +153,8 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path) set_eugid(var_owner_uid, var_owner_gid); if (status) - status = (errno == ENOSPC ? defer_append : bounce_append) + status = (errno == ENOSPC || errno == ESTALE ? + defer_append : bounce_append) (BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr), "maildir delivery failed: %s", vstring_str(why)); else diff --git a/postfix/src/nqmgr/qmgr_deliver.c b/postfix/src/nqmgr/qmgr_deliver.c index 7dbe299e6..394b267d6 100644 --- a/postfix/src/nqmgr/qmgr_deliver.c +++ b/postfix/src/nqmgr/qmgr_deliver.c @@ -163,19 +163,19 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, message->data_offset, - ATTR_TYPE_NUM, MAIL_ATTR_SIZE, message->data_size, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset, + ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt, - ATTR_TYPE_NUM, MAIL_ATTR_TIME, message->arrival_time, + ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time, ATTR_TYPE_END); if (sender_buf != 0) vstring_free(sender_buf); for (recipient = list.info; recipient < list.info + list.len; recipient++) attr_print(stream, ATTR_FLAG_MORE, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, recipient->offset, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address, ATTR_TYPE_END); attr_print(stream, ATTR_FLAG_NONE, diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index d9559dd9a..b5cfc89ac 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -23,7 +23,10 @@ $(PROG): $(OBJS) $(LIBS) ../../conf/main.cf.default: $(PROG) Makefile rm -f $@ - ./$(PROG) -d |egrep -v '^(myhostname|mydomain|mynetworks) ' >$@ + (echo "# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE"; \ + echo "# TEXT HERE JUST SHOWS DEFAULT SETTINGS BUILT INTO POSTFIX."; \ + echo "#"; \ + ./$(PROG) -d) |egrep -v '^(myhostname|mydomain|mynetworks) ' >$@ Makefile: Makefile.in (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@ diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index 403cc8ec5..45c0a6cdd 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -158,19 +158,19 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, message->data_offset, - ATTR_TYPE_NUM, MAIL_ATTR_SIZE, message->data_size, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset, + ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt, - ATTR_TYPE_NUM, MAIL_ATTR_TIME, message->arrival_time, + ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time, ATTR_TYPE_END); if (sender_buf != 0) vstring_free(sender_buf); for (recipient = list.info; recipient < list.info + list.len; recipient++) attr_print(stream, ATTR_FLAG_MORE, - ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, recipient->offset, + ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address, ATTR_TYPE_END); attr_print(stream, ATTR_FLAG_NONE, diff --git a/postfix/src/qmqpd/Makefile.in b/postfix/src/qmqpd/Makefile.in index b5fa478cc..5e923c5b0 100644 --- a/postfix/src/qmqpd/Makefile.in +++ b/postfix/src/qmqpd/Makefile.in @@ -89,7 +89,10 @@ qmqpd.o: ../../include/mail_conf.h qmqpd.o: ../../include/debug_peer.h qmqpd.o: ../../include/mail_stream.h qmqpd.o: ../../include/namadr_list.h +qmqpd.o: ../../include/match_list.h +qmqpd.o: ../../include/match_ops.h qmqpd.o: ../../include/quote_822_local.h +qmqpd.o: ../../include/match_parent_style.h qmqpd.o: ../../include/mail_server.h qmqpd.o: qmqpd.h qmqpd_peer.o: qmqpd_peer.c diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 5b1d1d1b0..cb23d5a16 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -135,6 +135,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -643,7 +644,9 @@ static void pre_accept(char *unused_name, char **unused_argv) static void pre_jail_init(char *unused_name, char **unused_argv) { debug_peer_init(); - qmqpd_clients = namadr_list_init(var_qmqpd_clients); + qmqpd_clients = + namadr_list_init(match_parent_style(VAR_QMQPD_CLIENTS), + var_qmqpd_clients); } /* main - the main program */ diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index cdf6ad880..b23589070 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -603,7 +603,7 @@ static void chat(VSTREAM *fp, VSTRING *buf, const char *fmt,...) smtp_get(buf, fp, var_line_limit); if (STR(buf)[0] != '2') - msg_fatal("server rejected request: %s", STR(buf)); + msg_fatal("server rejected ETRN request: %s", STR(buf)); if (msg_verbose) msg_info("<<< %s", STR(buf)); diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 87ba5ac14..035cd5aca 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -151,6 +151,7 @@ smtp_proto.o: ../../include/vstream.h smtp_proto.o: ../../include/vstring_vstream.h smtp_proto.o: ../../include/stringops.h smtp_proto.o: ../../include/mymalloc.h +smtp_proto.o: ../../include/iostuff.h smtp_proto.o: ../../include/mail_params.h smtp_proto.o: ../../include/smtp_stream.h smtp_proto.o: ../../include/mail_queue.h @@ -179,6 +180,8 @@ smtp_sasl_glue.o: ../../include/split_at.h smtp_sasl_glue.o: ../../include/name_mask.h smtp_sasl_glue.o: ../../include/mail_params.h smtp_sasl_glue.o: ../../include/string_list.h +smtp_sasl_glue.o: ../../include/match_list.h +smtp_sasl_glue.o: ../../include/match_ops.h smtp_sasl_glue.o: ../../include/maps.h smtp_sasl_glue.o: ../../include/dict.h smtp_sasl_glue.o: ../../include/vstream.h diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index b26095fd8..3a8f4d1df 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -82,6 +82,7 @@ #include #include #include +#include /* Global library. */ @@ -178,8 +179,11 @@ int smtp_helo(SMTP_STATE *state) * does not span a packet boundary. This hurts performance so it is not * on by default. */ - if (resp->str[strspn(resp->str, "20 *\t\n")] == 0) + if (resp->str[strspn(resp->str, "20 *\t\n")] == 0) { + msg_info("enabling PIX . workaround for %s", + session->namaddr); state->features |= SMTP_FEATURE_MAYBEPIX; + } /* * See if we are talking to ourself. This should not be possible with the @@ -196,9 +200,9 @@ int smtp_helo(SMTP_STATE *state) } else if (strcasecmp(word, "ESMTP") == 0) state->features |= SMTP_FEATURE_ESMTP; } - if (var_smtp_always_ehlo) + if (var_smtp_always_ehlo && (state->features & SMTP_FEATURE_MAYBEPIX) == 0) state->features |= SMTP_FEATURE_ESMTP; - if (var_smtp_never_ehlo) + if (var_smtp_never_ehlo || (state->features & SMTP_FEATURE_MAYBEPIX) != 0) state->features &= ~SMTP_FEATURE_ESMTP; /* @@ -657,9 +661,10 @@ int smtp_xfer(SMTP_STATE *state) if (prev_type == REC_TYPE_CONT) /* missing newline at end */ smtp_fputs("", 0, session->stream); - if ((state->features & SMTP_FEATURE_ESMTP) == 0 - && (state->features & SMTP_FEATURE_MAYBEPIX) != 0) + if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0) { vstream_fflush(session->stream);/* hurts performance */ + sleep(10); /* not to mention this */ + } if (vstream_ferror(state->src)) msg_fatal("queue file read error"); if (rec_type != REC_TYPE_XTRA) diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index e8181359b..f94336be3 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -176,6 +176,8 @@ smtpd_check.o: ../../include/htable.h smtpd_check.o: ../../include/ctable.h smtpd_check.o: ../../include/dns.h smtpd_check.o: ../../include/namadr_list.h +smtpd_check.o: ../../include/match_list.h +smtpd_check.o: ../../include/match_ops.h smtpd_check.o: ../../include/domain_list.h smtpd_check.o: ../../include/mail_params.h smtpd_check.o: ../../include/canon_addr.h @@ -187,6 +189,7 @@ smtpd_check.o: ../../include/own_inet_addr.h smtpd_check.o: ../../include/mail_conf.h smtpd_check.o: ../../include/maps.h smtpd_check.o: ../../include/mail_addr_find.h +smtpd_check.o: ../../include/match_parent_style.h smtpd_check.o: smtpd.h smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: smtpd_sasl_glue.h @@ -208,6 +211,8 @@ smtpd_sasl_glue.o: ../../include/sys_defs.h smtpd_sasl_glue.o: ../../include/msg.h smtpd_sasl_glue.o: ../../include/mymalloc.h smtpd_sasl_glue.o: ../../include/namadr_list.h +smtpd_sasl_glue.o: ../../include/match_list.h +smtpd_sasl_glue.o: ../../include/match_ops.h smtpd_sasl_glue.o: ../../include/name_mask.h smtpd_sasl_glue.o: ../../include/mail_params.h smtpd_sasl_glue.o: ../../include/smtp_stream.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index e2003ffd2..745c9e908 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -169,6 +169,10 @@ /* .SH "UCE control restrictions" /* .ad /* .fi +/* .IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +/* List of Postfix features that use \fIdomain.name\fR patterns +/* to match \fIsub.domain.name\fR (as opposed to +/* requiring \fI.domain.name\fR patterns). /* .IP \fBsmtpd_client_restrictions\fR /* Restrict what clients may connect to this mail system. /* .IP \fBsmtpd_helo_required\fR @@ -1281,7 +1285,7 @@ static void chat_reset(SMTPD_STATE *state) * report problems when running in stand-alone mode: postmaster notices * require availability of the cleanup service. */ - if (state->history != 0 && state->client != VSTREAM_IN + if (state->history != 0 && SMTPD_STAND_ALONE(state) == 0 && (state->error_mask & state->notify_mask)) smtpd_chat_notify(state); smtpd_chat_reset(state); diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index 29fb3d2d7..20386ad73 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -76,6 +76,7 @@ typedef struct SMTPD_STATE { VSTRING *sasl_encoded; VSTRING *sasl_decoded; #endif + int warn_if_reject; } SMTPD_STATE; extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index d558c37c3..6bd641706 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -289,6 +289,7 @@ #include #include #include +#include /* Application-specific. */ @@ -339,6 +340,11 @@ static DOMAIN_LIST *relay_domains; static NAMADR_LIST *mynetworks; static NAMADR_LIST *perm_mx_networks; + /* + * How to do parent domain wildcard matching, if any. + */ +static int access_parent_style; + /* * Pre-parsed restriction lists. */ @@ -452,6 +458,10 @@ static int has_required(ARGV *restrictions, char **required) * Recursively check list membership. */ for (rest = restrictions->argv; *rest; rest++) { + if (strcmp(*rest, WARN_IF_REJECT) == 0 && rest[1] != 0) { + rest += 1; + continue; + } for (reqd = required; *reqd; reqd++) if (strcmp(*rest, *reqd) == 0) return (1); @@ -481,8 +491,9 @@ static void fail_required(char *name, char **required) */ example = vstring_alloc(10); for (reqd = required; *reqd; reqd++) - vstring_sprintf_append(example, "%s ", *reqd); - msg_fatal("parameter \"%s\": specify at least one explicit instance of: %s", + vstring_sprintf_append(example, "%s%s", *reqd, + reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", "); + msg_fatal("parameter \"%s\": specify at least one working instance of: %s", name, STR(example)); } @@ -504,9 +515,15 @@ void smtpd_check_init(void) /* * Pre-open access control lists before going to jail. */ - mynetworks = namadr_list_init(var_mynetworks); - relay_domains = domain_list_init(var_relay_domains); - perm_mx_networks = namadr_list_init(var_perm_mx_networks); + mynetworks = + namadr_list_init(match_parent_style(VAR_MYNETWORKS), + var_mynetworks); + relay_domains = + domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + var_relay_domains); + perm_mx_networks = + namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS), + var_perm_mx_networks); /* * Pre-parse and pre-open the recipient maps. @@ -524,6 +541,8 @@ void smtpd_check_init(void) relocated_maps = maps_create(VAR_RELOCATED_MAPS, var_relocated_maps, DICT_FLAG_LOCK); + access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS); + /* * error_text is used for returning error responses. */ @@ -585,6 +604,20 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class, char *format,...) { va_list ap; + int warn_if_reject; + const char *whatsup; + + /* + * Do not reject mail if we were asked to warn only. However, + * configuration errors cannot be converted into warnings. + */ + if (state->warn_if_reject && error_class != MAIL_ERROR_SOFTWARE) { + warn_if_reject = 1; + whatsup = "reject_warning"; + } else { + warn_if_reject = 0; + whatsup = "reject"; + } /* * Update the error class mask, and format the response. XXX What about @@ -634,22 +667,22 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class, * rejected. Print the request, client name/address, and response. */ if (state->recipient && state->sender) { - msg_info("reject: %s from %s: %s; from=<%s> to=<%s>", - state->where, state->namaddr, STR(error_text), + msg_info("%s: %s from %s: %s; from=<%s> to=<%s>", + whatsup, state->where, state->namaddr, STR(error_text), state->sender, state->recipient); } else if (state->recipient) { - msg_info("reject: %s from %s: %s; to=<%s>", - state->where, state->namaddr, STR(error_text), + msg_info("%s: %s from %s: %s; to=<%s>", + whatsup, state->where, state->namaddr, STR(error_text), state->recipient); } else if (state->sender) { - msg_info("reject: %s from %s: %s; from=<%s>", - state->where, state->namaddr, STR(error_text), + msg_info("%s: %s from %s: %s; from=<%s>", + whatsup, state->where, state->namaddr, STR(error_text), state->sender); } else { - msg_info("reject: %s from %s: %s", - state->where, state->namaddr, STR(error_text)); + msg_info("%s: %s from %s: %s", + whatsup, state->where, state->namaddr, STR(error_text)); } - return (SMTPD_CHECK_REJECT); + return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT); } /* reject_dict_retry - reject with temporary failure if dict lookup fails */ @@ -1542,7 +1575,7 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, if ((dict = dict_handle(table)) == 0) msg_panic("%s: dictionary not found: %s", myname, table); - for (name = low_domain; /* void */ ; name = next + 1) { + for (name = low_domain; /* void */ ; name = next) { if (flags == 0 || (flags & dict->flags) != 0) { if ((value = dict_get(dict, name)) != 0) CHK_DOMAIN_RETURN(check_table_result(state, table, value, @@ -1551,8 +1584,10 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, if (dict_errno != 0) msg_fatal("%s: table lookup problem", table); } - if ((next = strchr(name, '.')) == 0) + if ((next = strchr(name + 1, '.')) == 0) break; + if (access_parent_style == MATCH_FLAG_PARENT) + next += 1; flags = PARTIAL; } CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED); @@ -1824,6 +1859,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, int status = 0; ARGV *list; int found; + int saved_recursion = state->recursion; if (msg_verbose) msg_info("%s: START", myname); @@ -1833,6 +1869,15 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, if (msg_verbose) msg_info("%s: name=%s", myname, name); + /* + * Pseudo restrictions. + */ + if (strcasecmp(name, WARN_IF_REJECT) == 0) { + if (state->warn_if_reject == 0) + state->warn_if_reject = state->recursion; + continue; + } + /* * Spoof the is_map_command() routine, so that we do not have to make * special cases for the implicit short-hand access map notation. @@ -1847,14 +1892,14 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, */ if (strcasecmp(name, PERMIT_ALL) == 0) { status = SMTPD_CHECK_OK; - if (cpp[1] != 0) + if (cpp[1] != 0 && state->warn_if_reject == 0) msg_warn("restriction `%s' after `%s' is ignored", cpp[1], PERMIT_ALL); } else if (strcasecmp(name, REJECT_ALL) == 0) { status = smtpd_check_reject(state, MAIL_ERROR_POLICY, "%d <%s>: %s rejected: Access denied", var_reject_code, reply_name, reply_class); - if (cpp[1] != 0) + if (cpp[1] != 0 && state->warn_if_reject == 0) msg_warn("restriction `%s' after `%s' is ignored", cpp[1], REJECT_ALL); } else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) { @@ -1963,7 +2008,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, if (state->recipient) status = check_relay_domains(state, state->recipient, state->recipient, SMTPD_NAME_RECIPIENT); - if (cpp[1] != 0) + if (cpp[1] != 0 && state->warn_if_reject == 0) msg_warn("restriction `%s' after `%s' is ignored", cpp[1], CHECK_RELAY_DOMAINS); #ifdef USE_SASL_AUTH @@ -2011,12 +2056,17 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, if (msg_verbose) msg_info("%s: name=%s status=%d", myname, name, status); + if (state->warn_if_reject >= state->recursion) + state->warn_if_reject = 0; + if (status != 0) break; } if (msg_verbose && name == 0) msg_info("%s: END", myname); + state->recursion = saved_recursion; + return (status); } @@ -2035,7 +2085,7 @@ char *smtpd_check_client(SMTPD_STATE *state) /* * Apply restrictions in the order as specified. */ - state->recursion = 0; + state->recursion = 1; status = setjmp(smtpd_check_buf); if (status == 0 && client_restrctions->argc) status = generic_checks(state, client_restrctions, state->namaddr, @@ -2081,7 +2131,7 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost) /* * Apply restrictions in the order as specified. */ - state->recursion = 0; + state->recursion = 1; status = setjmp(smtpd_check_buf); if (status == 0 && helo_restrctions->argc) status = generic_checks(state, helo_restrctions, state->helo_name, @@ -2117,7 +2167,7 @@ char *smtpd_check_mail(SMTPD_STATE *state, char *sender) /* * Apply restrictions in the order as specified. */ - state->recursion = 0; + state->recursion = 1; status = setjmp(smtpd_check_buf); if (status == 0 && mail_restrctions->argc) status = generic_checks(state, mail_restrctions, sender, @@ -2171,7 +2221,7 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) /* * Apply restrictions in the order as specified. */ - state->recursion = 0; + state->recursion = 1; status = setjmp(smtpd_check_buf); if (status == 0 && rcpt_restrctions->argc) status = generic_checks(state, rcpt_restrctions, @@ -2216,7 +2266,7 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) /* * Apply restrictions in the order as specified. */ - state->recursion = 0; + state->recursion = 1; status = setjmp(smtpd_check_buf); if (status == 0 && etrn_restrctions->argc) status = generic_checks(state, etrn_restrctions, domain, @@ -2421,6 +2471,7 @@ char *var_virt_mailbox_maps; char *var_relocated_maps; char *var_local_rcpt_maps; char *var_perm_mx_networks; +char *var_par_dom_match; typedef struct { char *name; @@ -2442,7 +2493,8 @@ static STRING_TABLE string_table[] = { VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, - VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 0, 0, + VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, + VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, }; @@ -2780,13 +2832,17 @@ int main(int argc, char **argv) } if (strcasecmp(args->argv[0], "mynetworks") == 0) { namadr_list_free(mynetworks); - mynetworks = namadr_list_init(args->argv[1]); + mynetworks = + namadr_list_init(match_parent_style(VAR_MYNETWORKS), + args->argv[1]); resp = 0; break; } if (strcasecmp(args->argv[0], "relay_domains") == 0) { domain_list_free(relay_domains); - relay_domains = domain_list_init(args->argv[1]); + relay_domains = + domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + args->argv[1]); resp = 0; break; } diff --git a/postfix/src/smtpd/smtpd_check.in b/postfix/src/smtpd/smtpd_check.in index f7c3cdd70..44f969ce9 100644 --- a/postfix/src/smtpd/smtpd_check.in +++ b/postfix/src/smtpd/smtpd_check.in @@ -6,6 +6,7 @@ smtpd_delay_reject 0 mynetworks 127.0.0.0/8,168.100.189.0/28 relay_domains porcupine.org +maps_rbl_domains blackholes.mail-abuse.org # # Test the client restrictions. # diff --git a/postfix/src/smtpd/smtpd_check.in2 b/postfix/src/smtpd/smtpd_check.in2 index 0eaf8c02b..2b9000267 100644 --- a/postfix/src/smtpd/smtpd_check.in2 +++ b/postfix/src/smtpd/smtpd_check.in2 @@ -6,6 +6,7 @@ smtpd_delay_reject 0 mynetworks 127.0.0.0/8,168.100.189.0/28 relay_domains porcupine.org +maps_rbl_domains blackholes.mail-abuse.org # # Test the client restrictions. # diff --git a/postfix/src/smtpd/smtpd_check.ref b/postfix/src/smtpd/smtpd_check.ref index b63c3f705..121c9e32a 100644 --- a/postfix/src/smtpd/smtpd_check.ref +++ b/postfix/src/smtpd/smtpd_check.ref @@ -9,6 +9,8 @@ OK OK >>> relay_domains porcupine.org OK +>>> maps_rbl_domains blackholes.mail-abuse.org +OK >>> # >>> # Test the client restrictions. >>> # diff --git a/postfix/src/smtpd/smtpd_check.ref2 b/postfix/src/smtpd/smtpd_check.ref2 index c8d014f60..2bd382663 100644 --- a/postfix/src/smtpd/smtpd_check.ref2 +++ b/postfix/src/smtpd/smtpd_check.ref2 @@ -9,6 +9,8 @@ OK OK >>> relay_domains porcupine.org OK +>>> maps_rbl_domains blackholes.mail-abuse.org +OK >>> # >>> # Test the client restrictions. >>> # diff --git a/postfix/src/smtpd/smtpd_state.c b/postfix/src/smtpd/smtpd_state.c index ca4929634..6e7236543 100644 --- a/postfix/src/smtpd/smtpd_state.c +++ b/postfix/src/smtpd/smtpd_state.c @@ -91,6 +91,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream) state->recursion = 0; state->msg_size = 0; state->junk_cmds = 0; + state->warn_if_reject = 0; #ifdef USE_SASL_AUTH if (SMTPD_STAND_ALONE(state)) diff --git a/postfix/src/smtpstone/smtp-sink.c b/postfix/src/smtpstone/smtp-sink.c index 7eb997446..24a5e2784 100644 --- a/postfix/src/smtpstone/smtp-sink.c +++ b/postfix/src/smtpstone/smtp-sink.c @@ -28,6 +28,9 @@ /* Terminate after \fIcount\fR sessions. This is for testing purposes. /* .IP \fB-p\fR /* Disable ESMTP command pipelining. +/* .IP \fB-P\fR +/* Change the server greeting so that it appears to come through +/* a CISCO PIX system. /* .IP \fB-v\fR /* Show the SMTP conversations. /* .IP "\fB-w \fIdelay\fR" @@ -114,6 +117,7 @@ static int max_count; static int disable_pipelining; static int fixed_delay; static int enable_lmtp; +static int pretend_pix; /* ehlo_response - respond to EHLO command */ @@ -443,6 +447,9 @@ static void connect_event(int unused_event, char *context) state->read = command_read; state->data_state = ST_ANY; smtp_timeout_setup(state->stream, var_tmout); +if (pretend_pix) + smtp_printf(state->stream, "220 ********"); +else smtp_printf(state->stream, "220 %s ESMTP", var_myhostname); event_enable_read(fd, read_event, (char *) state); } @@ -452,7 +459,7 @@ static void connect_event(int unused_event, char *context) static void usage(char *myname) { - msg_fatal("usage: %s [-cLpv] [-n count] [-w delay] [host]:port backlog", myname); + msg_fatal("usage: %s [-cLpPv] [-n count] [-w delay] [host]:port backlog", myname); } int main(int argc, char **argv) @@ -469,7 +476,7 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "cLn:pvw:")) > 0) { + while ((ch = GETOPT(argc, argv, "cLn:pPvw:")) > 0) { switch (ch) { case 'c': count++; @@ -483,6 +490,9 @@ int main(int argc, char **argv) case 'p': disable_pipelining = 1; break; + case 'P': + pretend_pix=1; + break; case 'v': msg_verbose++; break; diff --git a/postfix/src/trivial-rewrite/transport.c b/postfix/src/trivial-rewrite/transport.c index baf55f699..379e2395f 100644 --- a/postfix/src/trivial-rewrite/transport.c +++ b/postfix/src/trivial-rewrite/transport.c @@ -62,12 +62,14 @@ #include #include +#include /* Application-specific. */ #include "transport.h" static MAPS *transport_path; +static int transport_match_parent_style; /* transport_init - pre-jail initialization */ @@ -77,6 +79,7 @@ void transport_init(void) msg_panic("transport_init: repeated call"); transport_path = maps_create("transport", var_transport_maps, DICT_FLAG_LOCK); + transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS); } /* transport_lookup - map a transport domain */ @@ -85,6 +88,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop) { char *low_domain = lowercase(mystrdup(domain)); const char *name; + const char *next; const char *value; const char *host; char *saved_value; @@ -113,7 +117,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop) * Specify if a key is partial or full, to avoid matching partial keys with * regular expressions. */ - for (name = low_domain; name != 0; name = strchr(name + 1, '.')) { + for (name = low_domain; /* void */; name = next) { if ((value = maps_find(transport_path, name, maps_flag)) != 0) { saved_value = mystrdup(value); if ((host = split_at(saved_value, ':')) == 0 || *host == 0) @@ -132,6 +136,10 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop) } else if (dict_errno != 0) { msg_fatal("transport table lookup problem"); } + if ((next = strchr(name + 1, '.')) == 0) + break; + if (transport_match_parent_style == MATCH_FLAG_PARENT) + next++; maps_flag = PARTIAL; } myfree(low_domain); diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index 3ed42dbfc..2b3c808eb 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -92,6 +92,10 @@ /* .sp /* Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5) /* for details. The :\fInexthop\fR part is optional. +/* .IP "\fBparent_domain_matches_subdomains\fR (versions >= 20011119)" +/* List of Postfix features that use \fIdomain.name\fR patterns +/* to match \fIsub.domain.name\fR (as opposed to +/* requiring \fI.domain.name\fR patterns). /* .IP \fBrelayhost\fR /* The default host to send non-local mail to when no entry is matched /* in the \fBtransport\fR(5) table. diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index b31dc93aa..eb0523dcd 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -23,8 +23,8 @@ SRCS = argv.c argv_split.c basename.c binhash.c chroot_uid.c \ clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \ sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \ hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \ - sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \ - attr_scan.c base64_code.c + sane_socketpair.c myrand.c netstring.c ctable.c attr_print64.c intv.c \ + attr_scan64.c base64_code.c sock_empty_wait.c attr_print0.c attr_scan0.c OBJS = argv.o argv_split.o basename.o binhash.o chroot_uid.o \ close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \ dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ @@ -49,8 +49,8 @@ OBJS = argv.o argv_split.o basename.o binhash.o chroot_uid.o \ clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \ sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \ hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \ - sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \ - attr_scan.o base64_code.o + sane_socketpair.o myrand.o netstring.o ctable.o attr_print64.o intv.o \ + attr_scan64.o base64_code.o sock_empty_wait.o attr_print0.o attr_scan0.o HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \ dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \ dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \ @@ -84,7 +84,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ mystrtok sigdelay translit valid_hostname vstream_popen \ vstring vstring_vstream doze select_bug stream_test mac_expand \ watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \ - inet_addr_list attr_print attr_scan base64_code + inet_addr_list attr_print64 attr_scan64 base64_code attr_print0 \ + attr_scan0 LIB_DIR = ../../lib INC_DIR = ../../include @@ -288,12 +289,12 @@ inet_addr_list: $(LIB) $@.o $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o -attr_print: $(LIB) $@.o +attr_print64: $(LIB) $@.o mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o -attr_scan: $(LIB) $@.o +attr_scan64: $(LIB) $@.o mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o @@ -303,6 +304,16 @@ base64_code: $(LIB) $@.o $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +attr_print0: $(LIB) $@.o + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + +attr_scan0: $(LIB) $@.o + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ @@ -316,7 +327,7 @@ stream_test: stream_test.c $(LIB) tests: valid_hostname_test mac_expand_test dict_test unescape_test \ hex_quote_test ctable_test inet_addr_list_test base64_code_test \ - attr_scan_test + attr_scan64_test attr_scan0_test valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref ./valid_hostname valid_hostname.tmp @@ -352,10 +363,15 @@ inet_addr_list_test: inet_addr_list base64_code_test: base64_code ./base64_code -attr_scan_test: attr_print attr_scan attr_scan.ref - (./attr_print 2>&3 | (sleep 1; ./attr_scan)) >attr_scan.tmp 2>&1 3>&1 - diff attr_scan.ref attr_scan.tmp - rm -f attr_scan.tmp +attr_scan64_test: attr_print64 attr_scan64 attr_scan64.ref + (./attr_print64 2>&3 | (sleep 1; ./attr_scan64)) >attr_scan64.tmp 2>&1 3>&1 + diff attr_scan64.ref attr_scan64.tmp + rm -f attr_scan64.tmp + +attr_scan0_test: attr_print0 attr_scan0 attr_scan0.ref + (./attr_print0 2>&3 | (sleep 1; ./attr_scan0)) >attr_scan0.tmp 2>&1 3>&1 + diff attr_scan0.ref attr_scan0.tmp + rm -f attr_scan0.tmp DB_TYPE = `../postconf/postconf -h default_database_type` @@ -391,6 +407,24 @@ attr_print.o: htable.h attr_print.o: base64_code.h attr_print.o: vstring.h attr_print.o: attr.h +attr_print0.o: attr_print0.c +attr_print0.o: sys_defs.h +attr_print0.o: msg.h +attr_print0.o: mymalloc.h +attr_print0.o: vstream.h +attr_print0.o: vbuf.h +attr_print0.o: htable.h +attr_print0.o: attr.h +attr_print64.o: attr_print64.c +attr_print64.o: sys_defs.h +attr_print64.o: msg.h +attr_print64.o: mymalloc.h +attr_print64.o: vstream.h +attr_print64.o: vbuf.h +attr_print64.o: htable.h +attr_print64.o: base64_code.h +attr_print64.o: vstring.h +attr_print64.o: attr.h attr_scan.o: attr_scan.c attr_scan.o: sys_defs.h attr_scan.o: msg.h @@ -401,6 +435,26 @@ attr_scan.o: vstring.h attr_scan.o: htable.h attr_scan.o: base64_code.h attr_scan.o: attr.h +attr_scan0.o: attr_scan0.c +attr_scan0.o: sys_defs.h +attr_scan0.o: msg.h +attr_scan0.o: mymalloc.h +attr_scan0.o: vstream.h +attr_scan0.o: vbuf.h +attr_scan0.o: vstring.h +attr_scan0.o: vstring_vstream.h +attr_scan0.o: htable.h +attr_scan0.o: attr.h +attr_scan64.o: attr_scan64.c +attr_scan64.o: sys_defs.h +attr_scan64.o: msg.h +attr_scan64.o: mymalloc.h +attr_scan64.o: vstream.h +attr_scan64.o: vbuf.h +attr_scan64.o: vstring.h +attr_scan64.o: htable.h +attr_scan64.o: base64_code.h +attr_scan64.o: attr.h base64_code.o: base64_code.c base64_code.o: sys_defs.h base64_code.o: msg.h @@ -782,6 +836,7 @@ match_list.o: vstring_vstream.h match_list.o: stringops.h match_list.o: argv.h match_list.o: dict.h +match_list.o: match_ops.h match_list.o: match_list.h match_ops.o: match_ops.c match_ops.o: sys_defs.h @@ -979,6 +1034,10 @@ skipblanks.o: sys_defs.h skipblanks.o: stringops.h skipblanks.o: vstring.h skipblanks.o: vbuf.h +sock_empty_wait.o: sock_empty_wait.c +sock_empty_wait.o: sys_defs.h +sock_empty_wait.o: msg.h +sock_empty_wait.o: iostuff.h spawn_command.o: spawn_command.c spawn_command.o: sys_defs.h spawn_command.o: msg.h diff --git a/postfix/src/util/attr.h b/postfix/src/util/attr.h index 1033b53b3..c656dadf8 100644 --- a/postfix/src/util/attr.h +++ b/postfix/src/util/attr.h @@ -28,6 +28,7 @@ #define ATTR_TYPE_NUM 1 /* Unsigned integer */ #define ATTR_TYPE_STR 2 /* Character string */ #define ATTR_TYPE_HASH 3 /* Hash table */ +#define ATTR_TYPE_LONG 4 /* Unsigned long */ /* * Flags that control processing. See attr_scan(3) for documentation. @@ -40,17 +41,34 @@ #define ATTR_FLAG_STRICT (ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA) #define ATTR_FLAG_ALL (07) +#define attr_print attr_print0 +#define attr_vprint attr_vprint0 +#define attr_scan attr_scan0 +#define attr_vscan attr_vscan0 + + /* + * attr_print64.c. + */ +extern int attr_print64(VSTREAM *, int,...); +extern int attr_vprint64(VSTREAM *, int, va_list); + + /* + * attr_scan64.c. + */ +extern int attr_scan64(VSTREAM *, int,...); +extern int attr_vscan64(VSTREAM *, int, va_list); + /* - * attr_print.c. + * attr_print0.c. */ -extern int attr_print(VSTREAM *, int,...); -extern int attr_vprint(VSTREAM *, int, va_list); +extern int attr_print0(VSTREAM *, int,...); +extern int attr_vprint0(VSTREAM *, int, va_list); /* - * attr_scan.c. + * attr_scan0.c. */ -extern int attr_scan(VSTREAM *, int,...); -extern int attr_vscan(VSTREAM *, int, va_list); +extern int attr_scan0(VSTREAM *, int,...); +extern int attr_vscan0(VSTREAM *, int, va_list); /* * Attribute names for testing the compatibility of the read and write @@ -59,6 +77,7 @@ extern int attr_vscan(VSTREAM *, int, va_list); #ifdef TEST #define ATTR_NAME_NUM "number" #define ATTR_NAME_STR "string" +#define ATTR_NAME_LONG "long_number" #endif /* LICENSE diff --git a/postfix/src/util/attr_print0.c b/postfix/src/util/attr_print0.c new file mode 100644 index 000000000..3678e2416 --- /dev/null +++ b/postfix/src/util/attr_print0.c @@ -0,0 +1,208 @@ +/*++ +/* NAME +/* attr_print0 3 +/* SUMMARY +/* send attributes over byte stream +/* SYNOPSIS +/* #include +/* +/* int attr_print0(fp, flags, type, name, ...) +/* VSTREAM fp; +/* int flags; +/* int type; +/* char *name; +/* +/* int attr_vprint0(fp, flags, ap) +/* VSTREAM fp; +/* int flags; +/* va_list ap; +/* DESCRIPTION +/* attr_print0() takes zero or more (name, value) simple attributes +/* or (name, count, value) list attributes, and converts its input +/* to a byte stream that can be recovered with attr_scan0(). The stream +/* is not flushed. +/* +/* attr_vprint0() provides an alternate interface that is convenient +/* for calling from within variadoc functions. +/* +/* Attributes are sent in the requested order as specified with the +/* attr_print0() argument list. This routine satisfies the formatting +/* rules as outlined in attr_scan0(3). +/* +/* Arguments: +/* .IP fp +/* Stream to write the result to. +/* .IP flags +/* The bit-wise OR of zero or more of the following. +/* .RS +/* .IP ATTR_FLAG_MORE +/* After sending the requested attributes, leave the output stream in +/* a state that is usable for more attribute sending operations on +/* the same output attribute list. +/* By default, attr_print0() automatically appends an attribute list +/* terminator when it has sent the last requested attribute. +/* .RE +/* .IP type +/* The type determines the arguments that follow. +/* .RS +/* .IP "ATTR_TYPE_NUM (char *, int)" +/* This argument is followed by an attribute name and an integer. +/* .IP "ATTR_TYPE_NUM (char *, long)" +/* This argument is followed by an attribute name and a long integer. +/* .IP "ATTR_TYPE_STR (char *, char *)" +/* This argument is followed by an attribute name and a null-terminated +/* string. +/* .IP "ATTR_TYPE_HASH (HTABLE *)" +/* The content of the hash table is sent as a sequence of string-valued +/* attributes with names equal to the hash table lookup key. +/* .IP ATTR_TYPE_END +/* This terminates the attribute list. +/* .RE +/* DIAGNOSTICS +/* The result value is 0 in case of success, VSTREAM_EOF in case +/* of trouble. +/* +/* Panic: interface violation. All system call errors are fatal. +/* SEE ALSO +/* attr_scan0(3) recover attributes from byte stream +/* 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 +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include + +/* attr_vprint0 - send attribute list to stream */ + +int attr_vprint0(VSTREAM *fp, int flags, va_list ap) +{ + const char *myname = "attr_print0"; + int attr_type; + char *attr_name; + unsigned int_val; + unsigned long long_val; + char *str_val; + HTABLE_INFO **ht_info_list; + HTABLE_INFO **ht; + + /* + * Sanity check. + */ + if (flags & ~ATTR_FLAG_ALL) + msg_panic("%s: bad flags: 0x%x", myname, flags); + + /* + * Iterate over all (type, name, value) triples, and produce output on + * the fly. + */ + while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { + switch (attr_type) { + case ATTR_TYPE_NUM: + attr_name = va_arg(ap, char *); + vstream_fwrite(fp, attr_name, strlen(attr_name) + 1); + int_val = va_arg(ap, int); + vstream_fprintf(fp, "%u", (unsigned) int_val); + VSTREAM_PUTC('\0', fp); + if (msg_verbose) + msg_info("send attr %s = %u", attr_name, int_val); + break; + case ATTR_TYPE_LONG: + attr_name = va_arg(ap, char *); + vstream_fwrite(fp, attr_name, strlen(attr_name) + 1); + long_val = va_arg(ap, unsigned long); + vstream_fprintf(fp, "%lu", (unsigned long) long_val); + VSTREAM_PUTC('\0', fp); + if (msg_verbose) + msg_info("send attr %s = %lu", attr_name, long_val); + break; + case ATTR_TYPE_STR: + attr_name = va_arg(ap, char *); + vstream_fwrite(fp, attr_name, strlen(attr_name) + 1); + str_val = va_arg(ap, char *); + vstream_fwrite(fp, str_val, strlen(str_val) + 1); + if (msg_verbose) + msg_info("send attr %s = %s", attr_name, str_val); + break; + case ATTR_TYPE_HASH: + ht_info_list = htable_list(va_arg(ap, HTABLE *)); + for (ht = ht_info_list; *ht; ht++) { + vstream_fwrite(fp, ht[0]->key, strlen(ht[0]->key) + 1); + vstream_fwrite(fp, ht[0]->value, strlen(ht[0]->value) + 1); + if (msg_verbose) + msg_info("send attr name %s value %s", + ht[0]->key, ht[0]->value); + } + myfree((char *) ht_info_list); + break; + default: + msg_panic("%s: unknown type code: %d", myname, attr_type); + } + } + if ((flags & ATTR_FLAG_MORE) == 0) + VSTREAM_PUTC('\0', fp); + return (vstream_ferror(fp)); +} + +int attr_print0(VSTREAM *fp, int flags,...) +{ + va_list ap; + int ret; + + va_start(ap, flags); + ret = attr_vprint0(fp, flags, ap); + va_end(ap); + return (ret); +} + +#ifdef TEST + + /* + * Proof of concept test program. Mirror image of the attr_scan0 test + * program. + */ +#include + +int main(int unused_argc, char **argv) +{ + HTABLE *table = htable_create(1); + + msg_vstream_init(argv[0], VSTREAM_ERR); + msg_verbose = 1; + htable_enter(table, "foo-name", mystrdup("foo-value")); + htable_enter(table, "bar-name", mystrdup("bar-value")); + attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, + ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", + ATTR_TYPE_HASH, table, + ATTR_TYPE_END); + attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, + ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", + ATTR_TYPE_END); + if (vstream_fflush(VSTREAM_OUT) != 0) + msg_fatal("write error: %m"); + + htable_free(table, myfree); + return (0); +} + +#endif diff --git a/postfix/src/util/attr_print.c b/postfix/src/util/attr_print64.c similarity index 63% rename from postfix/src/util/attr_print.c rename to postfix/src/util/attr_print64.c index fe38ea6fd..2c64c06d7 100644 --- a/postfix/src/util/attr_print.c +++ b/postfix/src/util/attr_print64.c @@ -1,33 +1,33 @@ /*++ /* NAME -/* attr_print 3 +/* attr_print64 3 /* SUMMARY /* send attributes over byte stream /* SYNOPSIS /* #include /* -/* int attr_print(fp, flags, type, name, ...) +/* int attr_print64(fp, flags, type, name, ...) /* VSTREAM fp; /* int flags; /* int type; /* char *name; /* -/* int attr_vprint(fp, flags, ap) +/* int attr_vprint64(fp, flags, ap) /* VSTREAM fp; /* int flags; /* va_list ap; /* DESCRIPTION -/* attr_print() takes zero or more (name, value) simple attributes +/* attr_print64() takes zero or more (name, value) simple attributes /* or (name, count, value) list attributes, and converts its input -/* to a byte stream that can be recovered with attr_scan(). The stream +/* to a byte stream that can be recovered with attr_scan64(). The stream /* is not flushed. /* -/* attr_vprint() provides an alternate interface that is convenient +/* attr_vprint64() provides an alternate interface that is convenient /* for calling from within variadoc functions. /* /* Attributes are sent in the requested order as specified with the -/* attr_print() argument list. This routine satisfies the formatting -/* rules as outlined in attr_scan(3). +/* attr_print64() argument list. This routine satisfies the formatting +/* rules as outlined in attr_scan64(3). /* /* Arguments: /* .IP fp @@ -39,7 +39,7 @@ /* After sending the requested attributes, leave the output stream in /* a state that is usable for more attribute sending operations on /* the same output attribute list. -/* By default, attr_print() automatically appends an attribute list +/* By default, attr_print64() automatically appends an attribute list /* terminator when it has sent the last requested attribute. /* .RE /* .IP type @@ -47,6 +47,8 @@ /* .RS /* .IP "ATTR_TYPE_NUM (char *, int)" /* This argument is followed by an attribute name and an integer. +/* .IP "ATTR_TYPE_NUM (char *, long)" +/* This argument is followed by an attribute name and a long integer. /* .IP "ATTR_TYPE_STR (char *, char *)" /* This argument is followed by an attribute name and a null-terminated /* string. @@ -62,7 +64,7 @@ /* /* Panic: interface violation. All system call errors are fatal. /* SEE ALSO -/* attr_scan(3) recover attributes from byte stream +/* attr_scan64(3) recover attributes from byte stream /* LICENSE /* .ad /* .fi @@ -91,9 +93,9 @@ #define STR(x) vstring_str(x) #define LEN(x) VSTRING_LEN(x) -/* attr_print_str - encode and send attribute information */ +/* attr_print64_str - encode and send attribute information */ -static void attr_print_str(VSTREAM *fp, const char *str, int len) +static void attr_print64_str(VSTREAM *fp, const char *str, int len) { static VSTRING *base64_buf; @@ -104,7 +106,7 @@ static void attr_print_str(VSTREAM *fp, const char *str, int len) vstream_fputs(STR(base64_buf), fp); } -static void attr_print_num(VSTREAM *fp, unsigned num) +static void attr_print64_num(VSTREAM *fp, unsigned num) { static VSTRING *plain; @@ -112,17 +114,29 @@ static void attr_print_num(VSTREAM *fp, unsigned num) plain = vstring_alloc(10); vstring_sprintf(plain, "%u", num); - attr_print_str(fp, STR(plain), LEN(plain)); + attr_print64_str(fp, STR(plain), LEN(plain)); } -/* attr_vprint - send attribute list to stream */ +static void attr_print64_long_num(VSTREAM *fp, unsigned long long_num) +{ + static VSTRING *plain; + + if (plain == 0) + plain = vstring_alloc(10); + + vstring_sprintf(plain, "%lu", long_num); + attr_print64_str(fp, STR(plain), LEN(plain)); +} + +/* attr_vprint64 - send attribute list to stream */ -int attr_vprint(VSTREAM *fp, int flags, va_list ap) +int attr_vprint64(VSTREAM *fp, int flags, va_list ap) { - const char *myname = "attr_print"; + const char *myname = "attr_print64"; int attr_type; char *attr_name; unsigned int_val; + unsigned long long_val; char *str_val; HTABLE_INFO **ht_info_list; HTABLE_INFO **ht; @@ -141,28 +155,37 @@ int attr_vprint(VSTREAM *fp, int flags, va_list ap) switch (attr_type) { case ATTR_TYPE_NUM: attr_name = va_arg(ap, char *); - attr_print_str(fp, attr_name, strlen(attr_name)); + attr_print64_str(fp, attr_name, strlen(attr_name)); int_val = va_arg(ap, int); VSTREAM_PUTC(':', fp); - attr_print_num(fp, (unsigned) int_val); + attr_print64_num(fp, (unsigned) int_val); if (msg_verbose) msg_info("send attr %s = %u", attr_name, int_val); break; + case ATTR_TYPE_LONG: + attr_name = va_arg(ap, char *); + attr_print64_str(fp, attr_name, strlen(attr_name)); + long_val = va_arg(ap, long); + VSTREAM_PUTC(':', fp); + attr_print64_long_num(fp, (unsigned long) long_val); + if (msg_verbose) + msg_info("send attr %s = %lu", attr_name, long_val); + break; case ATTR_TYPE_STR: attr_name = va_arg(ap, char *); - attr_print_str(fp, attr_name, strlen(attr_name)); + attr_print64_str(fp, attr_name, strlen(attr_name)); str_val = va_arg(ap, char *); VSTREAM_PUTC(':', fp); - attr_print_str(fp, str_val, strlen(str_val)); + attr_print64_str(fp, str_val, strlen(str_val)); if (msg_verbose) msg_info("send attr %s = %s", attr_name, str_val); break; case ATTR_TYPE_HASH: ht_info_list = htable_list(va_arg(ap, HTABLE *)); for (ht = ht_info_list; *ht; ht++) { - attr_print_str(fp, ht[0]->key, strlen(ht[0]->key)); + attr_print64_str(fp, ht[0]->key, strlen(ht[0]->key)); VSTREAM_PUTC(':', fp); - attr_print_str(fp, ht[0]->value, strlen(ht[0]->value)); + attr_print64_str(fp, ht[0]->value, strlen(ht[0]->value)); if (msg_verbose) msg_info("send attr name %s value %s", ht[0]->key, ht[0]->value); @@ -181,13 +204,13 @@ int attr_vprint(VSTREAM *fp, int flags, va_list ap) return (vstream_ferror(fp)); } -int attr_print(VSTREAM *fp, int flags,...) +int attr_print64(VSTREAM *fp, int flags,...) { va_list ap; int ret; va_start(ap, flags); - ret = attr_vprint(fp, flags, ap); + ret = attr_vprint64(fp, flags, ap); va_end(ap); return (ret); } @@ -195,7 +218,7 @@ int attr_print(VSTREAM *fp, int flags,...) #ifdef TEST /* - * Proof of concept test program. Mirror image of the attr_scan test + * Proof of concept test program. Mirror image of the attr_scan64 test * program. */ #include @@ -208,15 +231,17 @@ int main(int unused_argc, char **argv) msg_verbose = 1; htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); - attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, - ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", - ATTR_TYPE_HASH, table, - ATTR_TYPE_END); - attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, - ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", - ATTR_TYPE_END); + attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, + ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", + ATTR_TYPE_HASH, table, + ATTR_TYPE_END); + attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, + ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", + ATTR_TYPE_END); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_scan0.c b/postfix/src/util/attr_scan0.c new file mode 100644 index 000000000..9ec37591a --- /dev/null +++ b/postfix/src/util/attr_scan0.c @@ -0,0 +1,440 @@ +/*++ +/* NAME +/* attr_scan0 3 +/* SUMMARY +/* recover attributes from byte stream +/* SYNOPSIS +/* #include +/* +/* int attr_scan0(fp, flags, type, name, ...) +/* VSTREAM fp; +/* int flags; +/* int type; +/* char *name; +/* +/* int attr_vscan0(fp, flags, ap) +/* VSTREAM fp; +/* int flags; +/* va_list ap; +/* DESCRIPTION +/* attr_scan0() takes zero or more (name, value) request attributes +/* and recovers the attribute values from the byte stream that was +/* possibly generated by attr_print0(). +/* +/* attr_vscan0() provides an alternative interface that is convenient +/* for calling from within a variadic function. +/* +/* The input stream is formatted as follows, where (item)* stands +/* for zero or more instances of the specified item, and where +/* (item1 | item2) stands for choice: +/* +/* .in +5 +/* attr-list :== simple-attr* null +/* .br +/* simple-attr :== attr-name null attr-value null +/* .br +/* attr-name :== any string not containing null +/* .br +/* attr-value :== any string not containing null +/* .br +/* null :== the ASCII null character +/* .in +/* +/* All attribute names and attribute values are sent as null terminated +/* strings. Each string must be no longer than 2*var_line_limit +/* characters. The formatting rules favor implementations in C. +/* +/* Normally, attributes must be received in the sequence as specified with +/* the attr_scan0() argument list. The input stream may contain additional +/* attributes at any point in the input stream, including additional +/* instances of requested attributes. +/* +/* Additional input attributes or input attribute instances are silently +/* skipped over, unless the ATTR_FLAG_EXTRA processing flag is specified +/* (see below). This allows for some flexibility in the evolution of +/* protocols while still providing the option of being strict where +/* this is desirable. +/* +/* Arguments: +/* .IP fp +/* Stream to recover the input attributes from. +/* .IP flags +/* The bit-wise OR of zero or more of the following. +/* .RS +/* .IP ATTR_FLAG_MISSING +/* Log a warning when the input attribute list terminates before all +/* requested attributes are recovered. It is always an error when the +/* input stream ends without the newline attribute list terminator. +/* .IP ATTR_FLAG_EXTRA +/* Log a warning and stop attribute recovery when the input stream +/* contains an attribute that was not requested. This includes the +/* case of additional instances of a requested attribute. +/* .IP ATTR_FLAG_MORE +/* After recovering the requested attributes, leave the input stream +/* in a state that is usable for more attr_scan0() operations from the +/* same input attribute list. +/* By default, attr_scan0() skips forward past the input attribute list +/* terminator. +/* .IP ATTR_FLAG_STRICT +/* For convenience, this value combines both ATTR_FLAG_MISSING and +/* ATTR_FLAG_EXTRA. +/* .IP ATTR_FLAG_NONE +/* For convenience, this value requests none of the above. +/* .RE +/* .IP type +/* The type argument determines the arguments that follow. +/* .RS +/* .IP "ATTR_TYPE_NUM (char *, int *)" +/* This argument is followed by an attribute name and an integer pointer. +/* .IP "ATTR_TYPE_LONG (char *, long *)" +/* This argument is followed by an attribute name and a long pointer. +/* .IP "ATTR_TYPE_STR (char *, VSTRING *)" +/* This argument is followed by an attribute name and a VSTRING pointer. +/* .IP "ATTR_TYPE_HASH (HTABLE *)" +/* All further input attributes are processed as string attributes. +/* No specific attribute sequence is enforced. +/* All attributes up to the attribute list terminator are read, +/* but only the first instance of each attribute is stored. +/* .sp +/* The attribute string values are stored in the hash table under +/* keys equal to the attribute name (obtained from the input stream). +/* Values from the input stream are added to the hash table. Existing +/* hash table entries are not replaced. +/* .sp +/* N.B. This construct must be followed by an ATTR_TYPE_END argument. +/* .IP ATTR_TYPE_END +/* This argument terminates the requested attribute list. +/* .RE +/* BUGS +/* ATTR_TYPE_HASH accepts attributes with arbitrary names from possibly +/* untrusted sources. This is unsafe, unless the resulting table is +/* queried only with known to be good attribute names. +/* DIAGNOSTICS +/* attr_scan0() and attr_vscan0() return -1 when malformed input is +/* detected (string too long, incomplete line, missing end marker). +/* Otherwise, the result value is the number of attributes that were +/* successfully recovered from the input stream (a hash table counts +/* as the number of entries stored into the table). +/* +/* Panic: interface violation. All system call errors are fatal. +/* SEE ALSO +/* attr_print0(3) send attributes over byte stream. +/* 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 +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include +#include + +/* Application specific. */ + +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + +/* attr_scan0_string - pull a string from the input stream */ + +static int attr_scan0_string(VSTREAM *fp, VSTRING *plain_buf, const char *context) +{ + extern int var_line_limit; /* XXX */ + int limit = var_line_limit * 2; + int ch; + + if ((ch = vstring_get_null(plain_buf, fp)) == VSTREAM_EOF) { + msg_warn("premature end-of-input from %s while reading %s", + VSTREAM_PATH(fp), context); + return (-1); + } + if (ch != 0) { + msg_warn("string length > %d characters from %s while reading %s", + limit, VSTREAM_PATH(fp), context); + return (-1); + } + if (msg_verbose) + msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)"); + return (ch); +} + +/* attr_scan0_number - pull a number from the input stream */ + +static int attr_scan0_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf, + const char *context) +{ + char junk = 0; + int ch; + + if ((ch = attr_scan0_string(fp, str_buf, context)) < 0) + return (-1); + if (sscanf(STR(str_buf), "%u%c", ptr, &junk) != 1 || junk != 0) { + msg_warn("malformed numerical data from %s while reading %s: %.100s", + VSTREAM_PATH(fp), context, STR(str_buf)); + return (-1); + } + return (ch); +} + +/* attr_scan0_long_number - pull a number from the input stream */ + +static int attr_scan0_long_number(VSTREAM *fp, unsigned long *ptr, + VSTRING *str_buf, + const char *context) +{ + char junk = 0; + int ch; + + if ((ch = attr_scan0_string(fp, str_buf, context)) < 0) + return (-1); + if (sscanf(STR(str_buf), "%lu%c", ptr, &junk) != 1 || junk != 0) { + msg_warn("malformed numerical data from %s while reading %s: %.100s", + VSTREAM_PATH(fp), context, STR(str_buf)); + return (-1); + } + return (ch); +} + +/* attr_vscan0 - receive attribute list from stream */ + +int attr_vscan0(VSTREAM *fp, int flags, va_list ap) +{ + const char *myname = "attr_scan0"; + static VSTRING *str_buf = 0; + static VSTRING *name_buf = 0; + int wanted_type = -1; + char *wanted_name; + unsigned int *number; + unsigned long *long_number; + VSTRING *string; + HTABLE *hash_table; + int ch; + int conversions; + + /* + * Sanity check. + */ + if (flags & ~ATTR_FLAG_ALL) + msg_panic("%s: bad flags: 0x%x", myname, flags); + + /* + * Initialize. + */ + if (str_buf == 0) { + str_buf = vstring_alloc(10); + name_buf = vstring_alloc(10); + } + + /* + * Iterate over all (type, name, value) triples. + */ + for (conversions = 0; /* void */ ; conversions++) { + + /* + * Determine the next attribute type and attribute name on the + * caller's wish list. + * + * If we're reading into a hash table, we already know that the + * attribute value is string-valued, and we get the attribute name + * from the input stream instead. This is secure only when the + * resulting table is queried with known to be good attribute names. + */ + if (wanted_type != ATTR_TYPE_HASH) { + wanted_type = va_arg(ap, int); + if (wanted_type == ATTR_TYPE_END) { + if ((flags & ATTR_FLAG_MORE) != 0) + return (conversions); + wanted_name = "(list terminator)"; + } else if (wanted_type == ATTR_TYPE_HASH) { + wanted_name = "(any attribute name or list terminator)"; + hash_table = va_arg(ap, HTABLE *); + if (va_arg(ap, int) !=ATTR_TYPE_END) + msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END", + myname); + } else { + wanted_name = va_arg(ap, char *); + } + } + + /* + * Locate the next attribute of interest in the input stream. + */ + for (;;) { + + /* + * Get the name of the next attribute. Hitting EOF is always bad. + * Hitting the end-of-input early is OK if the caller is prepared + * to deal with missing inputs. + */ + if (msg_verbose) + msg_info("%s: wanted attribute: %s", + VSTREAM_PATH(fp), wanted_name); + if ((ch = attr_scan0_string(fp, name_buf, + "input attribute name")) == VSTREAM_EOF) + return (-1); + if (LEN(name_buf) == 0) { + if (wanted_type == ATTR_TYPE_END + || wanted_type == ATTR_TYPE_HASH) + return (conversions); + if ((flags & ATTR_FLAG_MISSING) != 0) + msg_warn("missing attribute %s in input from %s", + wanted_name, VSTREAM_PATH(fp)); + return (conversions); + } + + /* + * See if the caller asks for this attribute. + */ + if (wanted_type == ATTR_TYPE_HASH + || (wanted_type != ATTR_TYPE_END + && strcmp(wanted_name, STR(name_buf)) == 0)) + break; + if ((flags & ATTR_FLAG_EXTRA) != 0) { + msg_warn("spurious attribute %s in input from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (conversions); + } + + /* + * Skip over this attribute. The caller does not ask for it. + */ + (void) attr_scan0_string(fp, str_buf, "input attribute value"); + } + + /* + * Do the requested conversion. + */ + switch (wanted_type) { + case ATTR_TYPE_NUM: + number = va_arg(ap, unsigned int *); + if ((ch = attr_scan0_number(fp, number, str_buf, + "input attribute value")) < 0) + return (-1); + break; + case ATTR_TYPE_LONG: + long_number = va_arg(ap, unsigned long *); + if ((ch = attr_scan0_long_number(fp, long_number, str_buf, + "input attribute value")) < 0) + return (-1); + break; + case ATTR_TYPE_STR: + string = va_arg(ap, VSTRING *); + if ((ch = attr_scan0_string(fp, string, + "input attribute value")) < 0) + return (-1); + break; + case ATTR_TYPE_HASH: + if ((ch = attr_scan0_string(fp, str_buf, + "input attribute value")) < 0) + return (-1); + if (htable_locate(hash_table, STR(name_buf)) != 0) { + if ((flags & ATTR_FLAG_EXTRA) != 0) { + msg_warn("duplicate attribute %s in input from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (conversions); + } + } else { + htable_enter(hash_table, STR(name_buf), + mystrdup(STR(str_buf))); + } + break; + default: + msg_panic("%s: unknown type code: %d", myname, wanted_type); + } + } +} + +/* attr_scan0 - read attribute list from stream */ + +int attr_scan0(VSTREAM *fp, int flags,...) +{ + va_list ap; + int ret; + + va_start(ap, flags); + ret = attr_vscan0(fp, flags, ap); + va_end(ap); + return (ret); +} + +#ifdef TEST + + /* + * Proof of concept test program. Mirror image of the attr_scan0 test + * program. + */ +#include + +int var_line_limit = 2048; + +int main(int unused_argc, char **used_argv) +{ + VSTRING *str_val = vstring_alloc(1); + HTABLE *table = htable_create(1); + HTABLE_INFO **ht_info_list; + HTABLE_INFO **ht; + int int_val; + long long_val; + int ret; + + msg_verbose = 1; + msg_vstream_init(used_argv[0], VSTREAM_ERR); + if ((ret = attr_scan0(VSTREAM_IN, + ATTR_FLAG_STRICT, + ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, + ATTR_TYPE_STR, ATTR_NAME_STR, str_val, + ATTR_TYPE_HASH, table, + ATTR_TYPE_END)) > 3) { + vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); + vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); + ht_info_list = htable_list(table); + for (ht = ht_info_list; *ht; ht++) + vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value); + myfree((char *) ht_info_list); + } else { + vstream_printf("return: %d\n", ret); + } + if ((ret = attr_scan0(VSTREAM_IN, + ATTR_FLAG_STRICT, + ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, + ATTR_TYPE_STR, ATTR_NAME_STR, str_val, + ATTR_TYPE_END)) == 3) { + vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); + vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); + ht_info_list = htable_list(table); + for (ht = ht_info_list; *ht; ht++) + vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value); + myfree((char *) ht_info_list); + } else { + vstream_printf("return: %d\n", ret); + } + if (vstream_fflush(VSTREAM_OUT) != 0) + msg_fatal("write error: %m"); + + vstring_free(str_val); + htable_free(table, myfree); + + return (0); +} + +#endif diff --git a/postfix/src/util/attr_scan0.ref b/postfix/src/util/attr_scan0.ref new file mode 100644 index 000000000..105382fd1 --- /dev/null +++ b/postfix/src/util/attr_scan0.ref @@ -0,0 +1,46 @@ +./attr_print0: send attr number = 4711 +./attr_print0: send attr long_number = 1234 +./attr_print0: send attr string = whoopee +./attr_print0: send attr name foo-name value foo-value +./attr_print0: send attr name bar-name value bar-value +./attr_print0: send attr number = 4711 +./attr_print0: send attr long_number = 1234 +./attr_print0: send attr string = whoopee +./attr_scan0: unknown_stream: wanted attribute: number +./attr_scan0: input attribute name: number +./attr_scan0: input attribute value: 4711 +./attr_scan0: unknown_stream: wanted attribute: long_number +./attr_scan0: input attribute name: long_number +./attr_scan0: input attribute value: 1234 +./attr_scan0: unknown_stream: wanted attribute: string +./attr_scan0: input attribute name: string +./attr_scan0: input attribute value: whoopee +./attr_scan0: unknown_stream: wanted attribute: (any attribute name or list terminator) +./attr_scan0: input attribute name: foo-name +./attr_scan0: input attribute value: foo-value +./attr_scan0: unknown_stream: wanted attribute: (any attribute name or list terminator) +./attr_scan0: input attribute name: bar-name +./attr_scan0: input attribute value: bar-value +./attr_scan0: unknown_stream: wanted attribute: (any attribute name or list terminator) +./attr_scan0: input attribute name: (end) +./attr_scan0: unknown_stream: wanted attribute: number +./attr_scan0: input attribute name: number +./attr_scan0: input attribute value: 4711 +./attr_scan0: unknown_stream: wanted attribute: long_number +./attr_scan0: input attribute name: long_number +./attr_scan0: input attribute value: 1234 +./attr_scan0: unknown_stream: wanted attribute: string +./attr_scan0: input attribute name: string +./attr_scan0: input attribute value: whoopee +./attr_scan0: unknown_stream: wanted attribute: (list terminator) +./attr_scan0: input attribute name: (end) +number 4711 +long_number 1234 +string whoopee +(hash) foo-name foo-value +(hash) bar-name bar-value +number 4711 +long_number 1234 +string whoopee +(hash) foo-name foo-value +(hash) bar-name bar-value diff --git a/postfix/src/util/attr_scan.c b/postfix/src/util/attr_scan64.c similarity index 77% rename from postfix/src/util/attr_scan.c rename to postfix/src/util/attr_scan64.c index 94e4c4ff9..786ba483e 100644 --- a/postfix/src/util/attr_scan.c +++ b/postfix/src/util/attr_scan64.c @@ -1,27 +1,27 @@ /*++ /* NAME -/* attr_scan 3 +/* attr_scan64 3 /* SUMMARY /* recover attributes from byte stream /* SYNOPSIS /* #include /* -/* int attr_scan(fp, flags, type, name, ...) +/* int attr_scan64(fp, flags, type, name, ...) /* VSTREAM fp; /* int flags; /* int type; /* char *name; /* -/* int attr_vscan(fp, flags, ap) +/* int attr_vscan64(fp, flags, ap) /* VSTREAM fp; /* int flags; /* va_list ap; /* DESCRIPTION -/* attr_scan() takes zero or more (name, value) request attributes +/* attr_scan64() takes zero or more (name, value) request attributes /* and recovers the attribute values from the byte stream that was -/* possibly generated by attr_print(). +/* possibly generated by attr_print64(). /* -/* attr_vscan() provides an alternative interface that is convenient +/* attr_vscan64() provides an alternative interface that is convenient /* for calling from within a variadic function. /* /* The input stream is formatted as follows, where (item)* stands @@ -47,9 +47,9 @@ /* characters. The formatting rules aim to make implementations in PERL /* and other languages easy. /* -/* Normally, attributes must be received in the sequence as specified with -/* the attr_scan() argument list. The input stream may contain additional -/* attributes at any point in the input stream, including additional +/* Normally, attributes must be received in the sequence as specified with +/* the attr_scan64() argument list. The input stream may contain additional +/* attributes at any point in the input stream, including additional /* instances of requested attributes. /* /* Additional input attributes or input attribute instances are silently @@ -74,9 +74,9 @@ /* case of additional instances of a requested attribute. /* .IP ATTR_FLAG_MORE /* After recovering the requested attributes, leave the input stream -/* in a state that is usable for more attr_scan() operations from the +/* in a state that is usable for more attr_scan64() operations from the /* same input attribute list. -/* By default, attr_scan() skips forward past the input attribute list +/* By default, attr_scan64() skips forward past the input attribute list /* terminator. /* .IP ATTR_FLAG_STRICT /* For convenience, this value combines both ATTR_FLAG_MISSING and @@ -89,6 +89,8 @@ /* .RS /* .IP "ATTR_TYPE_NUM (char *, int *)" /* This argument is followed by an attribute name and an integer pointer. +/* .IP "ATTR_TYPE_LONG (char *, long *)" +/* This argument is followed by an attribute name and a long pointer. /* .IP "ATTR_TYPE_STR (char *, VSTRING *)" /* This argument is followed by an attribute name and a VSTRING pointer. /* .IP "ATTR_TYPE_HASH (HTABLE *)" @@ -111,7 +113,7 @@ /* untrusted sources. This is unsafe, unless the resulting table is /* queried only with known to be good attribute names. /* DIAGNOSTICS -/* attr_scan() and attr_vscan() return -1 when malformed input is +/* attr_scan64() and attr_vscan64() return -1 when malformed input is /* detected (string too long, incomplete line, missing end marker). /* Otherwise, the result value is the number of attributes that were /* successfully recovered from the input stream (a hash table counts @@ -119,7 +121,7 @@ /* /* Panic: interface violation. All system call errors are fatal. /* SEE ALSO -/* attr_print(3) send attributes over byte stream. +/* attr_print64(3) send attributes over byte stream. /* LICENSE /* .ad /* .fi @@ -152,9 +154,9 @@ #define STR(x) vstring_str(x) #define LEN(x) VSTRING_LEN(x) -/* attr_scan_string - pull a string from the input stream */ +/* attr_scan64_string - pull a string from the input stream */ -static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context) +static int attr_scan64_string(VSTREAM *fp, VSTRING *plain_buf, const char *context) { static VSTRING *base64_buf = 0; extern int var_line_limit; /* XXX */ @@ -191,15 +193,15 @@ static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context return (ch); } -/* attr_scan_number - pull a number from the input stream */ +/* attr_scan64_number - pull a number from the input stream */ -static int attr_scan_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf, - const char *context) +static int attr_scan64_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf, + const char *context) { char junk = 0; int ch; - if ((ch = attr_scan_string(fp, str_buf, context)) < 0) + if ((ch = attr_scan64_string(fp, str_buf, context)) < 0) return (-1); if (sscanf(STR(str_buf), "%u%c", ptr, &junk) != 1 || junk != 0) { msg_warn("malformed numerical data from %s while reading %s: %.100s", @@ -209,16 +211,36 @@ static int attr_scan_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf, return (ch); } -/* attr_vscan - receive attribute list from stream */ +/* attr_scan64_long_number - pull a number from the input stream */ -int attr_vscan(VSTREAM *fp, int flags, va_list ap) +static int attr_scan64_long_number(VSTREAM *fp, unsigned long *ptr, + VSTRING *str_buf, + const char *context) { - const char *myname = "attr_scan"; + char junk = 0; + int ch; + + if ((ch = attr_scan64_string(fp, str_buf, context)) < 0) + return (-1); + if (sscanf(STR(str_buf), "%lu%c", ptr, &junk) != 1 || junk != 0) { + msg_warn("malformed numerical data from %s while reading %s: %.100s", + VSTREAM_PATH(fp), context, STR(str_buf)); + return (-1); + } + return (ch); +} + +/* attr_vscan64 - receive attribute list from stream */ + +int attr_vscan64(VSTREAM *fp, int flags, va_list ap) +{ + const char *myname = "attr_scan64"; static VSTRING *str_buf = 0; static VSTRING *name_buf = 0; int wanted_type = -1; char *wanted_name; unsigned int *number; + unsigned long *long_number; VSTRING *string; HTABLE *hash_table; int ch; @@ -282,7 +304,7 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap) if (msg_verbose) msg_info("%s: wanted attribute: %s", VSTREAM_PATH(fp), wanted_name); - if ((ch = attr_scan_string(fp, name_buf, + if ((ch = attr_scan64_string(fp, name_buf, "input attribute name")) == VSTREAM_EOF) return (-1); if (ch == '\n' && LEN(name_buf) == 0) { @@ -331,8 +353,24 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap) return (-1); } number = va_arg(ap, unsigned int *); - if ((ch = attr_scan_number(fp, number, str_buf, - "input attribute value")) < 0) + if ((ch = attr_scan64_number(fp, number, str_buf, + "input attribute value")) < 0) + return (-1); + if (ch != '\n') { + msg_warn("multiple values for attribute %s from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (-1); + } + break; + case ATTR_TYPE_LONG: + if (ch != ':') { + msg_warn("missing value for number attribute %s from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (-1); + } + long_number = va_arg(ap, unsigned long *); + if ((ch = attr_scan64_long_number(fp, long_number, str_buf, + "input attribute value")) < 0) return (-1); if (ch != '\n') { msg_warn("multiple values for attribute %s from %s", @@ -347,8 +385,8 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap) return (-1); } string = va_arg(ap, VSTRING *); - if ((ch = attr_scan_string(fp, string, - "input attribute value")) < 0) + if ((ch = attr_scan64_string(fp, string, + "input attribute value")) < 0) return (-1); if (ch != '\n') { msg_warn("multiple values for attribute %s from %s", @@ -362,8 +400,8 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap) STR(name_buf), VSTREAM_PATH(fp)); return (-1); } - if ((ch = attr_scan_string(fp, str_buf, - "input attribute value")) < 0) + if ((ch = attr_scan64_string(fp, str_buf, + "input attribute value")) < 0) return (-1); if (ch != '\n') { msg_warn("multiple values for attribute %s from %s", @@ -387,15 +425,15 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap) } } -/* attr_scan - read attribute list from stream */ +/* attr_scan64 - read attribute list from stream */ -int attr_scan(VSTREAM *fp, int flags,...) +int attr_scan64(VSTREAM *fp, int flags,...) { va_list ap; int ret; va_start(ap, flags); - ret = attr_vscan(fp, flags, ap); + ret = attr_vscan64(fp, flags, ap); va_end(ap); return (ret); } @@ -403,7 +441,7 @@ int attr_scan(VSTREAM *fp, int flags,...) #ifdef TEST /* - * Proof of concept test program. Mirror image of the attr_scan test + * Proof of concept test program. Mirror image of the attr_scan64 test * program. */ #include @@ -417,17 +455,20 @@ int main(int unused_argc, char **used_argv) HTABLE_INFO **ht_info_list; HTABLE_INFO **ht; int int_val; + long long_val; int ret; msg_verbose = 1; msg_vstream_init(used_argv[0], VSTREAM_ERR); - if ((ret = attr_scan(VSTREAM_IN, - ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, - ATTR_TYPE_STR, ATTR_NAME_STR, str_val, - ATTR_TYPE_HASH, table, - ATTR_TYPE_END)) > 2) { + if ((ret = attr_scan64(VSTREAM_IN, + ATTR_FLAG_STRICT, + ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, + ATTR_TYPE_STR, ATTR_NAME_STR, str_val, + ATTR_TYPE_HASH, table, + ATTR_TYPE_END)) > 3) { vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); ht_info_list = htable_list(table); for (ht = ht_info_list; *ht; ht++) @@ -436,12 +477,14 @@ int main(int unused_argc, char **used_argv) } else { vstream_printf("return: %d\n", ret); } - if ((ret = attr_scan(VSTREAM_IN, - ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, - ATTR_TYPE_STR, ATTR_NAME_STR, str_val, - ATTR_TYPE_END)) == 2) { + if ((ret = attr_scan64(VSTREAM_IN, + ATTR_FLAG_STRICT, + ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, + ATTR_TYPE_STR, ATTR_NAME_STR, str_val, + ATTR_TYPE_END)) == 3) { vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); ht_info_list = htable_list(table); for (ht = ht_info_list; *ht; ht++) diff --git a/postfix/src/util/attr_scan64.ref b/postfix/src/util/attr_scan64.ref new file mode 100644 index 000000000..1b3a01581 --- /dev/null +++ b/postfix/src/util/attr_scan64.ref @@ -0,0 +1,46 @@ +./attr_print64: send attr number = 4711 +./attr_print64: send attr long_number = 1234 +./attr_print64: send attr string = whoopee +./attr_print64: send attr name foo-name value foo-value +./attr_print64: send attr name bar-name value bar-value +./attr_print64: send attr number = 4711 +./attr_print64: send attr long_number = 1234 +./attr_print64: send attr string = whoopee +./attr_scan64: unknown_stream: wanted attribute: number +./attr_scan64: input attribute name: number +./attr_scan64: input attribute value: 4711 +./attr_scan64: unknown_stream: wanted attribute: long_number +./attr_scan64: input attribute name: long_number +./attr_scan64: input attribute value: 1234 +./attr_scan64: unknown_stream: wanted attribute: string +./attr_scan64: input attribute name: string +./attr_scan64: input attribute value: whoopee +./attr_scan64: unknown_stream: wanted attribute: (any attribute name or list terminator) +./attr_scan64: input attribute name: foo-name +./attr_scan64: input attribute value: foo-value +./attr_scan64: unknown_stream: wanted attribute: (any attribute name or list terminator) +./attr_scan64: input attribute name: bar-name +./attr_scan64: input attribute value: bar-value +./attr_scan64: unknown_stream: wanted attribute: (any attribute name or list terminator) +./attr_scan64: input attribute name: (end) +./attr_scan64: unknown_stream: wanted attribute: number +./attr_scan64: input attribute name: number +./attr_scan64: input attribute value: 4711 +./attr_scan64: unknown_stream: wanted attribute: long_number +./attr_scan64: input attribute name: long_number +./attr_scan64: input attribute value: 1234 +./attr_scan64: unknown_stream: wanted attribute: string +./attr_scan64: input attribute name: string +./attr_scan64: input attribute value: whoopee +./attr_scan64: unknown_stream: wanted attribute: (list terminator) +./attr_scan64: input attribute name: (end) +number 4711 +long_number 1234 +string whoopee +(hash) foo-name foo-value +(hash) bar-name bar-value +number 4711 +long_number 1234 +string whoopee +(hash) foo-name foo-value +(hash) bar-name bar-value diff --git a/postfix/src/util/inet_trigger.c b/postfix/src/util/inet_trigger.c index 980c22df1..dddbcb62a 100644 --- a/postfix/src/util/inet_trigger.c +++ b/postfix/src/util/inet_trigger.c @@ -107,6 +107,7 @@ int inet_trigger(const char *service, const char *buf, int len, int timeout) msg_warn("%s: connect to %s: %m", myname, service); return (-1); } + close_on_exec(fd, CLOSE_ON_EXEC); ip = (struct inet_trigger *) mymalloc(sizeof(*ip)); ip->fd = fd; ip->service = mystrdup(service); diff --git a/postfix/src/util/iostuff.h b/postfix/src/util/iostuff.h index 7da0f297d..ac9681b1d 100644 --- a/postfix/src/util/iostuff.h +++ b/postfix/src/util/iostuff.h @@ -29,6 +29,9 @@ extern int timed_write(int, void *, unsigned, int, void *); extern void doze(unsigned); extern void rand_sleep(unsigned, unsigned); extern int duplex_pipe(int *); +extern int sock_empty_wait(int, int); +extern int sock_maximize_send_lowat(int); +extern void sock_set_send_lowat(int, int); #define BLOCKING 0 #define NON_BLOCKING 1 diff --git a/postfix/src/util/make_dirs.c b/postfix/src/util/make_dirs.c index 31efea03e..ad1b451de 100644 --- a/postfix/src/util/make_dirs.c +++ b/postfix/src/util/make_dirs.c @@ -54,7 +54,7 @@ int make_dirs(const char *path, int perms) int saved_ch; struct stat st; int ret; - mode_t saved_mode; + mode_t saved_mode = 0; /* * Initialize. Make a copy of the path that we can safely clobber. diff --git a/postfix/src/util/match_list.c b/postfix/src/util/match_list.c index 7ae42d6d5..3d9e71c3f 100644 --- a/postfix/src/util/match_list.c +++ b/postfix/src/util/match_list.c @@ -6,10 +6,11 @@ /* SYNOPSIS /* #include /* -/* MATCH_LIST *match_list_init(pattern_list, count, func,...) +/* MATCH_LIST *match_list_init(flags, pattern_list, count, func,...) +/* int flags; /* const char *pattern_list; /* int count; -/* int (*func)(const char *string, const char *pattern); +/* int (*func)(int flags, const char *string, const char *pattern); /* /* int match_list_match(list, string,...) /* MATCH_LIST *list; @@ -28,9 +29,17 @@ /* a pattern match, precede a non-file name pattern with an /* exclamation point (!). /* -/* match_list_init() performs initializations. The first argument is -/* a list of patterns. The second argument specifies how many match -/* functions follow. +/* match_list_init() performs initializations. The flags argument +/* specifies the bit-wise OR of zero or more of the following: +/* .RS +/* .IP MATCH_FLAG_PARENT +/* The hostname pattern foo.com matches any name within the domain +/* foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. +/* .RE +/* Specify MATCH_FLAG_NONE to request none of the above. +/* The pattern_list argument specifies a list of patterns. The third +/* argument specifies how many match functions follow. /* /* match_list_match() matches strings against the specified pattern /* list, passing the first string to the first function given to @@ -73,11 +82,13 @@ #include #include #include +#include #include /* Application-specific */ struct MATCH_LIST { + int flags; /* processing options */ ARGV *patterns; /* one pattern each */ int match_count; /* match function/argument count */ MATCH_LIST_FN *match_func; /* match functions */ @@ -125,14 +136,18 @@ static ARGV *match_list_parse(ARGV *list, char *string) /* match_list_init - initialize pattern list */ -MATCH_LIST *match_list_init(const char *patterns, int match_count,...) +MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,...) { MATCH_LIST *list; char *saved_patterns; va_list ap; int i; + if (flags & ~MATCH_FLAG_ALL) + msg_panic("match_list_init: bad flags 0x%x", flags); + list = (MATCH_LIST *) mymalloc(sizeof(*list)); + list->flags = flags; list->match_count = match_count; list->match_func = (MATCH_LIST_FN *) mymalloc(match_count * sizeof(MATCH_LIST_FN)); @@ -173,7 +188,7 @@ int match_list_match(MATCH_LIST * list,...) for (match = 1; *pat == '!'; pat++) match = !match; for (i = 0; i < list->match_count; i++) - if (list->match_func[i] (list->match_args[i], pat) != 0) + if (list->match_func[i] (list->flags, list->match_args[i], pat)) return (match); } if (msg_verbose) diff --git a/postfix/src/util/match_list.h b/postfix/src/util/match_list.h index aba88b8f6..910ae713b 100644 --- a/postfix/src/util/match_list.h +++ b/postfix/src/util/match_list.h @@ -15,9 +15,9 @@ * External interface. */ typedef struct MATCH_LIST MATCH_LIST; -typedef int (*MATCH_LIST_FN) (const char *, const char *); +typedef int (*MATCH_LIST_FN) (int, const char *, const char *); -extern MATCH_LIST *match_list_init(const char *, int,...); +extern MATCH_LIST *match_list_init(int, const char *, int,...); extern int match_list_match(MATCH_LIST *,...); extern void match_list_free(MATCH_LIST *); diff --git a/postfix/src/util/match_ops.c b/postfix/src/util/match_ops.c index 764866bbc..1bde84abd 100644 --- a/postfix/src/util/match_ops.c +++ b/postfix/src/util/match_ops.c @@ -6,15 +6,18 @@ /* SYNOPSIS /* #include /* -/* int match_string(string, pattern) +/* int match_string(flags, string, pattern) +/* int flags; /* const char *string; /* const char *pattern; /* -/* int match_hostname(name, pattern) +/* int match_hostname(flags, name, pattern) +/* int flags; /* const char *name; /* const char *pattern; /* -/* int match_hostaddr(addr, pattern) +/* int match_hostaddr(flags, addr, pattern) +/* int flags; /* const char *addr; /* const char *pattern; /* DESCRIPTION @@ -24,16 +27,24 @@ /* or address comparison. /* /* match_string() matches the string against the pattern, requiring -/* an exact (case-insensitive) match. +/* an exact (case-insensitive) match. The flags argument is not used. /* /* match_hostname() matches the host name when the hostname matches /* the pattern exactly, or when the pattern matches a parent domain -/* of the named host. +/* of the named host. The flags argument specifies the bit-wise OR +/* of zero or more of the following: +/* .IP MATCH_FLAG_PARENT +/* The hostname pattern foo.com matches itself and any name below +/* the domain foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. +/* .RE +/* Specify MATCH_FLAG_NONE to request none of the above. /* /* match_hostaddr() matches a host address when the pattern is /* identical to the host address, or when the pattern is a net/mask /* that contains the address. The mask specifies the number of -/* bits in the network part of the pattern. +/* bits in the network part of the pattern. The flags argument is +/* not used. /* LICENSE /* .ad /* .fi @@ -72,7 +83,7 @@ /* match_string - match a string literal */ -int match_string(const char *string, const char *pattern) +int match_string(int unused_flags, const char *string, const char *pattern) { char *myname = "match_string"; int match; @@ -110,7 +121,7 @@ int match_string(const char *string, const char *pattern) /* match_hostname - match a host by name */ -int match_hostname(const char *name, const char *pattern) +int match_hostname(int flags, const char *name, const char *pattern) { char *myname = "match_hostname"; const char *pd; @@ -128,13 +139,15 @@ int match_hostname(const char *name, const char *pattern) if (strchr(pattern, ':') != 0) { temp = lowercase(mystrdup(name)); match = 0; - for (entry = temp; /* void */ ; entry = next + 1) { + for (entry = temp; /* void */ ; entry = next) { if ((match = (dict_lookup(pattern, entry) != 0)) != 0) break; if (dict_errno != 0) msg_fatal("%s: table lookup problem", pattern); - if ((next = strchr(entry, '.')) == 0) + if ((next = strchr(entry + 1, '.')) == 0) break; + if (flags & MATCH_FLAG_PARENT) + next += 1; } myfree(temp); return (match); @@ -151,9 +164,15 @@ int match_hostname(const char *name, const char *pattern) * See if the pattern is a parent domain of the hostname. */ else { - pd = name + strlen(name) - strlen(pattern); - if (pd > name && pd[-1] == '.' && strcasecmp(pd, pattern) == 0) - return (1); + if (flags & MATCH_FLAG_PARENT) { + pd = name + strlen(name) - strlen(pattern); + if (pd > name && pd[-1] == '.' && strcasecmp(pd, pattern) == 0) + return (1); + } else if (pattern[0] == '.') { + pd = name + strlen(name) - strlen(pattern); + if (pd > name && strcasecmp(pd, pattern) == 0) + return (1); + } } return (0); } @@ -181,7 +200,7 @@ static int match_parse_mask(const char *pattern, unsigned long *net_bits, /* match_hostaddr - match host by address */ -int match_hostaddr(const char *addr, const char *pattern) +int match_hostaddr(int unused_flags, const char *addr, const char *pattern) { char *myname = "match_hostaddr"; int mask_shift; diff --git a/postfix/src/util/match_ops.h b/postfix/src/util/match_ops.h index a938c04fb..e147f7b50 100644 --- a/postfix/src/util/match_ops.h +++ b/postfix/src/util/match_ops.h @@ -13,9 +13,13 @@ /* External interface. */ -extern int match_string(const char *, const char *); -extern int match_hostname(const char *, const char *); -extern int match_hostaddr(const char *, const char *); +#define MATCH_FLAG_NONE 0 +#define MATCH_FLAG_PARENT (1<<0) +#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT) + +extern int match_string(int, const char *, const char *); +extern int match_hostname(int, const char *, const char *); +extern int match_hostaddr(int, const char *, const char *); /* LICENSE /* .ad diff --git a/postfix/src/util/sock_empty_wait.c b/postfix/src/util/sock_empty_wait.c new file mode 100644 index 000000000..8cc681992 --- /dev/null +++ b/postfix/src/util/sock_empty_wait.c @@ -0,0 +1,207 @@ +/*++ +/* NAME +/* sock_empty_wait 3 +/* SUMMARY +/* wait until socket send buffer is near empty +/* SYNOPSIS +/* #include +/* +/* int sock_empty_wait(fd, timeout) +/* int fd; +/* int timeout; +/* AUXILIARY ROUTINES +/* int sock_maximize_send_lowat(fd) +/* int fd; +/* +/* void sock_set_send_lowat(fd, send_lowat) +/* int fd; +/* int send_lowat; +/* DESCRIPTION +/* sock_empty_wait() blocks the process until the specified socket's +/* send buffer is near empty, in the hope that the contents of the +/* next write() operation will not be merged with preceding data. +/* +/* sock_maximize_send_lowat() maximizes the socket send buffer +/* low-water mark, which controls how much free buffer space must +/* be available before the socket is considered writable. +/* The result value is the old low-water mark value. +/* +/* sock_set_send_lowat() sets the socket send buffer low-water mark +/* to the specified value. +/* +/* Arguments: +/* .IP fd +/* File descriptor in the range 0..FD_SETSIZE. +/* .IP timeout +/* If positive, deadline in seconds. A zero value effects a poll. +/* A negative value means wait until something happens. +/* DIAGNOSTICS +/* sock_maximize_send_lowat() returns -1 if the kernel does not +/* support access to or control over the send buffer low-water mark. +/* Otherwise, all system call errors are fatal. +/* +/* A zero result means success. When the specified deadline is +/* exceeded, sock_empty_wait() returns -1 and sets errno to ETIMEDOUT. +/* BUGS +/* Linux and Solaris do not provide the necessary support. Until +/* they become better citizens they are punished by having to sleep +/* for 10 seconds, and even then there is no reasonable way to find +/* out if all the written data was acknowledged by the remote TCP. +/* 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 +#include +#include +#include +#include + +/* Utility library. */ + +#include +#include + +/* sock_maximize_send_lowat - maximize the send buffer low-water mark */ + +int sock_maximize_send_lowat(int fd) +{ + char *myname = "sock_maximize_send_lowat"; + int send_buffer_size; + int saved_low_water_mark; + int want_low_water_mark; + int got_low_water_mark; + SOCKOPT_SIZE optlen; + + /* + * Get the send buffer size. If this succeeds then we know the file + * handle is a socket. + */ + optlen = sizeof(send_buffer_size); + if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, + (char *) &send_buffer_size, &optlen) < 0) + msg_fatal("%s: getsockopt SO_SNDBUF: %m", myname); + + /* + * Save the send buffer low-water mark. XXX Solaris 8 does not support + * this operation. + */ + optlen = sizeof(saved_low_water_mark); + if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, + (char *) &saved_low_water_mark, &optlen) < 0) { + if (msg_verbose) + msg_info("%s: getsockopt SO_SNDLOWAT: %m", myname); + return (-1); + } + + /* + * Max out the send buffer low-water mark. XXX Linux 2.4.14 does not + * support this operation. + */ + want_low_water_mark = send_buffer_size; + if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, + (char *) &want_low_water_mark, + sizeof(want_low_water_mark)) < 0) { + if (msg_verbose) + msg_info("%s: setsockopt SO_SNDLOWAT: %m", myname); + return (-1); + } + + /* + * Make sure the kernel did not cheat. + */ + optlen = sizeof(got_low_water_mark); + if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, + (char *) &got_low_water_mark, &optlen) < 0) + msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname); + if (got_low_water_mark == 1) + return (-1); + + /* + * Make debugging a bit easier. + */ + if (msg_verbose) { + msg_info("%s: send buffer %d, low-water mark was %d, wanted %d, got %d", + myname, send_buffer_size, saved_low_water_mark, + want_low_water_mark, got_low_water_mark); + + } + return (saved_low_water_mark); +} + +/* sock_set_send_lowat - restore socket send buffer low-water mark */ + +void sock_set_send_lowat(int fd, int want_low_water_mark) +{ + char *myname = "sock_set_send_lowat"; + int got_low_water_mark; + SOCKOPT_SIZE optlen; + + /* + * Set the send buffer low-water mark. + */ + if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, + (char *) &want_low_water_mark, + sizeof(want_low_water_mark)) < 0) + msg_fatal("%s: setsockopt SO_SNDLOWAT: %m", myname); + + /* + * Make debugging a bit easier. + */ + if (msg_verbose) { + optlen = sizeof(got_low_water_mark); + if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, + (char *) &got_low_water_mark, &optlen) < 0) + msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname); + msg_info("%s: low-water mark wanted %d, got %d", + myname, want_low_water_mark, got_low_water_mark); + } +} + +/* sock_empty_wait - wait until socket send buffer is near empty */ + +int sock_empty_wait(int fd, int timeout) +{ + int saved_errno; + int saved_low_water_mark; + int result; + + /* + * Max out the send buffer low-water mark. + */ + saved_low_water_mark = sock_maximize_send_lowat(fd); + + /* + * Wait until the socket is considered writable. + */ + result = write_wait(fd, timeout); + + /* + * Work around systems that have no functional SO_SNDLOWAT control. + */ + if (result == 0 && saved_low_water_mark <= 0) + sleep(10); + + /* + * Restore the send buffer low-water mark. + */ + if (saved_low_water_mark > 0) { + saved_errno = errno; + sock_set_send_lowat(fd, saved_low_water_mark); + errno = saved_errno; + } + + /* + * Done. + */ + return (result); +} diff --git a/postfix/src/util/stream_trigger.c b/postfix/src/util/stream_trigger.c index 31b4dae0a..9cb57e513 100644 --- a/postfix/src/util/stream_trigger.c +++ b/postfix/src/util/stream_trigger.c @@ -103,6 +103,7 @@ int stream_trigger(const char *service, const char *buf, int len, int timeou msg_warn("%s: connect to %s: %m", myname, service); return (-1); } + close_on_exec(fd, CLOSE_ON_EXEC); /* * Stash away context. diff --git a/postfix/src/util/unix_trigger.c b/postfix/src/util/unix_trigger.c index d4a341d75..6a3b19160 100644 --- a/postfix/src/util/unix_trigger.c +++ b/postfix/src/util/unix_trigger.c @@ -104,6 +104,7 @@ int unix_trigger(const char *service, const char *buf, int len, int timeout) msg_warn("%s: connect to %s: %m", myname, service); return (-1); } + close_on_exec(fd, CLOSE_ON_EXEC); /* * Stash away context. diff --git a/postfix/src/util/vstring_vstream.c b/postfix/src/util/vstring_vstream.c index 078d255e1..2f644bf1d 100644 --- a/postfix/src/util/vstring_vstream.c +++ b/postfix/src/util/vstring_vstream.c @@ -27,6 +27,11 @@ /* VSTRING *vp; /* VSTREAM *fp; /* int bound; +/* +/* int vstring_get_null_bound(vp, fp, bound) +/* VSTRING *vp; +/* VSTREAM *fp; +/* int bound; /* DESCRIPTION /* The routines in this module each read one newline or null-terminated /* string from an input stream. In all cases the result is either the @@ -41,7 +46,7 @@ /* vstring_get_null() reads a null-terminated string from the named /* stream. /* -/* vstring_get_bound() and vstring_get_nonl_bound() read no more +/* the vstring_get_bound() routines read no more /* than \fIbound\fR characters. Otherwise they behave like the /* unbounded versions documented above. /* DIAGNOSTICS @@ -154,6 +159,22 @@ int vstring_get_nonl_bound(VSTRING *vp, VSTREAM *fp, int bound) return (c == '\n' ? c : VSTRING_GET_RESULT(vp)); } +/* vstring_get_null_bound - read null-terminated string from file */ + +int vstring_get_null_bound(VSTRING *vp, VSTREAM *fp, int bound) +{ + int c; + + if (bound <= 0) + msg_panic("vstring_get_nonl_bound: invalid bound %d", bound); + + VSTRING_RESET(vp); + while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0) + VSTRING_ADDCH(vp, c); + VSTRING_TERMINATE(vp); + return (c == 0 ? c : VSTRING_GET_RESULT(vp)); +} + #ifdef TEST /* diff --git a/postfix/src/util/vstring_vstream.h b/postfix/src/util/vstring_vstream.h index 897167ca6..68bd8106d 100644 --- a/postfix/src/util/vstring_vstream.h +++ b/postfix/src/util/vstring_vstream.h @@ -24,6 +24,7 @@ extern int vstring_get_nonl(VSTRING *, VSTREAM *); extern int vstring_get_null(VSTRING *, VSTREAM *); extern int vstring_get_bound(VSTRING *, VSTREAM *, int); extern int vstring_get_nonl_bound(VSTRING *, VSTREAM *, int); +extern int vstring_get_null_bound(VSTRING *, VSTREAM *, int); /* * Backwards compatibility for code that still uses the vstring_fgets() diff --git a/postfix/src/virtual/virtual.c b/postfix/src/virtual/virtual.c index 14c388e8a..7968dcc28 100644 --- a/postfix/src/virtual/virtual.c +++ b/postfix/src/virtual/virtual.c @@ -70,9 +70,11 @@ /* numerical user ID values that may be specified in any /* \fBvirtual_owner_maps\fR or \fBvirtual_uid_maps\fR. /* SECURITY +/* .ad +/* .fi /* The virtual delivery agent is not security sensitive, provided -/* that the lookup tables with recipient information are adequately -/* protected. This program is not designed to run chrooted. +/* that the lookup tables with recipient user/group ID information are +/* adequately protected. This program is not designed to run chrooted. /* STANDARDS /* RFC 822 (ARPA Internet Text Messages) /* DIAGNOSTICS @@ -138,7 +140,7 @@ /* This setting is ignored with \fBmaildir\fR style delivery, /* because such deliveries are safe without explicit locks. /* -/* Use the command \fBpostconf -m\fR to find out what locking methods +/* Use the command \fBpostconf -l\fR to find out what locking methods /* are available on your system. /* .IP \fBdeliver_lock_attempts\fR /* Limit the number of attempts to acquire an exclusive lock