From: Wietse Venema Date: Sun, 23 Dec 2001 05:00:00 +0000 (-0500) Subject: snapshot-20011223 X-Git-Tag: v1.1.0~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3fb7553867ea023bd1502448091bdc46444f164;p=thirdparty%2Fpostfix.git snapshot-20011223 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 2cec9fdb2..64dbb3f5e 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -104,6 +104,7 @@ -TREC_TYPE_NAME -TRESOLVE_REPLY -TRESPONSE +-TREST_TABLE -TSCAN_DIR -TSCAN_INFO -TSCAN_OBJ diff --git a/postfix/HISTORY b/postfix/HISTORY index 53af27405..16d196a75 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5789,12 +5789,6 @@ Apologies for any names omitted. Bugfix: postmap/postalias queries ignored the -f flag. Reported by Hamish Marson. -20011215-6 - - Safety: config file comments no longer span multiple lines - when the next line starts with whitespace; a comment that - is preceded by whitespace does not break multi-line input. - 20011217 Compatibility: Sendmail now has a -L option to set the @@ -5803,22 +5797,51 @@ Apologies for any names omitted. Security: subtle hardening of the Postfix chroot jail, Postfix queue file permissions and access methods, in case - someone compromises the postfix account. Michael Tokarev - claims he got the insights from Solar Designer. Files: + someone compromises the postfix account. Michael Tokarev, + who received the insights from Solar Designer, who tested + Postfix with his "openwatch" kernel module. Files: master/master_wakeup.c, util/fifo_trigger.c, postfix-script. -Open problems: + Convenience: issue a warning instead of aborting when the + local machine name is not in fully-qualified domain form. + This would otherwise break initial postfix installation + which needs the postconf command. File: global/mail_params.c. + +20011220 + + Added more garbage detection to postconf -e input processing. + +20011221 + + Feature: SMTPD access map lookups of null sender addresses. + If your access maps cannot store or look up null string + key values, specify "smtpd_null_access_lookup_key = <>" + and the null sender address will be looked up as <> instead. + File: src/smtpd_access.c. + +20011223 - Low: warn about undomained hostnames instead of aborting. + Safety: configuration file comments no longer span multiple + lines when the next line begins with whitespace; multi-line + input is no longer terminated by a comment line, by an all + white space line, or by an empty line. Files: util/readlline.c, + postconf/postconf.c. + + Cleanup: proper detection of big number overflow in EHLO + and MAIL FROM size announcements. Files: global/off_cvt.c, + smtpd/smtpd.c, smtp/smtp_proto.c, util/alldig.c. + + Forward compatibility: added queue file record types for + original recipient and for generic named attributes. + + Cleanup: safe_open() now returns sensible errno values so + that the fifo_trigger() external interface is restored. + +Open problems: Low: after reorganizing configuration parameters, add flags to all parameters whose value can be read from file. - Low: replace null sender address internal representation - by <> so that it can be looked up reliably in maps. Must - prevent attempts to rewrite this address with canonical - maps, or else accidents are bound to happen. - Medium: need in-process caching for map lookups. LDAP servers seem to need this in particular. Need a way to expire cached results that are too old. @@ -5839,7 +5862,4 @@ Open problems: This should be documented, or better, the code should warn about attempts to set read-only parameters. - Low: the virtual delivery agent needs a way to specify - fixed uid/gid for all deliveries. - Low: postconf -e edits parameters that postconf won't list. diff --git a/postfix/NFS_README b/postfix/NFS_README index 807beb8df..31c74f968 100644 --- a/postfix/NFS_README +++ b/postfix/NFS_README @@ -12,8 +12,9 @@ For queue locking, NFS is not an issue because you cannot share Postfix queues between Postfix instances anyawy. For mailbox locking, some systems such as FreeBSD use flock() by -default. flock() does not work over NFS. This causes loss of mail -when multiple hosts access the same mailboxes. +default (use: ``postconf mailbox_delivery_lock'' to find out about +your system). flock() does not work over NFS. This causes loss of +mail when multiple hosts access the same mailboxes. In order to have mailbox locking over NFS you have to configure everything to use fcntl() locks for mailbox access (or switch to diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index a00487700..c0f76d024 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,18 +1,22 @@ -Incompatible changes with snapshot-20011217 +Incompatible changes with snapshot-200112XX =========================================== Postfix configuration file comments no longer continue on the next line when that next line starts with whitespace. This change avoids surprises, but it may cause unexpected behavior with existing, -poorly formatted, configuration files. Caveat user. +improperly formatted, configuration files. Caveat user. -Major changes with snapshot-20011217 +Major changes with snapshot-200112XX ==================================== -Postfix configuration files now support whitespace before comments. -This allows you to comment out just one line in the middle of a -block of multi-line input. A comment that starts at the beginning -of a line always terminates previous data. +In Postfix configuration files, comment lines are allowed to begin +with whitespace, and multi-line input is no longer terminated by +a comment line, by an all whitespace line, or by an empty line. + +Postfix will now do null address lookups in SMTPD access maps. If +your access maps cannot store or look up null string key values, +specify "smtpd_null_access_lookup_key = <>" and the null sender +address will be looked up as <> instead. Incompatible changes with snapshot-20011210 =========================================== diff --git a/postfix/conf/postfix-script-nosgid b/postfix/conf/postfix-script-nosgid index 62e57b759..40154a98a 100755 --- a/postfix/conf/postfix-script-nosgid +++ b/postfix/conf/postfix-script-nosgid @@ -177,33 +177,34 @@ check) test -d maildrop || { $WARN creating missing Postfix maildrop directory mkdir maildrop || exit 1 - chmod 1733 maildrop - chown $mail_owner maildrop + chmod 1733 maildrop || exit 1 + chown $mail_owner maildrop || exit 1 } test -d pid || { $WARN creating missing Postfix pid directory mkdir pid || exit 1 - chmod 755 pid + chmod 755 pid || exit 1 } for dir in incoming active bounce defer deferred flush saved corrupt; do test -d $dir || { $WARN creating missing Postfix $dir directory mkdir $dir || exit 1 - chmod 700 $dir; $CHATTR $dir 2>/dev/null - chown $mail_owner $dir + chmod 700 $dir || exit 1 + $CHATTR $dir 2>/dev/null + chown $mail_owner $dir || exit 1 } done test -d public || { $WARN creating missing Postfix public directory mkdir public || exit 1 - chmod 755 public - chown $mail_owner public + chmod 755 public || exit 1 + chown $mail_owner public || exit 1 } test -d private || { $WARN creating missing Postfix private directory mkdir private || exit 1 - chmod 700 private - chown $mail_owner private + chmod 700 private || exit 1 + chown $mail_owner private || exit 1 } find `ls -d $queue_directory/* | \ egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private|flush)$'` \ diff --git a/postfix/conf/postfix-script-sgid b/postfix/conf/postfix-script-sgid index a2da2c6e0..9f868f87a 100644 --- a/postfix/conf/postfix-script-sgid +++ b/postfix/conf/postfix-script-sgid @@ -177,34 +177,35 @@ check) test -d maildrop || { $WARN creating missing Postfix maildrop directory mkdir maildrop || exit 1 - chmod 1730 maildrop - chown $mail_owner maildrop + chmod 1730 maildrop || exit 1 + chown $mail_owner maildrop || exit 1 (. $config_directory/install.cf; chgrp $setgid maildrop) } test -d pid || { $WARN creating missing Postfix pid directory mkdir pid || exit 1 - chmod 755 pid + chmod 755 pid || exit 1 } for dir in incoming active bounce defer deferred flush saved corrupt; do test -d $dir || { $WARN creating missing Postfix $dir directory mkdir $dir || exit 1 - chmod 700 $dir; $CHATTR $dir 2>/dev/null - chown $mail_owner $dir + chmod 700 $dir || exit 1 + $CHATTR $dir 2>/dev/null + chown $mail_owner $dir || exit 1 } done test -d public || { $WARN creating missing Postfix public directory mkdir public || exit 1 - chmod 755 public - chown $mail_owner public + chmod 755 public || exit 1 + chown $mail_owner public || exit 1 } test -d private || { $WARN creating missing Postfix private directory mkdir private || exit 1 - chmod 700 private - chown $mail_owner private + chmod 700 private || exit 1 + chown $mail_owner private || exit 1 } find `ls -d $queue_directory/* | \ egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private|flush)$'` \ diff --git a/postfix/html/access.5.html b/postfix/html/access.5.html index e575307a5..beaba3ce9 100644 --- a/postfix/html/access.5.html +++ b/postfix/html/access.5.html @@ -37,35 +37,30 @@ ACCESS(5) ACCESS(5) When pattern matches a mail address, domain or host address, perform the corresponding action. + blank lines and comments + Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + multi-line text - A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - comments - The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. PATTERNS With lookups from indexed files such as DB or DBM, or from - networked tables such as NIS, LDAP or SQL, patterns are + networked tables such as NIS, LDAP or SQL, patterns are tried in the order as listed below: user@domain Matches the specified mail address. domain.name - Matches the domain.name itself and any subdomain - thereof, either in hostnames or in mail addresses. + Matches the domain.name itself and any subdomain + thereof, either in hostnames or in mail addresses. Top-level domains will never be matched. - user@ Matches all mail addresses with the specified user + user@ Matches all mail addresses with the specified user part. net.work.addr.ess @@ -74,13 +69,13 @@ ACCESS(5) ACCESS(5) net.work - net Matches any host address in the specified network. - A network address is a sequence of one or more + net Matches any host address in the specified network. + A network address is a sequence of one or more octets separated by ".". ACTIONS [45]NN text - Reject the address etc. that matches the pattern, + Reject the address etc. that matches the pattern, and respond with the numerical code and text. REJECT Reject the address etc. that matches the pattern. A @@ -93,29 +88,29 @@ ACCESS(5) ACCESS(5) reject_unauth_destination, and so on). REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to + Each pattern is a regular expression that is applied to the entire string being looked up. Depending on the appli- - cation, that string is an entire client hostname, an + cation, that string is an entire client hostname, an entire client IP address, or an entire mail address. Thus, - no parent domain or parent network search is done, and - user@domain mail addresses are not broken up into their + no parent domain or parent network search is done, and + user@domain mail addresses are not broken up into their user@ and domain constituent parts. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Actions are the same as with normal indexed file lookups, - with the additional feature that parenthesized substrings - from the pattern can be interpolated as $1, $2 and so on. + Actions are the same as with normal indexed file lookups, + with the additional feature that parenthesized substrings + from the pattern can be interpolated as $1, $2 and so on. BUGS - The table format does not understand quoting conventions. + The table format does not understand quoting conventions. SEE ALSO postmap(1) create mapping table @@ -124,7 +119,7 @@ ACCESS(5) ACCESS(5) regexp_table(5) format of POSIX regular expression tables 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/html/aliases.5.html b/postfix/html/aliases.5.html index fd7e77032..2992fc0c4 100644 --- a/postfix/html/aliases.5.html +++ b/postfix/html/aliases.5.html @@ -35,59 +35,54 @@ ALIASES(5) ALIASES(5) name: value1, value2, ... - o A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - o The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. - - The name is a local address (no domain part). Use double - quotes when the name contains any special characters such - as whitespace, `#', `:', or `@'. The name is folded to + o Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + + o A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. + + The name is a local address (no domain part). Use double + quotes when the name contains any special characters such + as whitespace, `#', `:', or `@'. The name is folded to lowercase, in order to make database lookups case insensi- tive. In addition, when an alias exists for owner-name, delivery - diagnostics are directed to that address, instead of to + diagnostics are directed to that address, instead of to the originator. This is typically used to direct delivery - errors to the owner of a mailing list, who is in a better - position to deal with mailing list delivery problems than + errors to the owner of a mailing list, who is in a better + position to deal with mailing list delivery problems than the originator of the undelivered mail. The value contains one or more of the following: address - Mail is forwarded to address, which is compatible + Mail is forwarded to address, which is compatible with the RFC 822 standard. /file/name - Mail is appended to /file/name. See local(8) for - details of delivery to file. Delivery is not lim- - ited to regular files. For example, to dispose of + Mail is appended to /file/name. See local(8) for + details of delivery to file. Delivery is not lim- + ited to regular files. For example, to dispose of unwanted mail, deflect it to /dev/null. |command - Mail is piped into command. Commands that contain - special characters, such as whitespace, should be - enclosed between double quotes. See local(8) for + Mail is piped into command. Commands that contain + special characters, such as whitespace, should be + enclosed between double quotes. See local(8) for details of delivery to command. When the command fails, a limited amount of command - output is mailed back to the sender. The file - /usr/include/sysexits.h defines the expected exit - status codes. For example, use |"exit 67" to simu- - late a "user unknown" error, and |"exit 0" to + output is mailed back to the sender. The file + /usr/include/sysexits.h defines the expected exit + status codes. For example, use |"exit 67" to simu- + late a "user unknown" error, and |"exit 0" to implement an expensive black hole. :include:/file/name - Mail is sent to the destinations listed in the + Mail is sent to the destinations listed in the named file. Lines in :include: files have the same syntax as the right-hand side of alias entries. @@ -99,31 +94,31 @@ ALIASES(5) ALIASES(5) ADDRESS EXTENSION When alias database search fails, and the recipient local- - part contains the optional recipient delimiter (e.g., - user+foo), the search is repeated for the unextended + part contains the optional recipient delimiter (e.g., + user+foo), the search is repeated for the unextended address (e.g., user). CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this topic. 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 topic. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. alias_maps List of alias databases. allow_mail_to_commands - Restrict the usage of mail delivery to external + Restrict the usage of mail delivery to external command. allow_mail_to_files - Restrict the usage of mail delivery to external + Restrict the usage of mail delivery to external file. expand_owner_alias When delivering to an alias that has an owner- com- - panion alias, set the envelope sender address to - the right-hand side of the owner alias, instead + panion alias, set the envelope sender address to + the right-hand side of the owner alias, instead using of the left-hand side address. owner_request_special @@ -131,7 +126,7 @@ ALIASES(5) ALIASES(5) addresses. recipient_delimiter - Delimiter that separates recipients from address + Delimiter that separates recipients from address extensions. STANDARDS @@ -142,7 +137,7 @@ ALIASES(5) ALIASES(5) postalias(1) alias database management 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/html/canonical.5.html b/postfix/html/canonical.5.html index d69e5d1f4..d473afd3e 100644 --- a/postfix/html/canonical.5.html +++ b/postfix/html/canonical.5.html @@ -52,85 +52,80 @@ CANONICAL(5) CANONICAL(5) When pattern matches a mail address, replace it by the corresponding result. + blank lines and comments + Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + multi-line text - A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - comments - The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. With lookups from indexed files such as DB or DBM, or from - networked tables such as NIS, LDAP or SQL, patterns are + networked tables such as NIS, LDAP or SQL, patterns are tried in the order as listed below: user@domain address - user@domain is replaced by address. This form has + user@domain is replaced by address. This form has the highest precedence. - This form useful to clean up addresses produced by - legacy mail systems. It can also be used to pro- - duce Firstname.Lastname style addresses, but see + This form useful to clean up addresses produced by + legacy mail systems. It can also be used to pro- + duce Firstname.Lastname style addresses, but see below for a simpler solution. user address user@site is replaced by address when site is equal - to $myorigin, when site is listed in $mydestina- + to $myorigin, when site is listed in $mydestina- tion, or when it is listed in $inet_interfaces. - This form is useful for replacing login names by + This form is useful for replacing login names by Firstname.Lastname. @domain address - Every address in domain is replaced by address. + Every address in domain is replaced by address. This form has the lowest precedence. - In all the above forms, when address has the form @other- + In all the above forms, when address has the form @other- domain, the result is the same user in otherdomain. ADDRESS EXTENSION - When table lookup fails, and the address localpart con- - tains the optional recipient delimiter (e.g., - user+foo@domain), the search is repeated for the unex- - tended address (e.g. user@domain), and the unmatched + When table lookup fails, and the address localpart con- + tains the optional recipient delimiter (e.g., + user+foo@domain), the search is repeated for the unex- + tended address (e.g. user@domain), and the unmatched extension is propagated to the result of table lookup. The matching order is: user+foo@domain, user@domain, user+foo, user, and @domain. REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to + Each pattern is a regular expression that is applied to the entire address being looked up. Thus, user@domain mail - addresses are not broken up into their user and @domain + addresses are not broken up into their user and @domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Results are the same as with normal indexed file lookups, - with the additional feature that parenthesized substrings - from the pattern can be interpolated as $1, $2 and so on. + Results are the same as with normal indexed file lookups, + with the additional feature that parenthesized substrings + from the pattern can be interpolated as $1, $2 and so on. BUGS - The table format does not understand quoting conventions. + The table format does not understand quoting conventions. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this topic. 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 topic. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. canonical_maps @@ -147,24 +142,24 @@ CANONICAL(5) CANONICAL(5) Other parameters of interest: inet_interfaces - The network interface addresses that this system + The network interface addresses that this system receives mail on. masquerade_classes - List of address classes subject to masquerading: - zero or more of envelope_sender, envelope_recipi- + List of address classes subject to masquerading: + zero or more of envelope_sender, envelope_recipi- ent, header_sender, header_recipient. masquerade_domains - List of domains that hide their subdomain struc- + List of domains that hide their subdomain struc- ture. masquerade_exceptions - List of user names that are not subject to address + List of user names that are not subject to address masquerading. mydestination - List of domains that this mail system considers + List of domains that this mail system considers local. myorigin @@ -182,7 +177,7 @@ CANONICAL(5) CANONICAL(5) regexp_table(5) format of POSIX regular expression tables 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/html/pcre_table.5.html b/postfix/html/pcre_table.5.html index 09e869fc6..55d1e7148 100644 --- a/postfix/html/pcre_table.5.html +++ b/postfix/html/pcre_table.5.html @@ -23,49 +23,44 @@ PCRE_TABLE(5) PCRE_TABLE(5) When pattern matches a search string, use the cor- responding result. + blank lines and comments + Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + multi-line text - A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - comments - The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. Each pattern is a perl-like regular expression. The - expression delimiter can be any character, except whites- - pace or characters that have special meaning (tradition- - ally the forward slash is used). The regular expression + expression delimiter can be any character, except whites- + pace or characters that have special meaning (tradition- + ally the forward slash is used). The regular expression can contain whitespace. By default, matching is case-insensitive, although follow- - ing the second slash with an `i' flag will reverse this. - Other flags are supported, but the only other useful one + ing the second slash with an `i' flag will reverse this. + Other flags are supported, but the only other useful one is `U', which makes matching ungreedy (see PCRE documenta- tion and source for more info). - Each pattern is applied to the entire lookup key string. - Depending on the application, that string is an entire + Each pattern is applied to the entire lookup key string. + Depending on the application, that string is an entire client hostname, an entire client IP address, or an entire - mail address. Thus, no parent domain or parent network - search is done, and user@domain mail addresses are not - broken up into their user and domain constituent parts, + mail address. Thus, no parent domain or parent network + search is done, and user@domain mail addresses are not + broken up into their user and domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Substitution of substrings from the matched expression - into the result string is possible using the conventional - perl syntax ($1, $2, etc.). The macros in the result - string may need to be written as ${n} or $(n) if they + Substitution of substrings from the matched expression + into the result string is possible using the conventional + perl syntax ($1, $2, etc.). The macros in the result + string may need to be written as ${n} or $(n) if they aren't followed by whitespace. EXAMPLE SMTPD ACCESS MAP diff --git a/postfix/html/regexp_table.5.html b/postfix/html/regexp_table.5.html index 11273391a..704b8abc3 100644 --- a/postfix/html/regexp_table.5.html +++ b/postfix/html/regexp_table.5.html @@ -23,20 +23,15 @@ REGEXP_TABLE(5) REGEXP_TABLE(5) When pattern matches a search string, use the cor- responding result. + blank lines and comments + Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + multi-line text - A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - comments - The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. pattern1!pattern2 result Matches pattern1 but not pattern2. @@ -44,28 +39,28 @@ REGEXP_TABLE(5) REGEXP_TABLE(5) Each pattern is a regular expression enclosed by a pair of delimiters. The regular expression syntax is described in re_format(7). The expression delimiter can be any charac- - ter, except whitespace or characters that have special - meaning (traditionally the forward slash is used). The + ter, except whitespace or characters that have special + meaning (traditionally the forward slash is used). The regular expression can contain whitespace. By default, matching is case-insensitive, although follow- - ing the second slash with an `i' flag will reverse this. - Other flags are `x' (disable extended expression syntax), + ing the second slash with an `i' flag will reverse this. + Other flags are `x' (disable extended expression syntax), and `m' (enable multi-line mode). - Each pattern is applied to the entire lookup key string. - Depending on the application, that string is an entire + Each pattern is applied to the entire lookup key string. + Depending on the application, that string is an entire client hostname, an entire client IP address, or an entire - mail address. Thus, no parent domain or parent network - search is done, and user@domain mail addresses are not - broken up into their user and domain constituent parts, + mail address. Thus, no parent domain or parent network + search is done, and user@domain mail addresses are not + broken up into their user and domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Substitution of substrings from the matched expression + Substitution of substrings from the matched expression into the result string is possible using $1, $2, etc.. The macros in the result string may need to be written as ${n} or $(n) if they aren't followed by whitespace. diff --git a/postfix/html/relocated.5.html b/postfix/html/relocated.5.html index 5ef72fed6..e2d970067 100644 --- a/postfix/html/relocated.5.html +++ b/postfix/html/relocated.5.html @@ -40,25 +40,20 @@ RELOCATED(5) RELOCATED(5) such as an email address, or perhaps a street address or telephone number. - o A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - o The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + o Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + + o A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. With lookups from indexed files such as DB or DBM, or from - networked tables such as NIS, LDAP or SQL, the key field + networked tables such as NIS, LDAP or SQL, the key field is one of the following: user@domain - Matches user@domain. This form has precedence over + Matches user@domain. This form has precedence over all other forms. user Matches user@site when site is $myorigin, when site @@ -66,42 +61,42 @@ RELOCATED(5) RELOCATED(5) in $inet_interfaces. @domain - Matches every address in domain. This form has the + Matches every address in domain. This form has the lowest precedence. ADDRESS EXTENSION - When the search fails, and the address localpart contains - the optional recipient delimiter (e.g., user+foo@domain), - the search is repeated for the unextended address (e.g. + When the search fails, and the address localpart contains + the optional recipient delimiter (e.g., user+foo@domain), + the search is repeated for the unextended address (e.g. user@domain). REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to + Each pattern is a regular expression that is applied to the entire address being looked up. Thus, user@domain mail - addresses are not broken up into their user and @domain + addresses are not broken up into their user and @domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Results are the same as with normal indexed file lookups, - with the additional feature that parenthesized substrings - from the pattern can be interpolated as $1, $2 and so on. + Results are the same as with normal indexed file lookups, + with the additional feature that parenthesized substrings + from the pattern can be interpolated as $1, $2 and so on. BUGS - The table format does not understand quoting conventions. + The table format does not understand quoting conventions. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this topic. 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 topic. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. relocated_maps @@ -110,11 +105,11 @@ RELOCATED(5) RELOCATED(5) Other parameters of interest: inet_interfaces - The network interface addresses that this system + The network interface addresses that this system receives mail on. mydestination - List of domains that this mail system considers + List of domains that this mail system considers local. myorigin @@ -126,7 +121,7 @@ RELOCATED(5) RELOCATED(5) regexp_table(5) format of POSIX regular expression tables 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/html/rewrite.html b/postfix/html/rewrite.html index b1ade9a61..0d87a8a5a 100644 --- a/postfix/html/rewrite.html +++ b/postfix/html/rewrite.html @@ -263,8 +263,8 @@ For example,

- By default, Postfix makes no exceptions. +

Subtle point: by default, address masquerading is applied only to diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 2d6349670..099a41de1 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -67,20 +67,20 @@ SMTPD(8) SMTPD(8) the AUTH protocol, and that expect an EHLO response of "250 AUTH=list" instead of "250 AUTH list". -Content inspection controls - content_filter - The name of a mail delivery transport that filters - mail and that either bounces mail or re-injects the - result back into Postfix. This parameter uses the - same syntax as the right-hand side of a Postfix - transport table. - smtpd_noop_commands List of commands that are treated as NOOP (no oper- ation) commands, without any parameter syntax checking and without any state change. This list overrides built-in command definitions. +Content inspection controls + content_filter + The name of a mail delivery transport that filters + mail and that either bounces mail or re-injects the + result back into Postfix. This parameter uses the + same syntax as the right-hand side of a Postfix + transport table. + Authentication controls enable_sasl_authentication Enable per-session authentication as per RFC 2554 @@ -263,6 +263,11 @@ SMTPD(8) SMTPD(8) these parameters can then be used instead of the restriction lists that they represent. + smtpd_null_access_lookup_key + The lookup key to be used in SMTPD access tables + instead of the null sender address. A null sender + address cannot be looked up. + maps_rbl_domains List of DNS domains that publish the addresses of blacklisted hosts. diff --git a/postfix/html/transport.5.html b/postfix/html/transport.5.html index 7cedd665b..4f8927497 100644 --- a/postfix/html/transport.5.html +++ b/postfix/html/transport.5.html @@ -37,121 +37,116 @@ TRANSPORT(5) TRANSPORT(5) When pattern matches the domain, use the corre- sponding result. + blank lines and comments + Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + multi-line text - A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - comments - The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. With lookups from indexed files such as DB or DBM, or from - networked tables such as NIS, LDAP or SQL, patterns are + networked tables such as NIS, LDAP or SQL, patterns are tried in the order as listed below: domain transport:nexthop - Mail for domain is delivered through transport to + Mail for domain is delivered through transport to nexthop. .domain transport:nexthop - Mail for any subdomain of domain is delivered + Mail for any subdomain of domain is delivered through transport to nexthop. - Note: transport map entries take precedence over domains - specified in the mydestination parameter. If you use the + Note: transport map entries take precedence over domains + specified in the mydestination parameter. If you use the optional transport map, it may be safer to specify - explicit entries for all domains specified in mydestina- + explicit entries for all domains specified in mydestina- tion, for example: hostname.my.domain local: localhost.my.domain local: - The interpretation of the nexthop field is transport + The interpretation of the nexthop field is transport dependent. In the case of SMTP, specify host:service for a - non-default server port, and use [host] or [host]:port in - order to disable MX (mail exchanger) DNS lookups. The [] - form can also be used with IP addresses instead of host- + non-default server port, and use [host] or [host]:port in + order to disable MX (mail exchanger) DNS lookups. The [] + form can also be used with IP addresses instead of host- names. EXAMPLES - In order to send mail for foo.org and its subdomains via + In order to send mail for foo.org and its subdomains via the uucp transport to the UUCP host named foo: foo.org uucp:foo .foo.org uucp:foo - When no nexthop host name is specified, the destination - domain name is used instead. For example, the following - directs mail for user@foo.org via the slow transport to a - mail exchanger for foo.org. The slow transport could be - something that runs at most one delivery process at a + When no nexthop host name is specified, the destination + domain name is used instead. For example, the following + directs mail for user@foo.org via the slow transport to a + mail exchanger for foo.org. The slow transport could be + something that runs at most one delivery process at a time: foo.org slow: - When no transport is specified, the default transport is + When no transport is specified, the default transport is used, as specified via the default_transport configuration - parameter. The following sends all mail for foo.org and + parameter. The following sends all mail for foo.org and its subdomains to host gateway.foo.org: foo.org :[gateway.foo.org] .foo.org :[gateway.foo.org] - In the above example, the [] are used to suppress MX - lookups. The result would likely point to your local + In the above example, the [] are used to suppress MX + lookups. The result would likely point to your local machine. - In the case of delivery via SMTP, one may specify host- + In the case of delivery via SMTP, one may specify host- name:service instead of just a host: foo.org smtp:bar.org:2025 - This directs mail for user@foo.org to host bar.org port - 2025. Instead of a numerical port a symbolic name may be - used. Specify [] around the hostname in order to disable + This directs mail for user@foo.org to host bar.org port + 2025. Instead of a numerical port a symbolic name may be + used. Specify [] around the hostname in order to disable MX lookups. The error mailer can be used to bounce mail: - .foo.org error:mail for *.foo.org is not deliv- + .foo.org error:mail for *.foo.org is not deliv- erable - This causes all mail for user@anything.foo.org to be + This causes all mail for user@anything.foo.org to be bounced. REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to + Each pattern is a regular expression that is applied to the entire domain being looked up. Thus, some.domain.hier- archy is not broken up into parent domains. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Results are the same as with normal indexed file lookups, - with the additional feature that parenthesized substrings - from the pattern can be interpolated as $1, $2 and so on. + Results are the same as with normal indexed file lookups, + with the additional feature that parenthesized substrings + from the pattern can be interpolated as $1, $2 and so on. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this topic. 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 topic. See the Postfix main.cf file for syntax + 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- + List of Postfix features that use domain.name pat- terns to match sub.domain.name (as opposed to requiring .domain.name patterns). @@ -161,7 +156,7 @@ TRANSPORT(5) TRANSPORT(5) Other parameters of interest: default_transport - The transport to use when no transport is explic- + The transport to use when no transport is explic- itly specified. relayhost @@ -175,7 +170,7 @@ TRANSPORT(5) TRANSPORT(5) regexp_table(5) format of POSIX regular expression tables 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/html/virtual.5.html b/postfix/html/virtual.5.html index 9304514b9..660e196be 100644 --- a/postfix/html/virtual.5.html +++ b/postfix/html/virtual.5.html @@ -108,83 +108,78 @@ VIRTUAL(5) VIRTUAL(5) When pattern matches a mail address, replace it by the corresponding result. + blank lines and comments + Empty lines and whitespace-only lines are ignored, + as are lines whose first non-whitespace character + is a `#'. + multi-line text - A line that starts with whitespace (space or tab) - is a continuation of the previous line. An empty - line terminates the previous line, as does a line - that starts with non-whitespace (text or comment). - A comment line that starts with whitespace does not - terminate multi-line text. - - comments - The # is recognized as the start of a comment, but - only when it is the first non-whitespace character - on a line. A comment terminates at the end of the - line, even when the next line starts with whites- - pace. + A logical line starts with non-whitespace text. A + line that starts with whitespace continues a logi- + cal line. With lookups from indexed files such as DB or DBM, or from - networked tables such as NIS, LDAP or SQL, patterns are + networked tables such as NIS, LDAP or SQL, patterns are tried in the order as listed below: user@domain address, address, ... - Mail for user@domain is redirected to address. + Mail for user@domain is redirected to address. This form has the highest precedence. user address, address, ... - Mail for user@site is redirected to address when - site is equal to $myorigin, when site is listed in + Mail for user@site is redirected to address when + site is equal to $myorigin, when site is listed in $mydestination, or when it is listed in $inet_interfaces. - This functionality overlaps with functionality of + This functionality overlaps with functionality of the local alias(5) database. The difference is that - virtual mapping can be applied to non-local + virtual mapping can be applied to non-local addresses. @domain address, address, ... - Mail for any user in domain is redirected to + Mail for any user in domain is redirected to address. This form has the lowest precedence. - In all the above forms, when address has the form @other- - domain, the result is the same user in otherdomain. This + In all the above forms, when address has the form @other- + domain, the result is the same user in otherdomain. This works for the first address in the expansion only. ADDRESS EXTENSION - When the search fails, and the address localpart contains - the optional recipient delimiter (e.g., user+foo@domain), - the search is repeated for the unextended address (e.g. + When the search fails, and the address localpart contains + the optional recipient delimiter (e.g., user+foo@domain), + the search is repeated for the unextended address (e.g. user@domain), and the unmatched address extension is prop- - agated to the result of expansion. The matching order is: + agated to the result of expansion. The matching order is: user+foo@domain, user@domain, user+foo, user, and @domain. REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to + Each pattern is a regular expression that is applied to the entire address being looked up. Thus, user@domain mail - addresses are not broken up into their user and @domain + addresses are not broken up into their user and @domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Results are the same as with normal indexed file lookups, - with the additional feature that parenthesized substrings - from the pattern can be interpolated as $1, $2 and so on. + Results are the same as with normal indexed file lookups, + with the additional feature that parenthesized substrings + from the pattern can be interpolated as $1, $2 and so on. BUGS - The table format does not understand quoting conventions. + The table format does not understand quoting conventions. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this topic. 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 topic. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. virtual_maps @@ -193,11 +188,11 @@ VIRTUAL(5) VIRTUAL(5) Other parameters of interest: inet_interfaces - The network interface addresses that this system + The network interface addresses that this system receives mail on. mydestination - List of domains that this mail system considers + List of domains that this mail system considers local. myorigin @@ -214,7 +209,7 @@ VIRTUAL(5) VIRTUAL(5) regexp_table(5) format of POSIX regular expression tables 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/man/man5/access.5 b/postfix/man/man5/access.5 index 80ce2af17..58a02a996 100644 --- a/postfix/man/man5/access.5 +++ b/postfix/man/man5/access.5 @@ -38,16 +38,12 @@ The format of the access table is as follows: .IP "\fIpattern action\fR" When \fIpattern\fR matches a mail address, domain or host address, perform the corresponding \fIaction\fR. +.IP "blank lines and comments" +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP "multi-line text" -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. -.IP "comments" -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .SH PATTERNS .na .nf diff --git a/postfix/man/man5/aliases.5 b/postfix/man/man5/aliases.5 index 89ef2bdee..394ad1178 100644 --- a/postfix/man/man5/aliases.5 +++ b/postfix/man/man5/aliases.5 @@ -40,15 +40,11 @@ An alias definition has the form .ti +5 \fIname\fR: \fIvalue1\fR, \fIvalue2\fR, \fI...\fR .IP \(bu -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP \(bu -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .PP The \fIname\fR is a local address (no domain part). Use double quotes when the name contains any special characters diff --git a/postfix/man/man5/canonical.5 b/postfix/man/man5/canonical.5 index 6cee20288..80fe42c14 100644 --- a/postfix/man/man5/canonical.5 +++ b/postfix/man/man5/canonical.5 @@ -53,16 +53,12 @@ The format of the \fBcanonical\fR table is as follows: .IP "\fIpattern result\fR" When \fIpattern\fR matches a mail address, replace it by the corresponding \fIresult\fR. +.IP "blank lines and comments" +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP "multi-line text" -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. -.IP "comments" -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .PP With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, patterns are tried in the order as diff --git a/postfix/man/man5/pcre_table.5 b/postfix/man/man5/pcre_table.5 index cb4b51aba..598839ee0 100644 --- a/postfix/man/man5/pcre_table.5 +++ b/postfix/man/man5/pcre_table.5 @@ -24,16 +24,12 @@ The general form of a PCRE table is: .IP "\fIpattern result\fR" When \fIpattern\fR matches a search string, use the corresponding \fIresult\fR. +.IP "blank lines and comments" +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP "multi-line text" -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. -.IP "comments" -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .PP Each pattern is a perl-like regular expression. The expression delimiter can be any character, except whitespace or characters diff --git a/postfix/man/man5/regexp_table.5 b/postfix/man/man5/regexp_table.5 index 43a84fb1a..b561a4b14 100644 --- a/postfix/man/man5/regexp_table.5 +++ b/postfix/man/man5/regexp_table.5 @@ -24,16 +24,12 @@ The general form of a Postfix regular expression table is: .IP "\fIpattern result\fR" When \fIpattern\fR matches a search string, use the corresponding \fIresult\fR. +.IP "blank lines and comments" +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP "multi-line text" -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. -.IP "comments" -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .IP "\fIpattern1!pattern2 result\fR" Matches \fIpattern1\fR but not \fIpattern2\fR. .PP diff --git a/postfix/man/man5/relocated.5 b/postfix/man/man5/relocated.5 index c3cb8de6b..189bb167c 100644 --- a/postfix/man/man5/relocated.5 +++ b/postfix/man/man5/relocated.5 @@ -44,15 +44,11 @@ An entry has one of the following form: Where \fInew_location\fR specifies contact information such as an email address, or perhaps a street address or telephone number. .IP \(bu -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP \(bu -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .PP With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, the \fIkey\fR field is one of the diff --git a/postfix/man/man5/transport.5 b/postfix/man/man5/transport.5 index 0d467b964..674c8e3d7 100644 --- a/postfix/man/man5/transport.5 +++ b/postfix/man/man5/transport.5 @@ -38,16 +38,12 @@ The format of the transport table is as follows: .IP "\fIpattern result\fR" When \fIpattern\fR matches the domain, use the corresponding \fIresult\fR. +.IP "blank lines and comments" +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP "multi-line text" -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. -.IP "comments" -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .PP With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, patterns are tried in the order as diff --git a/postfix/man/man5/virtual.5 b/postfix/man/man5/virtual.5 index 8ac87c937..ab3eb1ae9 100644 --- a/postfix/man/man5/virtual.5 +++ b/postfix/man/man5/virtual.5 @@ -125,16 +125,12 @@ tried in the order as listed in this manual page: .IP "\fIpattern result\fR" When \fIpattern\fR matches a mail address, replace it by the corresponding \fIresult\fR. +.IP "blank lines and comments" +Empty lines and whitespace-only lines are ignored, as +are lines whose first non-whitespace character is a `#'. .IP "multi-line text" -A line that starts with whitespace (space or tab) is a continuation -of the previous line. An empty line terminates the previous line, -as does a line that starts with non-whitespace (text or comment). A -comment line that starts with whitespace does not terminate multi-line -text. -.IP "comments" -The \fB#\fR is recognized as the start of a comment, but only when it is -the first non-whitespace character on a line. A comment terminates -at the end of the line, even when the next line starts with whitespace. +A logical line starts with non-whitespace text. A line that +starts with whitespace continues a logical line. .PP With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, patterns are tried in the order as diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index aea27968d..f4b5b9d55 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -76,16 +76,16 @@ the RFC822-style address forms with comments that Sendmail allows. Support older Microsoft clients that mis-implement the AUTH protocol, and that expect an EHLO response of "250 AUTH=list" instead of "250 AUTH list". +.IP \fBsmtpd_noop_commands\fR +List of commands that are treated as NOOP (no operation) commands, +without any parameter syntax checking and without any state change. +This list overrides built-in command definitions. .SH "Content inspection controls" .IP \fBcontent_filter\fR The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the result back into Postfix. This parameter uses the same syntax as the right-hand side of a Postfix transport table. -.IP \fBsmtpd_noop_commands\fR -List of commands that are treated as NOOP (no operation) commands, -without any parameter syntax checking and without any state change. -This list overrides built-in command definitions. .SH "Authentication controls" .IP \fBenable_sasl_authentication\fR Enable per-session authentication as per RFC 2554 (SASL). @@ -218,6 +218,9 @@ trusted backup MX hosts. Declares the name of zero or more parameters that contain a list of UCE restrictions. The names of these parameters can then be used instead of the restriction lists that they represent. +.IP \fBsmtpd_null_access_lookup_key\fR +The lookup key to be used in SMTPD access tables instead of the +null sender address. A null sender address cannot be looked up. .IP \fBmaps_rbl_domains\fR List of DNS domains that publish the addresses of blacklisted hosts. diff --git a/postfix/proto/access b/postfix/proto/access index 55842b6eb..a9559901b 100644 --- a/postfix/proto/access +++ b/postfix/proto/access @@ -30,16 +30,12 @@ # .IP "\fIpattern action\fR" # When \fIpattern\fR matches a mail address, domain or host address, # perform the corresponding \fIaction\fR. +# .IP "blank lines and comments" +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP "multi-line text" -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. -# .IP "comments" -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # PATTERNS # .ad # .fi diff --git a/postfix/proto/aliases b/postfix/proto/aliases index 8922c01f5..4a53b7987 100644 --- a/postfix/proto/aliases +++ b/postfix/proto/aliases @@ -34,15 +34,11 @@ # .ti +5 # \fIname\fR: \fIvalue1\fR, \fIvalue2\fR, \fI...\fR # .IP \(bu -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP \(bu -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .PP # The \fIname\fR is a local address (no domain part). # Use double quotes when the name contains any special characters diff --git a/postfix/proto/canonical b/postfix/proto/canonical index c803429c7..60a760548 100644 --- a/postfix/proto/canonical +++ b/postfix/proto/canonical @@ -45,16 +45,12 @@ # .IP "\fIpattern result\fR" # When \fIpattern\fR matches a mail address, replace it by the # corresponding \fIresult\fR. +# .IP "blank lines and comments" +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP "multi-line text" -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. -# .IP "comments" -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .PP # With lookups from indexed files such as DB or DBM, or from networked # tables such as NIS, LDAP or SQL, patterns are tried in the order as diff --git a/postfix/proto/pcre_table b/postfix/proto/pcre_table index 8579f8974..69c8488b2 100644 --- a/postfix/proto/pcre_table +++ b/postfix/proto/pcre_table @@ -18,16 +18,12 @@ # .IP "\fIpattern result\fR" # When \fIpattern\fR matches a search string, use the corresponding # \fIresult\fR. +# .IP "blank lines and comments" +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP "multi-line text" -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. -# .IP "comments" -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .PP # Each pattern is a perl-like regular expression. The expression # delimiter can be any character, except whitespace or characters diff --git a/postfix/proto/regexp_table b/postfix/proto/regexp_table index be13704e3..bd6cb7f72 100644 --- a/postfix/proto/regexp_table +++ b/postfix/proto/regexp_table @@ -18,16 +18,12 @@ # .IP "\fIpattern result\fR" # When \fIpattern\fR matches a search string, use the corresponding # \fIresult\fR. +# .IP "blank lines and comments" +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP "multi-line text" -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. -# .IP "comments" -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .IP "\fIpattern1!pattern2 result\fR" # Matches \fIpattern1\fR but not \fIpattern2\fR. # .PP diff --git a/postfix/proto/relocated b/postfix/proto/relocated index 6b916223e..6f3336658 100644 --- a/postfix/proto/relocated +++ b/postfix/proto/relocated @@ -36,15 +36,11 @@ # Where \fInew_location\fR specifies contact information such as # an email address, or perhaps a street address or telephone number. # .IP \(bu -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP \(bu -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .PP # With lookups from indexed files such as DB or DBM, or from networked # tables such as NIS, LDAP or SQL, the \fIkey\fR field is one of the diff --git a/postfix/proto/transport b/postfix/proto/transport index 4e95106c5..16f910ff9 100644 --- a/postfix/proto/transport +++ b/postfix/proto/transport @@ -30,16 +30,12 @@ # .IP "\fIpattern result\fR" # When \fIpattern\fR matches the domain, use the corresponding # \fIresult\fR. +# .IP "blank lines and comments" +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP "multi-line text" -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. -# .IP "comments" -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .PP # With lookups from indexed files such as DB or DBM, or from networked # tables such as NIS, LDAP or SQL, patterns are tried in the order as diff --git a/postfix/proto/virtual b/postfix/proto/virtual index 84c65b685..9f56d0d63 100644 --- a/postfix/proto/virtual +++ b/postfix/proto/virtual @@ -113,16 +113,12 @@ # .IP "\fIpattern result\fR" # When \fIpattern\fR matches a mail address, replace it by the # corresponding \fIresult\fR. +# .IP "blank lines and comments" +# Empty lines and whitespace-only lines are ignored, as +# are lines whose first non-whitespace character is a `#'. # .IP "multi-line text" -# A line that starts with whitespace (space or tab) is a continuation -# of the previous line. An empty line terminates the previous line, -# as does a line that starts with non-whitespace (text or comment). A -# comment line that starts with whitespace does not terminate multi-line -# text. -# .IP "comments" -# The \fB#\fR is recognized as the start of a comment, but only when it is -# the first non-whitespace character on a line. A comment terminates -# at the end of the line, even when the next line starts with whitespace. +# A logical line starts with non-whitespace text. A line that +# starts with whitespace continues a logical line. # .PP # With lookups from indexed files such as DB or DBM, or from networked # tables such as NIS, LDAP or SQL, patterns are tried in the order as diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 9e517fc92..019a0fe89 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -218,9 +218,10 @@ static const char *check_myhostname(void) name = get_hostname(); if ((dot = strchr(name, '.')) == 0) { if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0) - msg_fatal("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf", - name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir); - name = concatenate(name, ".", domain, (char *) 0); + msg_warn("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf", + name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir); + else + name = concatenate(name, ".", domain, (char *) 0); } return (name); } diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 6818a56b9..b1d5b884c 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1175,6 +1175,10 @@ extern int var_smtpd_delay_reject; #define REJECT_UNAUTH_PIPE "reject_unauth_pipelining" +#define VAR_SMTPD_NULL_KEY "smtpd_null_access_lookup_key" +#define DEF_SMTPD_NULL_KEY "" +extern char *var_smtpd_null_key; + /* * Heuristic to reject most unknown recipients at the SMTP port. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index d69188498..01b6c03bb 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-20011217" +#define DEF_MAIL_VERSION "Snapshot-20011223" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/global/off_cvt.c b/postfix/src/global/off_cvt.c index 95a689f14..30680187c 100644 --- a/postfix/src/global/off_cvt.c +++ b/postfix/src/global/off_cvt.c @@ -27,10 +27,6 @@ /* Buffer for storage of the result of conversion to string. /* .IP offset /* Non-negative off_t value to be converted to string. -/* BUGS -/* The string to number conversion routine has no reliable way to -/* detect an overflow error, so the result may be much smaller -/* than the number specified in the input. /* DIAGNOSTICS /* Panic: negative offset /* LICENSE @@ -70,20 +66,20 @@ off_t off_cvt_string(const char *str) { int ch; off_t result; + off_t last; /* * We're not doing this often, so simplicity has precedence over - * performance. XXX Need a portable way to correctly detect overflow. - * Bear in mind that an off_t is not necessarily a long integer, so using - * raw bit patterns is not going to be a portable solution. + * performance. */ - for (result = 0; (ch = *(unsigned char *) str) != 0; str++) { + for (last = result = 0; (ch = *(unsigned char *) str) != 0; str++) { if (!ISDIGIT(ch)) return (-1); result *= 10; - result += ch - '0'; - if (result < 0) + if (result < last) return (-1); + result += ch - '0'; + last = result; } return (result); } @@ -101,7 +97,7 @@ VSTRING *off_cvt_number(VSTRING *buf, off_t offset) * Sanity checks */ if (offset < 0) - msg_panic("off_cvt_number: negative offset %s", + msg_panic("off_cvt_number: negative offset -%s", STR(off_cvt_number(buf, -offset))); /* diff --git a/postfix/src/global/rec_type.c b/postfix/src/global/rec_type.c index 3b8f46f05..d1e630b37 100644 --- a/postfix/src/global/rec_type.c +++ b/postfix/src/global/rec_type.c @@ -48,7 +48,9 @@ REC_TYPE_NAME rec_type_names[] = { REC_TYPE_FROM, "sender", REC_TYPE_DONE, "done", REC_TYPE_RCPT, "recipient", + REC_TYPE_ORCP, "original recipient", REC_TYPE_WARN, "warning_message_time", + REC_TYPE_ATTR, "named attribute", REC_TYPE_MESG, "message_content", REC_TYPE_CONT, "unterminated", REC_TYPE_NORM, "normal_data", diff --git a/postfix/src/global/rec_type.h b/postfix/src/global/rec_type.h index 1a89d8c95..f1caaa466 100644 --- a/postfix/src/global/rec_type.h +++ b/postfix/src/global/rec_type.h @@ -33,7 +33,9 @@ #define REC_TYPE_FROM 'S' /* sender, required */ #define REC_TYPE_DONE 'D' /* delivered recipient, optional */ #define REC_TYPE_RCPT 'R' /* todo recipient, optional */ +#define REC_TYPE_ORCP 'O' /* original recipient, optional */ #define REC_TYPE_WARN 'W' /* warning message time */ +#define REC_TYPE_ATTR 'A' /* named attribute for extensions */ #define REC_TYPE_MESG 'M' /* start message records */ @@ -54,9 +56,9 @@ * record groups. The first member in each set is the record type that * indicates the end of that record group. */ -#define REC_TYPE_ENVELOPE "MCTFILSDRWV" +#define REC_TYPE_ENVELOPE "MCTFILSDROWVA" #define REC_TYPE_CONTENT "XLN" -#define REC_TYPE_EXTRACT "EDRPre" +#define REC_TYPE_EXTRACT "EDROPre" /* NOT A */ #define REC_TYPE_NOEXTRACT "E" /* diff --git a/postfix/src/global/tok822_parse.c b/postfix/src/global/tok822_parse.c index e8c1a9774..997a03554 100644 --- a/postfix/src/global/tok822_parse.c +++ b/postfix/src/global/tok822_parse.c @@ -566,7 +566,7 @@ int main(int unused_argc, char **unused_argv) TOK822 *list; VSTRING *buf = vstring_alloc(100); - while (readlline(buf, VSTREAM_IN, (int *) 0, READLL_KEEPNL)) { + while (readlline(buf, VSTREAM_IN, (int *) 0)) { while (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\n') { vstring_end(buf)[-1] = 0; vstring_truncate(buf, VSTRING_LEN(buf) - 1); diff --git a/postfix/src/master/master_ent.c b/postfix/src/master/master_ent.c index b8e0bff28..89aac56ab 100644 --- a/postfix/src/master/master_ent.c +++ b/postfix/src/master/master_ent.c @@ -242,7 +242,7 @@ MASTER_SERV *get_master_ent() * Skip blank lines and comment lines. */ do { - if (readlline(buf, master_fp, &master_line, READLL_STRIP_NOISE) == 0) { + if (readlline(buf, master_fp, &master_line) == 0) { vstring_free(buf); vstring_free(junk); return (0); diff --git a/postfix/src/master/master_wakeup.c b/postfix/src/master/master_wakeup.c index e5aa9d1e5..506bd11df 100644 --- a/postfix/src/master/master_wakeup.c +++ b/postfix/src/master/master_wakeup.c @@ -120,8 +120,9 @@ static void master_wakeup_timer_event(int unused_event, char *context) * - The postfix user and group ID must not be shared with other * applications (says the INSTALL documentation). * - * Result of a discussion with Michael Tokarev who claims het got - * his insights from Solar Designer. + * Result of a discussion with Michael Tokarev, who received his + * insights from Solar Designer, who tested Postfix with his + * "openwatch" kernel module. */ case MASTER_SERV_TYPE_FIFO: set_eugid(var_owner_uid, var_owner_gid); diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index 08c1fb5a7..6daf0fff6 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -198,17 +198,7 @@ static void postalias(char *map_type, char *path_name, * Add records to the database. */ lineno = 0; - while (readlline(line_buffer, source_fp, &lineno, READLL_STRIP_NOISE)) { - - /* - * Weird stuff. Normally, a line that begins with whitespace is a - * continuation of the previous line. - */ - if (ISSPACE(*STR(line_buffer))) { - msg_warn("%s, line %d: malformed line", - VSTREAM_PATH(source_fp), lineno); - continue; - } + while (readlline(line_buffer, source_fp, &lineno)) { /* * Tokenize the input, so that we do the right thing when a quoted diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index 2998b23de..c5f6a37a3 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -84,7 +84,7 @@ #include #include #include -#include +#include #include /* Global library. */ @@ -280,9 +280,10 @@ static void edit_parameters(int argc, char **argv) VSTRING *buf = vstring_alloc(100); VSTRING *key = vstring_alloc(10); char *cp; - char *value; + char *ep; + char *edit_key; + char *edit_val; HTABLE *table; - int first = 1; struct cvalue { char *value; int found; @@ -290,21 +291,42 @@ static void edit_parameters(int argc, char **argv) struct cvalue *cvalue; HTABLE_INFO **ht_info; HTABLE_INFO **ht; + int interesting; + + /* + * Ugly macros to make complex expressions less unreadable. + */ +#define SKIP(start, var, cond) \ + for (var = start; *var && (cond); var++); + +#define TRIM(s) { \ + char *p; \ + for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \ + *p = 0; \ + } /* * Store command-line parameters for quick lookup. */ table = htable_create(argc); while ((cp = *argv++) != 0) { - if ((value = split_at(cp, '=')) == 0 - || *(cp += strspn(cp, " \t\r\n")) == 0) - msg_fatal("edit requires \"key = value\" arguments"); - while (*value && ISSPACE(*value)) - value++; + if (strchr(cp, '\n') != 0) + msg_fatal("edit accepts no multi-line input"); + SKIP(cp, edit_key, ISSPACE(*edit_key)); /* find key begin */ + if (*edit_key == '#') + msg_fatal("edit accepts no comment input"); + SKIP(edit_key, ep, !ISSPACE(*ep) && *ep != '='); /* key end */ + SKIP(ep, cp, ISSPACE(*cp)); /* skip blanks before '=' */ + if (*cp != '=') /* need '=' */ + msg_fatal("missing '=' after attribute name: \"%s\"", edit_key); + *ep = 0; /* terminate key */ + cp++; /* skip over '=' */ + SKIP(cp, edit_val, ISSPACE(*edit_val)); /* skip leading blanks */ + TRIM(edit_val); /* trim trailing blanks */ cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue)); - cvalue->value = value; + cvalue->value = edit_val; cvalue->found = 0; - htable_enter(table, mystrtok(&cp, " \t\r\n"), (char *) cvalue); + htable_enter(table, edit_key, (char *) cvalue); } /* @@ -342,26 +364,29 @@ static void edit_parameters(int argc, char **argv) */ #define STR(x) vstring_str(x) - while (readlline(buf, src, (int *) 0, READLL_KEEP_NOISE)) { - cp = STR(buf); - if (first) { - first = 0; - if (ISSPACE(*cp)) - msg_fatal("%s: file starts with whitespace", path); - } - if (*cp == '#') { + interesting = 0; + while (vstring_get(buf, src) != VSTREAM_EOF) { + SKIP(STR(buf), cp, ISSPACE(*cp) /* including newline */ ); + /* Copy comment, all-whitespace, or empty line. */ + if (*cp == '#' || *cp == 0) { vstream_fputs(STR(buf), dst); - continue; } - cp += strspn(cp, " \t\r\n"); - vstring_strncpy(key, cp, strcspn(cp, " \t\r\n=")); - cvalue = (struct cvalue *) htable_find(table, STR(key)); - if (cvalue == 0) { - vstream_fputs(STR(buf), dst); - } else { - if (cvalue->found++ == 1) - msg_warn("%s: multiple entries for key %s", path, STR(key)); - vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value); + /* Copy or skip continued text. */ + else if (cp > STR(buf)) { + if (interesting == 0) + vstream_fputs(STR(buf), dst); + } + /* Copy or replace start of logical line. */ + else { + vstring_strncpy(key, cp, strcspn(cp, " \t\r\n=")); + cvalue = (struct cvalue *) htable_find(table, STR(key)); + if ((interesting = !!cvalue) != 0) { + if (cvalue->found++ == 1) + msg_warn("%s: multiple entries for \"%s\"", path, STR(key)); + vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value); + } else { + vstream_fputs(STR(buf), dst); + } } } diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index c269549cf..a6a98dfae 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -208,35 +208,21 @@ static void postmap(char *map_type, char *path_name, * Add records to the database. */ lineno = 0; - while (readlline(line_buffer, source_fp, &lineno, READLL_STRIP_NOISE)) { - - /* - * Skip comments. - */ - if (*STR(line_buffer) == '#') - continue; + while (readlline(line_buffer, source_fp, &lineno)) { /* * Split on the first whitespace character, then trim leading and * trailing whitespace from key and value. */ key = STR(line_buffer); - value = STR(line_buffer) + strcspn(STR(line_buffer), " \t\r\n"); + value = key + strcspn(key, " \t\r\n"); if (*value) *value++ = 0; - while (ISSPACE(*key)) - key++; while (ISSPACE(*value)) value++; trimblanks(key, 0)[0] = 0; trimblanks(value, 0)[0] = 0; - /* - * Skip empty lines, or lines with whitespace characters only. - */ - if (*key == 0 && *value == 0) - continue; - /* * Enforce the "key whitespace value" format. Disallow missing keys * or missing values. diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 90c9b772d..81990e8a2 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -52,6 +52,7 @@ typedef struct SMTP_STATE { VSTRING *sasl_decoded; /* decoding buffer */ sasl_callback_t *sasl_callbacks; /* stateful callbacks */ #endif + off_t size_limit; /* server limit or unknown */ } SMTP_STATE; #define SMTP_FEATURE_ESMTP (1<<0) diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 9f9201569..35c2046d6 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -237,8 +237,16 @@ int smtp_helo(SMTP_STATE *state) state->features |= SMTP_FEATURE_8BITMIME; else if (strcasecmp(word, "PIPELINING") == 0) state->features |= SMTP_FEATURE_PIPELINING; - else if (strcasecmp(word, "SIZE") == 0) + else if (strcasecmp(word, "SIZE") == 0) { state->features |= SMTP_FEATURE_SIZE; + if ((word = mystrtok(&words, " \t=")) != 0) { + if (!alldig(word)) + msg_warn("bad size limit \"%s\" in EHLO reply from %s", + word, session->namaddr); + else + state->size_limit = off_cvt_string(word); + } + } #ifdef USE_SASL_AUTH else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0) smtp_sasl_helo_auth(state, words); @@ -311,6 +319,19 @@ int smtp_xfer(SMTP_STATE *state) #define SENDING_MAIL \ (recv_state <= SMTP_STATE_DOT) + /* + * See if we should even try to send this message at all. This code sits + * here rather than in the EHLO processing code, because of future SMTP + * connection caching. + */ + if (state->size_limit > 0 && state->size_limit < request->data_size) { + smtp_mesg_fail(state, resp->code, + "message size %lu exceeds size limit %.0f of server %s", + request->data_size, (double) state->size_limit, + session->namaddr); + return (0); + } + /* * We use SMTP command pipelining if the server said it supported it. * Since we use blocking I/O, RFC 2197 says that we should inspect the diff --git a/postfix/src/smtp/smtp_state.c b/postfix/src/smtp/smtp_state.c index 790bdfa6b..2c4cad35c 100644 --- a/postfix/src/smtp/smtp_state.c +++ b/postfix/src/smtp/smtp_state.c @@ -68,6 +68,7 @@ SMTP_STATE *smtp_state_alloc(void) #ifdef USE_SASL_AUTH smtp_sasl_connect(state); #endif + state->size_limit = 0; return (state); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index eb00514bc..eaa1c3887 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -62,16 +62,16 @@ /* Support older Microsoft clients that mis-implement the AUTH /* protocol, and that expect an EHLO response of "250 AUTH=list" /* instead of "250 AUTH list". +/* .IP \fBsmtpd_noop_commands\fR +/* List of commands that are treated as NOOP (no operation) commands, +/* without any parameter syntax checking and without any state change. +/* This list overrides built-in command definitions. /* .SH "Content inspection controls" /* .IP \fBcontent_filter\fR /* The name of a mail delivery transport that filters mail and that /* either bounces mail or re-injects the result back into Postfix. /* This parameter uses the same syntax as the right-hand side of /* a Postfix transport table. -/* .IP \fBsmtpd_noop_commands\fR -/* List of commands that are treated as NOOP (no operation) commands, -/* without any parameter syntax checking and without any state change. -/* This list overrides built-in command definitions. /* .SH "Authentication controls" /* .IP \fBenable_sasl_authentication\fR /* Enable per-session authentication as per RFC 2554 (SASL). @@ -204,6 +204,9 @@ /* Declares the name of zero or more parameters that contain a /* list of UCE restrictions. The names of these parameters can /* then be used instead of the restriction lists that they represent. +/* .IP \fBsmtpd_null_access_lookup_key\fR +/* The lookup key to be used in SMTPD access tables instead of the +/* null sender address. A null sender address cannot be looked up. /* .IP \fBmaps_rbl_domains\fR /* List of DNS domains that publish the addresses of blacklisted /* hosts. @@ -375,6 +378,7 @@ bool var_broken_auth_clients; char *var_perm_mx_networks; char *var_smtpd_snd_auth_maps; char *var_smtpd_noop_cmds; +char *var_smtpd_null_key; /* * Global state, for stand-alone mode queue file cleanup. When this is @@ -667,8 +671,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) state->msg_size = 0; /* - * Sanity checks. XXX Ignore bad SIZE= values until we can reliably and - * portably detect overflows while converting from string to off_t. + * Sanity checks. * * XXX 2821 pedantism: Section 4.1.2 says that SMTP servers that receive a * command in which invalid character codes have been employed, and for @@ -708,8 +711,18 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) || strcasecmp(arg, "BODY=7BIT") == 0) { /* void */ ; } else if (strncasecmp(arg, "SIZE=", 5) == 0) { - if ((state->msg_size = off_cvt_string(arg + 5)) < 0) - state->msg_size = 0; + /* Reject non-numeric size. */ + if (!alldig(arg + 5)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad message size syntax"); + return (-1); + } + /* Reject size overflow. */ + if ((state->msg_size = off_cvt_string(arg + 5)) < 0) { + smtpd_chat_reply(state, "552 Message size exceeds file system imposed limit"); + state->error_mask |= MAIL_ERROR_POLICY; + return (-1); + } #ifdef USE_SASL_AUTH } else if (var_smtpd_sasl_enable && strncasecmp(arg, "AUTH=", 5) == 0) { if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) { @@ -1645,6 +1658,7 @@ int main(int argc, char **argv) VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 0, 0, VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0, VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0, + VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0, 0, }; diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index e3283c067..2ff7e222d 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -1449,7 +1449,7 @@ static int check_table_result(SMTPD_STATE *state, const char *table, * All-numeric result probably means OK - some out-of-band authentication * mechanism uses this as time stamp. */ - if (*value && value[strspn(value, "0123456789")] == 0) + if (alldig(value)) return (SMTPD_CHECK_OK); /* @@ -1865,7 +1865,7 @@ static int reject_sender_login_mismatch(SMTPD_STATE *state, const char *sender) if (login) { if (owner == 0 || strcasecmp(login, owner) != 0) return (smtpd_check_reject(state, MAIL_ERROR_POLICY, - "553 <%s>: Sender address rejected: not owned by username %s", + "553 <%s>: Sender address rejected: not owned by user %s", sender, login)); } else { if (owner) @@ -2027,6 +2027,10 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, status = check_mail_access(state, *cpp, state->sender, &found, state->sender, SMTPD_NAME_SENDER, def_acl); + if (state->sender && !*state->sender) + status = check_access(state, *cpp, var_smtpd_null_key, FULL, + &found, state->sender, + SMTPD_NAME_SENDER, def_acl); } else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) { if (state->sender && *state->sender) status = reject_unknown_address(state, state->sender, @@ -2529,6 +2533,8 @@ char *var_relocated_maps; char *var_local_rcpt_maps; char *var_perm_mx_networks; char *var_par_dom_match; +char *var_smtpd_null_key; +char *var_smtpd_snd_auth_maps; typedef struct { char *name; @@ -2552,6 +2558,8 @@ static STRING_TABLE string_table[] = { VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, + VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, + VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, }; @@ -2652,7 +2660,7 @@ static int int_update(char **argv) typedef struct { char *name; ARGV **target; -} REST_TABLE; +} REST_TABLE; static REST_TABLE rest_table[] = { "client_restrictions", &client_restrctions, @@ -2749,7 +2757,7 @@ VSTRING *canon_addr_internal(VSTRING *result, const char *addr) { if (addr == STR(result)) msg_panic("canon_addr_internal: result clobbers input"); - if (strchr(addr, '@') == 0) + if (*addr && strchr(addr, '@') == 0) msg_fatal("%s: address rewriting is disabled", addr); vstring_strcpy(result, addr); } @@ -2787,6 +2795,7 @@ int main(int argc, char **argv) ARGV *args; char *bp; char *resp; + char *addr; /* * Initialization. Use dummies for client information. @@ -2918,18 +2927,29 @@ int main(int argc, char **argv) /* * Try restrictions. */ +#define TRIM_ADDR(src, res) { \ + if (*(res = src) == '<') { \ + res += strlen(res) - 1; \ + if (*res == '>') \ + *res = 0; \ + res = src + 1; \ + } \ + } + if (strcasecmp(args->argv[0], "helo") == 0) { state.where = "HELO"; resp = smtpd_check_helo(&state, args->argv[1]); UPDATE_STRING(state.helo_name, args->argv[1]); } else if (strcasecmp(args->argv[0], "mail") == 0) { state.where = "MAIL"; - resp = smtpd_check_mail(&state, args->argv[1]); - UPDATE_STRING(state.sender, args->argv[1]); + TRIM_ADDR(args->argv[1], addr); + UPDATE_STRING(state.sender, addr); + resp = smtpd_check_mail(&state, addr); } else if (strcasecmp(args->argv[0], "rcpt") == 0) { state.where = "RCPT"; - (resp = smtpd_check_rcpt(&state, args->argv[1])) - || (resp = smtpd_check_rcptmap(&state, args->argv[1])); + TRIM_ADDR(args->argv[1], addr); + (resp = smtpd_check_rcpt(&state, addr)) + || (resp = smtpd_check_rcptmap(&state, addr)); } break; diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index f345644cc..fccaead71 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -1,8 +1,8 @@ SHELL = /bin/sh -SRCS = argv.c argv_split.c attr_print0.c attr_print64.c attr_scan0.c \ - attr_scan64.c base64_code.c basename.c binhash.c chroot_uid.c \ - clean_env.c close_on_exec.c concatenate.c ctable.c dict.c \ - dict_alloc.c dict_db.c dict_dbm.c dict_debug.c dict_env.c \ +SRCS = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \ + attr_scan0.c attr_scan64.c base64_code.c basename.c binhash.c \ + chroot_uid.c clean_env.c close_on_exec.c concatenate.c ctable.c \ + dict.c dict_alloc.c dict_db.c dict_dbm.c dict_debug.c dict_env.c \ dict_ht.c dict_ldap.c dict_mysql.c dict_ni.c dict_nis.c \ dict_nisplus.c dict_open.c dict_pcre.c dict_regexp.c dict_static.c \ dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \ @@ -27,10 +27,10 @@ SRCS = argv.c argv_split.c attr_print0.c attr_print64.c attr_scan0.c \ valid_hostname.c vbuf.c vbuf_print.c vstream.c vstream_popen.c \ vstring.c vstring_vstream.c watchdog.c writable.c write_buf.c \ write_wait.c -OBJS = argv.o argv_split.o attr_print0.o attr_print64.o attr_scan0.o \ - attr_scan64.o base64_code.o basename.o binhash.o chroot_uid.o \ - clean_env.o close_on_exec.o concatenate.o ctable.o dict.o \ - dict_alloc.o dict_db.o dict_dbm.o dict_debug.o dict_env.o \ +OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \ + attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \ + chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \ + dict.o dict_alloc.o dict_db.o dict_dbm.o dict_debug.o dict_env.o \ dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ dict_nisplus.o dict_open.o dict_pcre.o dict_regexp.o dict_static.o \ dict_tcp.o dict_unix.o dir_forest.o doze.o duplex_pipe.o \ @@ -387,9 +387,14 @@ dict_test: dict_open testdb dict_test.in dict_test.ref ../postmap/postmap -n testdb ./dict_open $(DB_TYPE):testdb write < dict_test.in > dict_test.tmp 2>&1 diff dict_test.ref dict_test.tmp - rm -f testdb.db testdb.dir testdb.pag + rm -f testdb.db testdb.dir testdb.pag dict_test.tmp # do not edit below this line - it is generated by 'make depend' +alldig.o: alldig.c +alldig.o: sys_defs.h +alldig.o: stringops.h +alldig.o: vstring.h +alldig.o: vbuf.h argv.o: argv.c argv.o: sys_defs.h argv.o: mymalloc.h @@ -964,6 +969,7 @@ readable.o: msg.h readable.o: iostuff.h readlline.o: readlline.c readlline.o: sys_defs.h +readlline.o: msg.h readlline.o: vstream.h readlline.o: vbuf.h readlline.o: vstring.h diff --git a/postfix/src/util/alldig.c b/postfix/src/util/alldig.c new file mode 100644 index 000000000..c4815f68c --- /dev/null +++ b/postfix/src/util/alldig.c @@ -0,0 +1,48 @@ +/*++ +/* NAME +/* alldig 3 +/* SUMMARY +/* predicate if string is all numerical +/* SYNOPSIS +/* #include +/* +/* int alldig(string) +/* const char *string; +/* DESCRIPTION +/* alldig() determines if its argument is an all-numerical string. +/* SEE ALSO +/* An alldig() routine appears in Brian W. Kernighan, P.J. Plauger: +/* "Software Tools", Addison-Wesley 1976. +/* 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 + +/* alldig - return true if string is all digits */ + +int alldig(const char *string) +{ + const char *cp; + + if (*string == 0) + return (0); + for (cp = string; *cp != 0; cp++) + if (!ISDIGIT(*cp)) + return (0); + return (1); +} diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index 62163909f..80184516d 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -394,17 +394,16 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp) buf = vstring_alloc(100); lineno = 0; - while (readlline(buf, fp, &lineno, READLL_STRIP_NOISE)) { + while (readlline(buf, fp, &lineno)) { start = STR(buf); SKIP(start, member, ISSPACE(*member)); /* find member begin */ SKIP(member, ep, !ISSPACE(*ep) && *ep != '='); /* find member end */ SKIP(ep, cp, ISSPACE(*cp)); /* skip blanks before '=' */ - if (*cp && *cp != '=') /* need '=' or end of string */ - msg_fatal("%s, line %d: whitespace in attribute name: \"%s\"", + if (*cp != '=') /* need '=' */ + msg_fatal("%s, line %d: missing '=' after attribute name: \"%s\"", VSTREAM_PATH(fp), lineno, member); - if (*cp) - cp++; /* skip over '=' */ *ep = 0; /* terminate member name */ + cp++; /* skip over '=' */ SKIP(cp, val, ISSPACE(*val)); /* skip leading blanks */ TRIM(val); /* trim trailing blanks */ dict_update(dict_name, member, val); diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c index 3d24f5ff4..52a5dddc1 100644 --- a/postfix/src/util/dict_open.c +++ b/postfix/src/util/dict_open.c @@ -343,6 +343,7 @@ static NORETURN usage(char *myname) int main(int argc, char **argv) { VSTRING *keybuf = vstring_alloc(1); + VSTRING *inbuf = vstring_alloc(1); DICT *dict; char *dict_name; int open_flags; @@ -378,13 +379,16 @@ int main(int argc, char **argv) dict_name = argv[optind]; dict = dict_open(dict_name, open_flags, DICT_FLAG_LOCK); dict_register(dict_name, dict); - while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) { - bufp = vstring_str(keybuf); - if ((cmd = mystrtok(&bufp, " ")) == 0) + while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { + bufp = vstring_str(inbuf); + if ((cmd = mystrtok(&bufp, " ")) == 0 || *bufp == 0) { + vstream_printf("usage: del key|get key|put key=value\n"); + vstream_fflush(VSTREAM_OUT); continue; + } if (dict_changed()) msg_warn("dictionary has changed"); - key = mystrtok(&bufp, " ="); + key = vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))); value = mystrtok(&bufp, " ="); if (strcmp(cmd, "del") == 0 && key && !value) { if (dict_del(dict, key)) @@ -408,6 +412,7 @@ int main(int argc, char **argv) vstream_fflush(VSTREAM_OUT); } vstring_free(keybuf); + vstring_free(inbuf); dict_close(dict); return (0); } diff --git a/postfix/src/util/dict_pcre.c b/postfix/src/util/dict_pcre.c index 15482013f..1cc0f19f9 100644 --- a/postfix/src/util/dict_pcre.c +++ b/postfix/src/util/dict_pcre.c @@ -257,7 +257,7 @@ DICT *dict_pcre_open(const char *map, int unused_flags, int dict_flags) if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) { msg_fatal("open %s: %m", map); } - while (readlline(line_buffer, map_fp, &lineno, READLL_STRIP_NOISE)) { + while (readlline(line_buffer, map_fp, &lineno)) { p = vstring_str(line_buffer); trimblanks(p, 0)[0] = 0; /* Trim space at end */ diff --git a/postfix/src/util/dict_regexp.c b/postfix/src/util/dict_regexp.c index 3c0c7a3bb..732208ca6 100644 --- a/postfix/src/util/dict_regexp.c +++ b/postfix/src/util/dict_regexp.c @@ -356,7 +356,7 @@ DICT *dict_regexp_open(const char *map, int unused_flags, int dict_flags) if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) { msg_fatal("open %s: %m", map); } - while (readlline(line_buffer, map_fp, &lineno, READLL_STRIP_NOISE)) { + while (readlline(line_buffer, map_fp, &lineno)) { p = vstring_str(line_buffer); trimblanks(p, 0)[0] = 0; /* Trim space at end */ diff --git a/postfix/src/util/fifo_trigger.c b/postfix/src/util/fifo_trigger.c index feff2e421..841011a1b 100644 --- a/postfix/src/util/fifo_trigger.c +++ b/postfix/src/util/fifo_trigger.c @@ -13,7 +13,8 @@ /* int timeout; /* DESCRIPTION /* fifo_trigger() wakes up the named fifo server by writing -/* the contents of the specified buffer to the fifo. +/* the contents of the specified buffer to the fifo. There is +/* no guarantee that the written data will actually be received. /* /* Arguments: /* .IP service @@ -26,7 +27,7 @@ /* Deadline in seconds. Specify a value <= 0 to disable /* the time limit. /* DIAGNOSTICS -/* The result is zero in case of success, -1 in case of problems. +/* The result is zero when the fifo could be opened, -1 otherwise. /* BUGS /* LICENSE /* .ad @@ -56,21 +57,27 @@ int fifo_trigger(const char *service, const char *buf, int len, int timeout) { + static VSTRING *why; char *myname = "fifo_trigger"; VSTREAM *fp; int fd; + if (why == 0) + why = vstring_alloc(1); + /* * Write the request to the service fifo. According to POSIX, the open * shall always return immediately, and shall return an error when no * process is reading from the FIFO. * - * Use safe_open() so that we don't follow arbitrary symlinks. + * Use safe_open() so that we don't follow symlinks, and so that we don't + * open files with multiple hard links. We're not (yet) going to bother + * the caller with safe_open() specific quirks such as the why argument. */ if ((fp = safe_open(service, O_WRONLY | O_NONBLOCK, 0, - (struct stat *) 0, -1, -1, (VSTRING *) 0)) == 0) { + (struct stat *) 0, -1, -1, why)) == 0) { if (msg_verbose) - msg_info("%s: open %s: %m", myname, service); + msg_info("%s: open %s: %s", myname, service, vstring_str(why)); return (-1); } fd = vstream_fileno(fp); diff --git a/postfix/src/util/readlline.c b/postfix/src/util/readlline.c index 977db3ed9..bb05585de 100644 --- a/postfix/src/util/readlline.c +++ b/postfix/src/util/readlline.c @@ -6,40 +6,34 @@ /* SYNOPSIS /* #include /* -/* VSTRING *readlline(buf, fp, lineno, strip_noise) +/* VSTRING *readlline(buf, fp, lineno) /* VSTRING *buf; /* VSTREAM *fp; /* int *lineno; -/* int strip_noise; /* DESCRIPTION /* readlline() reads one logical line from the named stream. -/* -/* A line that starts with whitespace (space or tab) is a continuation -/* of the previous line. An empty line terminates the previous line, -/* as does a line that starts with non-whitespace (text or comment). A -/* comment line that starts with whitespace does not terminate multi-line -/* text. -/* -/* The # is recognized as the start of a comment, but only when it is -/* the first non-whitespace character on a line. A comment terminates -/* at the end of the line, even when the next line starts with whitespace. -/* +/* .IP "blank lines and comments" +/* Empty lines and whitespace-only lines are ignored, as +/* are lines whose first non-whitespace character is a `#'. +/* .IP "multi-line text" +/* A logical line starts with non-whitespace text. A line that +/* starts with whitespace continues a logical line. +/* .PP /* The result value is the input buffer argument or a null pointer /* when no input is found. /* /* Arguments: /* .IP buf -/* A variable-length buffer for input. +/* A variable-length buffer for input. The result is null terminated. /* .IP fp /* Handle to an open stream. /* .IP lineno /* A null pointer, or a pointer to an integer that is incremented -/* after reading a newline. -/* .IP strip_noise -/* Non-zero to strip newlines, empty lines and comments from the result. -/* For convenience, READLL_STRIP_NOISE requests stripping while -/* READLL_KEEP_NOISE disables stripping. +/* after reading a newline character. /* .RE +/* DIAGNOSTICS +/* Warning: a continuation line that does not continue preceding text. +/* The invalid input is ignored, to avoid complicating caller code. /* LICENSE /* .ad /* .fi @@ -54,83 +48,73 @@ /* System library. */ #include +#include /* Utility library. */ +#include "msg.h" #include "vstream.h" #include "vstring.h" #include "readlline.h" - /* - * Comment stripper states. States are (1)->(2) or (1)->(3) as we proceed - * through a line of text. - */ -#define READLL_STATE_WANT_LWSP 1 /* expecting leading whitespace */ -#define READLL_STATE_IN_COMMENT 2 /* inside comment */ -#define READLL_STATE_IN_TEXT 3 /* inside other text */ - -#define LWSP_CHARACTER(ch) ((ch) == ' ' || (ch) == '\t') - #define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) +#define END(x) vstring_end(x) /* readlline - read one logical line */ -VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno, int strip_noise) +VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno) { int ch; int next; - int state; + int start; + char *cp; - /* - * Lines that start with whitespace continue the preceding line. Comments - * always terminate at the first newline. - */ VSTRING_RESET(buf); - if (strip_noise) - state = READLL_STATE_WANT_LWSP; - while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) { - /* Skip leading whitespace that doesn't continue a previous line. */ - if (VSTRING_LEN(buf) == 0 && LWSP_CHARACTER(ch)) - continue; - if (ch == '\n') { - if (lineno) - *lineno += 1; - if (strip_noise) { - state = READLL_STATE_WANT_LWSP; - /* Skip empty, whitespace, or comment line before text. */ - if (VSTRING_LEN(buf) == 0) - continue; - } else { - VSTRING_ADDCH(buf, ch); - /* Terminate empty, whitespace, or comment line before text. */ - if (VSTRING_LEN(buf) == 1 || STR(buf)[0] == '#') - break; - } - next = VSTREAM_GETC(fp); - /* Continue this line if the next line starts with whitespace. */ - if (LWSP_CHARACTER(next)) { - ch = next; - } else { - if (next != VSTREAM_EOF) - vstream_ungetc(fp, next); + /* + * Ignore comment lines, all whitespace lines, and empty lines. Terminate + * at EOF or at the beginning of the next logical line. + */ + for (;;) { + /* Read one line, possibly not newline terminated. */ + start = LEN(buf); + while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n') + VSTRING_ADDCH(buf, ch); + if (ch == '\n' && lineno != 0) + *lineno += 1; + /* Ignore comment line, all whitespace line, or empty line. */ + for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++) + /* void */ ; + if (cp == END(buf) || *cp == '#') + vstring_truncate(buf, start); + /* Terminate at EOF or at the beginning of the next logical line. */ + if (ch == VSTREAM_EOF) + break; + if (LEN(buf) > 0) { + if ((next = VSTREAM_GETC(fp)) != VSTREAM_EOF) + vstream_ungetc(fp, next); + if (next != '#' && !ISSPACE(next)) break; - } } - /* Update the comment stripping state machine. */ - if (strip_noise) { - if (state == READLL_STATE_WANT_LWSP) { - if (ch == '#') { - state = READLL_STATE_IN_COMMENT; - } else if (!LWSP_CHARACTER(ch)) { - state = READLL_STATE_IN_TEXT; - } - } - if (state == READLL_STATE_IN_COMMENT) - continue; - } - VSTRING_ADDCH(buf, ch); } + + /* + * Invalid input: continuing text without preceding text. Allowing this + * would complicate "postconf -e", which implements its own multi-line + * parsing routine. Do not abort, just warn, so that critical programs + * like postmap do not leave behind a truncated table. + */ + if (LEN(buf) > 0 && ISSPACE(*STR(buf))) { + msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"", + VSTREAM_PATH(fp), STR(buf), + LEN(buf) > 100 ? "..." : ""); + return (readlline(buf, fp, lineno)); + } + + /* + * Done. + */ VSTRING_TERMINATE(buf); - return (VSTRING_LEN(buf) || ch == '\n' ? buf : 0); + return (LEN(buf) > 0 ? buf : 0); } diff --git a/postfix/src/util/readlline.h b/postfix/src/util/readlline.h index dbeb95e4a..8a8bd5487 100644 --- a/postfix/src/util/readlline.h +++ b/postfix/src/util/readlline.h @@ -20,10 +20,7 @@ /* * External interface. */ -extern VSTRING *readlline(VSTRING *, VSTREAM *, int *, int); - -#define READLL_STRIP_NOISE 1 -#define READLL_KEEP_NOISE 0 +extern VSTRING *readlline(VSTRING *, VSTREAM *, int *); /* LICENSE /* .ad diff --git a/postfix/src/util/safe_open.c b/postfix/src/util/safe_open.c index e1e88f8b4..d20c9404c 100644 --- a/postfix/src/util/safe_open.c +++ b/postfix/src/util/safe_open.c @@ -41,8 +41,9 @@ /* Panic: interface violations. /* /* A null result means there was a problem. The nature of the -/* problem is returned via the \fIwhy\fR buffer; some errors -/* cannot be reported via \fIerrno\fR. +/* problem is returned via the \fIwhy\fR buffer; when an error +/* cannot be reported via \fIerrno\fR, the generic value EPERM +/* (operation not permitted) is used instead. /* HISTORY /* .fi /* .ad @@ -54,7 +55,7 @@ /* be fooled by delaying the open() until the inode found with /* lstat() has been re-used for a sensitive file (article /* <20000103212443.A5807@monad.swb.de> posted to bugtraq on -/* Jan 3, 2000). This can be a concern for a set-uid process +/* Jan 3, 2000). This can be a concern for a set-ugid process /* that runs under the control of a user and that can be /* manipulated with start/stop signals. /* LICENSE @@ -113,8 +114,10 @@ static VSTREAM *safe_open_exist(const char *path, int flags, } else if (fstat_st->st_nlink != 1) { vstring_sprintf(why, "file has %d hard links", (int) fstat_st->st_nlink); + errno = EPERM; } else if (S_ISDIR(fstat_st->st_mode)) { vstring_sprintf(why, "file is a directory"); + errno = EISDIR; } /* @@ -135,10 +138,12 @@ static VSTREAM *safe_open_exist(const char *path, int flags, */ else if (lstat(path, &lstat_st) < 0) { vstring_sprintf(why, "file status changed unexpectedly: %m"); + errno = EPERM; } else if (S_ISLNK(lstat_st.st_mode)) { if (lstat_st.st_uid == 0) return (fp); vstring_sprintf(why, "file is a symbolic link"); + errno = EPERM; } else if (fstat_st->st_dev != lstat_st.st_dev || fstat_st->st_ino != lstat_st.st_ino #ifdef HAS_ST_GEN @@ -147,6 +152,7 @@ static VSTREAM *safe_open_exist(const char *path, int flags, || fstat_st->st_nlink != lstat_st.st_nlink || fstat_st->st_mode != lstat_st.st_mode) { vstring_sprintf(why, "file status changed unexpectedly"); + errno = EPERM; } /* @@ -158,9 +164,7 @@ static VSTREAM *safe_open_exist(const char *path, int flags, /* * End up here in case of fstat()/lstat() problems or inconsistencies. - * Reset errno to reduce confusion. */ - errno = 0; vstream_fclose(fp); return (0); } @@ -190,7 +194,7 @@ static VSTREAM *safe_open_create(const char *path, int flags, int mode, if (CHANGE_OWNER(user, group) && fchown(vstream_fileno(fp), user, group) < 0) { - vstring_sprintf(why, "cannot change file ownership: %m"); + msg_warn("%s: cannot change file ownership: %m", path); } /* diff --git a/postfix/src/util/stringops.h b/postfix/src/util/stringops.h index 1310d4cb0..ca6838058 100644 --- a/postfix/src/util/stringops.h +++ b/postfix/src/util/stringops.h @@ -30,6 +30,7 @@ extern char *translit(char *, const char *, const char *); extern char *basename(const char *); #endif extern VSTRING *unescape(VSTRING *, const char *); +extern int alldig(const char *); /* LICENSE /* .ad