mirror of
https://github.com/vdukhovni/postfix
synced 2025-09-03 15:45:24 +00:00
postfix-1.1.10-20020524
This commit is contained in:
committed by
Viktor Dukhovni
parent
f0d9a4857f
commit
5eb74275bf
6
postfix/.indent.pro
vendored
6
postfix/.indent.pro
vendored
@@ -51,6 +51,7 @@
|
|||||||
-TFILE
|
-TFILE
|
||||||
-TFORWARD_INFO
|
-TFORWARD_INFO
|
||||||
-THEADER_OPTS
|
-THEADER_OPTS
|
||||||
|
-THEADER_TOKEN
|
||||||
-THOST
|
-THOST
|
||||||
-THTABLE
|
-THTABLE
|
||||||
-THTABLE_INFO
|
-THTABLE_INFO
|
||||||
@@ -75,6 +76,11 @@
|
|||||||
-TMASTER_STATUS
|
-TMASTER_STATUS
|
||||||
-TMBLOCK
|
-TMBLOCK
|
||||||
-TMBOX
|
-TMBOX
|
||||||
|
-TMIME_ENCODING
|
||||||
|
-TMIME_INFO
|
||||||
|
-TMIME_STACK
|
||||||
|
-TMIME_STATE
|
||||||
|
-TMIME_TOKEN
|
||||||
-TMKMAP
|
-TMKMAP
|
||||||
-TMKMAP_OPEN_INFO
|
-TMKMAP_OPEN_INFO
|
||||||
-TMULTI_SERVER
|
-TMULTI_SERVER
|
||||||
|
@@ -6447,8 +6447,59 @@ Apologies for any names omitted.
|
|||||||
with "resolve_dequoted_address = no"). Victor Duchovny,
|
with "resolve_dequoted_address = no"). Victor Duchovny,
|
||||||
Morgan Stanley. File: smtpd/smtpd_check.c.
|
Morgan Stanley. File: smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
20020515
|
||||||
|
|
||||||
|
Workaround: flush the SMTP client output buffer when no
|
||||||
|
output has happened for 10+ seconds. This prevents the
|
||||||
|
socket from timing out, in case DNS CNAME expansion is
|
||||||
|
slow. Problem experienced by Alex Erdelyi, peregrine.com.
|
||||||
|
File: smtp/smtp_chat.c. We did the same thing for the SMTP
|
||||||
|
server years ago, and one wonders why the coin didn't drop
|
||||||
|
at the time that the SMTP client could suffer from a similar
|
||||||
|
problem.
|
||||||
|
|
||||||
|
20020517
|
||||||
|
|
||||||
|
Cleanup: Mailbox-Line: message header labels should be
|
||||||
|
X-Mailbox-Line: labels. Files: smtpd/smtpd.c, qmqpd/qmqpd.c.
|
||||||
|
|
||||||
|
20020515-21
|
||||||
|
|
||||||
|
Feature: new MIME parser, written from scratch, that recognizes
|
||||||
|
the structure of MIME encapsulated mail. MIME header scanning
|
||||||
|
now happens in header_checks, and are is faster than
|
||||||
|
body_checks could ever be. Thus also eliminates the problem
|
||||||
|
with multi-line MIME headers being matched one line at a
|
||||||
|
time. Files: global/mime_state.[hc], cleanup/cleanup_message.c.
|
||||||
|
|
||||||
|
20020521-22
|
||||||
|
|
||||||
|
Feature: 8-bit to quoted-printable conversion. First use in
|
||||||
|
the Postfix SMTP client. File: smtp/smtp_proto.c.
|
||||||
|
|
||||||
|
Logging: the Postfix SMTP and LMTP clients now report the
|
||||||
|
stage of the protocol when it reports a server reply.
|
||||||
|
File: smtp/smtp_proto.c, lmtp/lmtp_proto.c.
|
||||||
|
|
||||||
|
Bugfix: the SMTP server complained about ignored client
|
||||||
|
attributes in mail submitted with "sendmail -bs".
|
||||||
|
File: smtpd/smtpd.c.
|
||||||
|
|
||||||
|
20020525
|
||||||
|
|
||||||
|
Cleanup: broke out the header value parser from the MIME
|
||||||
|
processor so it can be used elsewhere. File:
|
||||||
|
global/header_token.c.
|
||||||
|
|
||||||
|
Cleanup needs an option to revert to old non-MIME
|
||||||
|
aware behavior - this must override the MIME header
|
||||||
|
match override.
|
||||||
|
|
||||||
Open problems:
|
Open problems:
|
||||||
|
|
||||||
|
Medium: old maildrop files are no longer readable by the
|
||||||
|
pickup service. Log a message that suggests a fix.
|
||||||
|
|
||||||
Low: all table lookups should consistently use internalized
|
Low: all table lookups should consistently use internalized
|
||||||
(unquoted) or externalized (quoted) forms as lookup keys.
|
(unquoted) or externalized (quoted) forms as lookup keys.
|
||||||
smtpd, qmgr, local, etc. use internalized forms as keys.
|
smtpd, qmgr, local, etc. use internalized forms as keys.
|
||||||
|
@@ -128,10 +128,11 @@ The second example is considerably more complex, but can give much
|
|||||||
better performance, and is less likely to bounce mail when the
|
better performance, and is less likely to bounce mail when the
|
||||||
machine runs into a resource problem. This approach uses content
|
machine runs into a resource problem. This approach uses content
|
||||||
filtering software that can receive and deliver mail via SMTP.
|
filtering software that can receive and deliver mail via SMTP.
|
||||||
|
|
||||||
You can expect to lose about a factor of two in Postfix performance
|
You can expect to lose about a factor of two in Postfix performance
|
||||||
for transit mail that arrives and leaves via SMTP, provided that
|
for transit mail (not delivered on the same machine) that arrives
|
||||||
you create no temporary files. Each temporary file adds another
|
and leaves via SMTP; and each temporary file created by the content
|
||||||
factor to the performance loss.
|
filter adds another factor to the performance loss.
|
||||||
|
|
||||||
We will set up a content filtering program that receives SMTP mail
|
We will set up a content filtering program that receives SMTP mail
|
||||||
via localhost port 10025, and that submits SMTP mail back into
|
via localhost port 10025, and that submits SMTP mail back into
|
||||||
@@ -158,18 +159,33 @@ To enable content filtering in this manner, specify in main.cf a
|
|||||||
new parameter:
|
new parameter:
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
/etc/postfix/main.cf:
|
||||||
content_filter = smtp:localhost:10025
|
content_filter = scan:localhost:10025
|
||||||
|
|
||||||
This causes Postfix to add one extra content filtering record to
|
This causes Postfix to add one extra content filtering record to
|
||||||
each incoming mail message, with content smtp:localhost:10025.
|
each incoming mail message, with content scan:localhost:10025.
|
||||||
You can use the same syntax as in the right-hand side of a Postfix
|
The content filtering records are added by the smtpd and pickup
|
||||||
transport table. The content filtering records are added by the
|
servers.
|
||||||
smtpd and pickup servers.
|
|
||||||
|
|
||||||
When a queue file has content filtering information, the queue
|
When a queue file has content filtering information, the queue
|
||||||
manager will deliver the mail to the specified content filter
|
manager will deliver the mail to the specified content filter
|
||||||
regardless of its final destination.
|
regardless of its final destination.
|
||||||
|
|
||||||
|
In this example, "scan" is an instance of the Postfix SMTP client
|
||||||
|
with slightly different configuration parameters. This is how
|
||||||
|
one would set up the service in the Postfix master.cf file:
|
||||||
|
|
||||||
|
/etc/postfix/master.cf:
|
||||||
|
scan unix - - n - 10 smtp
|
||||||
|
-o disable_dns_lookups=yes
|
||||||
|
|
||||||
|
Turning off DNS lookups at this point can make a great difference
|
||||||
|
in content filtering performance. It also isolates the content
|
||||||
|
filtering process from temporary outages in DNS service.
|
||||||
|
|
||||||
|
Instead of 10, use whatever limit is feasible for your machine.
|
||||||
|
Content inspection software can gobble up a lot of system resources,
|
||||||
|
so you don't want to have too much of it running at the same time.
|
||||||
|
|
||||||
The content filter can be set up with the Postfix spawn service,
|
The content filter can be set up with the Postfix spawn service,
|
||||||
which is the Postfix equivalent of inetd. For example, to instantiate
|
which is the Postfix equivalent of inetd. For example, to instantiate
|
||||||
up to 10 content filtering processes on demand:
|
up to 10 content filtering processes on demand:
|
||||||
@@ -263,7 +279,7 @@ into Postfix via localhost port 10026.
|
|||||||
: cleanup2/ | \smtp----->
|
: cleanup2/ | \smtp----->
|
||||||
: ^ v :
|
: ^ v :
|
||||||
: | v :
|
: | v :
|
||||||
: smtpd smtp :
|
: smtpd scan :
|
||||||
: 10026 | :
|
: 10026 | :
|
||||||
.......................|...........
|
.......................|...........
|
||||||
^ |
|
^ |
|
||||||
|
@@ -12,6 +12,13 @@ snapshot release). Patches change the patchlevel and the release
|
|||||||
date. Snapshots change only the release date, unless they include
|
date. Snapshots change only the release date, unless they include
|
||||||
the same bugfixes as a patch release.
|
the same bugfixes as a patch release.
|
||||||
|
|
||||||
|
Incompatible changes with Postfix snapshot 1.1.10-200205XX
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
Message headers in MIME attachments etc. are now matched by
|
||||||
|
header_checks instead of body_checks. Multi-line headers in MIME
|
||||||
|
attachments are now properly recognized.
|
||||||
|
|
||||||
Incompatible changes with Postfix snapshot 1.1.10-20020514
|
Incompatible changes with Postfix snapshot 1.1.10-20020514
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
|
@@ -55,6 +55,8 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
|
|
||||||
<b>STANDARDS</b>
|
<b>STANDARDS</b>
|
||||||
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
|
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
|
||||||
|
<a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a> (MIME: Format of Internet Message Bodies)
|
||||||
|
<a href="http://www.faqs.org/rfcs/rfc2046.html">RFC 2046</a> (MIME: Media Types)
|
||||||
|
|
||||||
<b>DIAGNOSTICS</b>
|
<b>DIAGNOSTICS</b>
|
||||||
Problems and transactions are logged to <b>syslogd</b>(8).
|
Problems and transactions are logged to <b>syslogd</b>(8).
|
||||||
@@ -76,14 +78,21 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
time, in chunks of at most line_length_limit bytes.
|
time, in chunks of at most line_length_limit bytes.
|
||||||
|
|
||||||
<b>header</b><i>_</i><b>checks</b>
|
<b>header</b><i>_</i><b>checks</b>
|
||||||
|
|
||||||
|
<b>mime</b><i>_</i><b>header</b><i>_</i><b>checks</b> (default: <b>$header</b><i>_</i><b>checks</b>)
|
||||||
|
|
||||||
|
<b>nested</b><i>_</i><b>header</b><i>_</i><b>checks</b> (default: <b>$header</b><i>_</i><b>checks</b>)
|
||||||
Lookup tables with content filters for message
|
Lookup tables with content filters for message
|
||||||
header lines. These filters see logical headers
|
header lines: respectively, these are applied to
|
||||||
one at a time, including headers that span multiple
|
the primary message headers (not including MIME
|
||||||
lines.
|
headers), to the MIME headers anywhere in the mes-
|
||||||
|
sage, and to the initial headers of attached mes-
|
||||||
|
sages. These filters see logical headers one at a
|
||||||
|
time, including headers that span multiple lines.
|
||||||
|
|
||||||
<b>Miscellaneous</b>
|
<b>Miscellaneous</b>
|
||||||
<b>always</b><i>_</i><b>bcc</b>
|
<b>always</b><i>_</i><b>bcc</b>
|
||||||
Address to send a copy of each message that enters
|
Address to send a copy of each message that enters
|
||||||
the system.
|
the system.
|
||||||
|
|
||||||
<b>hopcount</b><i>_</i><b>limit</b>
|
<b>hopcount</b><i>_</i><b>limit</b>
|
||||||
@@ -96,8 +105,8 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
|
|
||||||
<b>Address</b> <b>transformations</b>
|
<b>Address</b> <b>transformations</b>
|
||||||
<b>empty</b><i>_</i><b>address</b><i>_</i><b>recipient</b>
|
<b>empty</b><i>_</i><b>address</b><i>_</i><b>recipient</b>
|
||||||
The destination for undeliverable mail from <>.
|
The destination for undeliverable mail from <>.
|
||||||
This substitution is done before all other address
|
This substitution is done before all other address
|
||||||
rewriting.
|
rewriting.
|
||||||
|
|
||||||
<b>canonical</b><i>_</i><b>maps</b>
|
<b>canonical</b><i>_</i><b>maps</b>
|
||||||
@@ -113,16 +122,16 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
header sender addresses.
|
header sender addresses.
|
||||||
|
|
||||||
<b>masquerade</b><i>_</i><b>classes</b>
|
<b>masquerade</b><i>_</i><b>classes</b>
|
||||||
List of address classes subject to masquerading:
|
List of address classes subject to masquerading:
|
||||||
zero or more of <b>envelope</b><i>_</i><b>sender</b>, <b>envelope</b><i>_</i><b>recipi-</b>
|
zero or more of <b>envelope</b><i>_</i><b>sender</b>, <b>envelope</b><i>_</i><b>recipi-</b>
|
||||||
<b>ent</b>, <b>header</b><i>_</i><b>sender</b>, <b>header</b><i>_</i><b>recipient</b>.
|
<b>ent</b>, <b>header</b><i>_</i><b>sender</b>, <b>header</b><i>_</i><b>recipient</b>.
|
||||||
|
|
||||||
<b>masquerade</b><i>_</i><b>domains</b>
|
<b>masquerade</b><i>_</i><b>domains</b>
|
||||||
List of domains that hide their subdomain struc-
|
List of domains that hide their subdomain struc-
|
||||||
ture.
|
ture.
|
||||||
|
|
||||||
<b>masquerade</b><i>_</i><b>exceptions</b>
|
<b>masquerade</b><i>_</i><b>exceptions</b>
|
||||||
List of user names that are not subject to address
|
List of user names that are not subject to address
|
||||||
masquerading.
|
masquerading.
|
||||||
|
|
||||||
<b>virtual</b><i>_</i><b>maps</b>
|
<b>virtual</b><i>_</i><b>maps</b>
|
||||||
@@ -131,7 +140,7 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
|
|
||||||
<b>Resource</b> <b>controls</b>
|
<b>Resource</b> <b>controls</b>
|
||||||
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
|
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
|
||||||
Limit the number of envelope recipients that are
|
Limit the number of envelope recipients that are
|
||||||
remembered.
|
remembered.
|
||||||
|
|
||||||
<b>header</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
<b>header</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
||||||
@@ -140,11 +149,11 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
|
|
||||||
<b>in</b><i>_</i><b>flow</b><i>_</i><b>delay</b>
|
<b>in</b><i>_</i><b>flow</b><i>_</i><b>delay</b>
|
||||||
Amount of time to pause before accepting a message,
|
Amount of time to pause before accepting a message,
|
||||||
when the message arrival rate exceeds the message
|
when the message arrival rate exceeds the message
|
||||||
delivery rate.
|
delivery rate.
|
||||||
|
|
||||||
<b>extract</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
<b>extract</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
||||||
Limit the amount of recipients extracted from mes-
|
Limit the amount of recipients extracted from mes-
|
||||||
sage headers.
|
sage headers.
|
||||||
|
|
||||||
<b>SEE</b> <b>ALSO</b>
|
<b>SEE</b> <b>ALSO</b>
|
||||||
@@ -159,7 +168,7 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
/etc/postfix/virtual*, virtual mapping table
|
/etc/postfix/virtual*, virtual mapping table
|
||||||
|
|
||||||
<b>LICENSE</b>
|
<b>LICENSE</b>
|
||||||
The Secure Mailer license must be distributed with this
|
The Secure Mailer license must be distributed with this
|
||||||
software.
|
software.
|
||||||
|
|
||||||
<b>AUTHOR(S)</b>
|
<b>AUTHOR(S)</b>
|
||||||
|
@@ -102,6 +102,9 @@ POSTALIAS(1) POSTALIAS(1)
|
|||||||
<i>file_name</i><b>.db</b>. This is available only on
|
<i>file_name</i><b>.db</b>. This is available only on
|
||||||
systems with support for <b>db</b> databases.
|
systems with support for <b>db</b> databases.
|
||||||
|
|
||||||
|
Use the command <b>postconf</b> <b>-m</b> to find out what types
|
||||||
|
of database your Postfix installation can support.
|
||||||
|
|
||||||
When no <i>file_type</i> is specified, the software uses
|
When no <i>file_type</i> is specified, the software uses
|
||||||
the database type specified via the <b>database</b><i>_</i><b>type</b>
|
the database type specified via the <b>database</b><i>_</i><b>type</b>
|
||||||
configuration parameter. The default value for
|
configuration parameter. The default value for
|
||||||
|
@@ -55,17 +55,69 @@ POSTCONF(1) POSTCONF(1)
|
|||||||
|
|
||||||
<b>-m</b> List the names of all supported lookup table types.
|
<b>-m</b> List the names of all supported lookup table types.
|
||||||
|
|
||||||
|
<b>btree</b> A sorted, balanced tree structure. This is
|
||||||
|
available only on systems with support for
|
||||||
|
Berkeley DB databases.
|
||||||
|
|
||||||
|
<b>dbm</b> An indexed file type based on hashing. This
|
||||||
|
is available only on systems with support
|
||||||
|
for DBM databases.
|
||||||
|
|
||||||
|
<b>environ</b>
|
||||||
|
The UNIX process environment array. The
|
||||||
|
lookup key is the variable name. Originally
|
||||||
|
implemented for testing, someone may find
|
||||||
|
this useful someday.
|
||||||
|
|
||||||
|
<b>hash</b> An indexed file type based on hashing. This
|
||||||
|
is available only on systems with support
|
||||||
|
for Berkeley DB databases.
|
||||||
|
|
||||||
|
<b>ldap</b> Perform lookups using the LDAP protocol.
|
||||||
|
This is described in an LDAP_README file.
|
||||||
|
|
||||||
|
<b>pcre</b> A lookup table based on Perl Compatible Reg-
|
||||||
|
ular Expressions. The file format is
|
||||||
|
described in <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
|
||||||
|
|
||||||
|
<b>regexp</b> A lookup table based on regular expressions.
|
||||||
|
The file format is described in <b>reg-</b>
|
||||||
|
<b>exp</b><i>_</i><b>table</b>(5).
|
||||||
|
|
||||||
|
<b>static</b> A table that always returns the same result.
|
||||||
|
For example, <b>static:foobar</b> always returns
|
||||||
|
the string <b>foobar</b>.
|
||||||
|
|
||||||
|
<b>unix</b> A limited way to query the UNIX authentica-
|
||||||
|
tion database. The following tables are
|
||||||
|
implemented:
|
||||||
|
|
||||||
|
<b>unix:passwd.byname</b>
|
||||||
|
The table is the UNIX password
|
||||||
|
database. The key is a login name.
|
||||||
|
The result is a password file entry
|
||||||
|
in passwd(5) format.
|
||||||
|
|
||||||
|
<b>unix:group.byname</b>
|
||||||
|
The table is the UNIX group
|
||||||
|
database. The key is a group name.
|
||||||
|
The result is a group file entry in
|
||||||
|
group(5) format.
|
||||||
|
|
||||||
|
Other table types may exist depending on how Postfix was
|
||||||
|
built.
|
||||||
|
|
||||||
<b>-n</b> Print non-default parameter settings only.
|
<b>-n</b> Print non-default parameter settings only.
|
||||||
|
|
||||||
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
|
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
|
||||||
tiple <b>-v</b> options make the software increasingly
|
tiple <b>-v</b> options make the software increasingly
|
||||||
verbose.
|
verbose.
|
||||||
|
|
||||||
<b>DIAGNOSTICS</b>
|
<b>DIAGNOSTICS</b>
|
||||||
Problems are reported to the standard error stream.
|
Problems are reported to the standard error stream.
|
||||||
|
|
||||||
<b>LICENSE</b>
|
<b>LICENSE</b>
|
||||||
The Secure Mailer license must be distributed with this
|
The Secure Mailer license must be distributed with this
|
||||||
software.
|
software.
|
||||||
|
|
||||||
<b>AUTHOR(S)</b>
|
<b>AUTHOR(S)</b>
|
||||||
|
@@ -123,6 +123,9 @@ POSTMAP(1) POSTMAP(1)
|
|||||||
<i>file_name</i><b>.db</b>. This is available only on
|
<i>file_name</i><b>.db</b>. This is available only on
|
||||||
systems with support for <b>db</b> databases.
|
systems with support for <b>db</b> databases.
|
||||||
|
|
||||||
|
Use the command <b>postconf</b> <b>-m</b> to find out what types
|
||||||
|
of database your Postfix installation can support.
|
||||||
|
|
||||||
When no <i>file_type</i> is specified, the software uses
|
When no <i>file_type</i> is specified, the software uses
|
||||||
the database type specified via the <b>database</b><i>_</i><b>type</b>
|
the database type specified via the <b>database</b><i>_</i><b>type</b>
|
||||||
configuration parameter.
|
configuration parameter.
|
||||||
|
@@ -42,9 +42,12 @@ SMTP(8) SMTP(8)
|
|||||||
|
|
||||||
<b>STANDARDS</b>
|
<b>STANDARDS</b>
|
||||||
<a href="http://www.faqs.org/rfcs/rfc821.html">RFC 821</a> (SMTP protocol)
|
<a href="http://www.faqs.org/rfcs/rfc821.html">RFC 821</a> (SMTP protocol)
|
||||||
|
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1651.html">RFC 1651</a> (SMTP service extensions)
|
<a href="http://www.faqs.org/rfcs/rfc1651.html">RFC 1651</a> (SMTP service extensions)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1652.html">RFC 1652</a> (8bit-MIME transport)
|
<a href="http://www.faqs.org/rfcs/rfc1652.html">RFC 1652</a> (8bit-MIME transport)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1870.html">RFC 1870</a> (Message Size Declaration)
|
<a href="http://www.faqs.org/rfcs/rfc1870.html">RFC 1870</a> (Message Size Declaration)
|
||||||
|
<a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a> (MIME: Format of Internet Message Bodies)
|
||||||
|
<a href="http://www.faqs.org/rfcs/rfc2046.html">RFC 2046</a> (MIME: Media Types)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc2197.html">RFC 2197</a> (Pipelining)
|
<a href="http://www.faqs.org/rfcs/rfc2197.html">RFC 2197</a> (Pipelining)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH command)
|
<a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH command)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> (SMTP protocol)
|
<a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> (SMTP protocol)
|
||||||
|
@@ -92,6 +92,9 @@ This is available only on systems with support for \fBdbm\fR databases.
|
|||||||
The output is a hashed file, named \fIfile_name\fB.db\fR.
|
The output is a hashed file, named \fIfile_name\fB.db\fR.
|
||||||
This is available only on systems with support for \fBdb\fR databases.
|
This is available only on systems with support for \fBdb\fR databases.
|
||||||
.PP
|
.PP
|
||||||
|
Use the command \fBpostconf -m\fR to find out what types of database
|
||||||
|
your Postfix installation can support.
|
||||||
|
|
||||||
When no \fIfile_type\fR is specified, the software uses the database
|
When no \fIfile_type\fR is specified, the software uses the database
|
||||||
type specified via the \fBdatabase_type\fR configuration parameter.
|
type specified via the \fBdatabase_type\fR configuration parameter.
|
||||||
The default value for this parameter depends on the host environment.
|
The default value for this parameter depends on the host environment.
|
||||||
|
@@ -54,6 +54,48 @@ stale lock files that were left behind after abnormal termination.
|
|||||||
.RE
|
.RE
|
||||||
.IP \fB-m\fR
|
.IP \fB-m\fR
|
||||||
List the names of all supported lookup table types.
|
List the names of all supported lookup table types.
|
||||||
|
.RS
|
||||||
|
.IP \fBbtree\fR
|
||||||
|
A sorted, balanced tree structure.
|
||||||
|
This is available only on systems with support for Berkeley DB
|
||||||
|
databases.
|
||||||
|
.IP \fBdbm\fR
|
||||||
|
An indexed file type based on hashing.
|
||||||
|
This is available only on systems with support for DBM databases.
|
||||||
|
.IP \fBenviron\fR
|
||||||
|
The UNIX process environment array. The lookup key is the variable
|
||||||
|
name. Originally implemented for testing, someone may find this
|
||||||
|
useful someday.
|
||||||
|
.IP \fBhash\fR
|
||||||
|
An indexed file type based on hashing.
|
||||||
|
This is available only on systems with support for Berkeley DB
|
||||||
|
databases.
|
||||||
|
.IP \fBldap\fR
|
||||||
|
Perform lookups using the LDAP protocol. This is described
|
||||||
|
in an LDAP_README file.
|
||||||
|
.IP \fBpcre\fR
|
||||||
|
A lookup table based on Perl Compatible Regular Expressions. The
|
||||||
|
file format is described in \fBpcre_table\fR(5).
|
||||||
|
.IP \fBregexp\fR
|
||||||
|
A lookup table based on regular expressions. The file format is
|
||||||
|
described in \fBregexp_table\fR(5).
|
||||||
|
.IP \fBstatic\fR
|
||||||
|
A table that always returns the same result. For example,
|
||||||
|
\fBstatic:foobar\fR always returns the string \fBfoobar\fR.
|
||||||
|
.IP \fBunix\fR
|
||||||
|
A limited way to query the UNIX authentication database. The
|
||||||
|
following tables are implemented:
|
||||||
|
.RS
|
||||||
|
. IP \fBunix:passwd.byname\fR
|
||||||
|
The table is the UNIX password database. The key is a login name.
|
||||||
|
The result is a password file entry in passwd(5) format.
|
||||||
|
.IP \fBunix:group.byname\fR
|
||||||
|
The table is the UNIX group database. The key is a group name.
|
||||||
|
The result is a group file entry in group(5) format.
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.sp
|
||||||
|
Other table types may exist depending on how Postfix was built.
|
||||||
.IP \fB-n\fR
|
.IP \fB-n\fR
|
||||||
Print non-default parameter settings only.
|
Print non-default parameter settings only.
|
||||||
.IP \fB-v\fR
|
.IP \fB-v\fR
|
||||||
|
@@ -113,6 +113,9 @@ This is available only on systems with support for \fBdbm\fR databases.
|
|||||||
The output file is a hashed file, named \fIfile_name\fB.db\fR.
|
The output file is a hashed file, named \fIfile_name\fB.db\fR.
|
||||||
This is available only on systems with support for \fBdb\fR databases.
|
This is available only on systems with support for \fBdb\fR databases.
|
||||||
.PP
|
.PP
|
||||||
|
Use the command \fBpostconf -m\fR to find out what types of database
|
||||||
|
your Postfix installation can support.
|
||||||
|
|
||||||
When no \fIfile_type\fR is specified, the software uses the database
|
When no \fIfile_type\fR is specified, the software uses the database
|
||||||
type specified via the \fBdatabase_type\fR configuration parameter.
|
type specified via the \fBdatabase_type\fR configuration parameter.
|
||||||
.RE
|
.RE
|
||||||
|
@@ -56,6 +56,8 @@ in case of trouble.
|
|||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
RFC 822 (ARPA Internet Text Messages)
|
RFC 822 (ARPA Internet Text Messages)
|
||||||
|
RFC 2045 (MIME: Format of Internet Message Bodies)
|
||||||
|
RFC 2046 (MIME: Media Types)
|
||||||
.SH DIAGNOSTICS
|
.SH DIAGNOSTICS
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
@@ -80,7 +82,12 @@ Lookup tables with content filters for message body lines.
|
|||||||
These filters see physical lines one at a time, in chunks of
|
These filters see physical lines one at a time, in chunks of
|
||||||
at most line_length_limit bytes.
|
at most line_length_limit bytes.
|
||||||
.IP \fBheader_checks\fR
|
.IP \fBheader_checks\fR
|
||||||
Lookup tables with content filters for message header lines.
|
.IP "\fBmime_header_checks\fR (default: \fB$header_checks\fR)"
|
||||||
|
.IP "\fBnested_header_checks\fR (default: \fB$header_checks\fR)"
|
||||||
|
Lookup tables with content filters for message header lines:
|
||||||
|
respectively, these are applied to the primary message headers
|
||||||
|
(not including MIME headers), to the MIME headers anywhere in
|
||||||
|
the message, and to the initial headers of attached messages.
|
||||||
These filters see logical headers one at a time, including headers
|
These filters see logical headers one at a time, including headers
|
||||||
that span multiple lines.
|
that span multiple lines.
|
||||||
.SH Miscellaneous
|
.SH Miscellaneous
|
||||||
|
@@ -47,9 +47,12 @@ run chrooted at fixed low privilege.
|
|||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
RFC 821 (SMTP protocol)
|
RFC 821 (SMTP protocol)
|
||||||
|
RFC 822 (ARPA Internet Text Messages)
|
||||||
RFC 1651 (SMTP service extensions)
|
RFC 1651 (SMTP service extensions)
|
||||||
RFC 1652 (8bit-MIME transport)
|
RFC 1652 (8bit-MIME transport)
|
||||||
RFC 1870 (Message Size Declaration)
|
RFC 1870 (Message Size Declaration)
|
||||||
|
RFC 2045 (MIME: Format of Internet Message Bodies)
|
||||||
|
RFC 2046 (MIME: Media Types)
|
||||||
RFC 2197 (Pipelining)
|
RFC 2197 (Pipelining)
|
||||||
RFC 2554 (AUTH command)
|
RFC 2554 (AUTH command)
|
||||||
RFC 2821 (SMTP protocol)
|
RFC 2821 (SMTP protocol)
|
||||||
|
@@ -86,6 +86,8 @@ cleanup.o: ../../include/tok822.h
|
|||||||
cleanup.o: ../../include/resolve_clnt.h
|
cleanup.o: ../../include/resolve_clnt.h
|
||||||
cleanup.o: ../../include/been_here.h
|
cleanup.o: ../../include/been_here.h
|
||||||
cleanup.o: ../../include/mail_stream.h
|
cleanup.o: ../../include/mail_stream.h
|
||||||
|
cleanup.o: ../../include/mime_state.h
|
||||||
|
cleanup.o: ../../include/header_opts.h
|
||||||
cleanup_api.o: cleanup_api.c
|
cleanup_api.o: cleanup_api.c
|
||||||
cleanup_api.o: ../../include/sys_defs.h
|
cleanup_api.o: ../../include/sys_defs.h
|
||||||
cleanup_api.o: ../../include/msg.h
|
cleanup_api.o: ../../include/msg.h
|
||||||
@@ -111,6 +113,8 @@ cleanup_api.o: ../../include/tok822.h
|
|||||||
cleanup_api.o: ../../include/resolve_clnt.h
|
cleanup_api.o: ../../include/resolve_clnt.h
|
||||||
cleanup_api.o: ../../include/been_here.h
|
cleanup_api.o: ../../include/been_here.h
|
||||||
cleanup_api.o: ../../include/mail_conf.h
|
cleanup_api.o: ../../include/mail_conf.h
|
||||||
|
cleanup_api.o: ../../include/mime_state.h
|
||||||
|
cleanup_api.o: ../../include/header_opts.h
|
||||||
cleanup_envelope.o: cleanup_envelope.c
|
cleanup_envelope.o: cleanup_envelope.c
|
||||||
cleanup_envelope.o: ../../include/sys_defs.h
|
cleanup_envelope.o: ../../include/sys_defs.h
|
||||||
cleanup_envelope.o: ../../include/msg.h
|
cleanup_envelope.o: ../../include/msg.h
|
||||||
@@ -138,6 +142,8 @@ cleanup_envelope.o: ../../include/dict.h
|
|||||||
cleanup_envelope.o: ../../include/been_here.h
|
cleanup_envelope.o: ../../include/been_here.h
|
||||||
cleanup_envelope.o: ../../include/mail_stream.h
|
cleanup_envelope.o: ../../include/mail_stream.h
|
||||||
cleanup_envelope.o: ../../include/mail_conf.h
|
cleanup_envelope.o: ../../include/mail_conf.h
|
||||||
|
cleanup_envelope.o: ../../include/mime_state.h
|
||||||
|
cleanup_envelope.o: ../../include/header_opts.h
|
||||||
cleanup_extracted.o: cleanup_extracted.c
|
cleanup_extracted.o: cleanup_extracted.c
|
||||||
cleanup_extracted.o: ../../include/sys_defs.h
|
cleanup_extracted.o: ../../include/sys_defs.h
|
||||||
cleanup_extracted.o: ../../include/msg.h
|
cleanup_extracted.o: ../../include/msg.h
|
||||||
@@ -164,6 +170,8 @@ cleanup_extracted.o: ../../include/resolve_clnt.h
|
|||||||
cleanup_extracted.o: ../../include/been_here.h
|
cleanup_extracted.o: ../../include/been_here.h
|
||||||
cleanup_extracted.o: ../../include/mail_stream.h
|
cleanup_extracted.o: ../../include/mail_stream.h
|
||||||
cleanup_extracted.o: ../../include/mail_conf.h
|
cleanup_extracted.o: ../../include/mail_conf.h
|
||||||
|
cleanup_extracted.o: ../../include/mime_state.h
|
||||||
|
cleanup_extracted.o: ../../include/header_opts.h
|
||||||
cleanup_init.o: cleanup_init.c
|
cleanup_init.o: cleanup_init.c
|
||||||
cleanup_init.o: ../../include/sys_defs.h
|
cleanup_init.o: ../../include/sys_defs.h
|
||||||
cleanup_init.o: ../../include/msg.h
|
cleanup_init.o: ../../include/msg.h
|
||||||
@@ -187,6 +195,8 @@ cleanup_init.o: ../../include/resolve_clnt.h
|
|||||||
cleanup_init.o: ../../include/been_here.h
|
cleanup_init.o: ../../include/been_here.h
|
||||||
cleanup_init.o: ../../include/mail_stream.h
|
cleanup_init.o: ../../include/mail_stream.h
|
||||||
cleanup_init.o: ../../include/mail_conf.h
|
cleanup_init.o: ../../include/mail_conf.h
|
||||||
|
cleanup_init.o: ../../include/mime_state.h
|
||||||
|
cleanup_init.o: ../../include/header_opts.h
|
||||||
cleanup_map11.o: cleanup_map11.c
|
cleanup_map11.o: cleanup_map11.c
|
||||||
cleanup_map11.o: ../../include/sys_defs.h
|
cleanup_map11.o: ../../include/sys_defs.h
|
||||||
cleanup_map11.o: ../../include/msg.h
|
cleanup_map11.o: ../../include/msg.h
|
||||||
@@ -209,6 +219,8 @@ cleanup_map11.o: ../../include/resolve_clnt.h
|
|||||||
cleanup_map11.o: ../../include/been_here.h
|
cleanup_map11.o: ../../include/been_here.h
|
||||||
cleanup_map11.o: ../../include/mail_stream.h
|
cleanup_map11.o: ../../include/mail_stream.h
|
||||||
cleanup_map11.o: ../../include/mail_conf.h
|
cleanup_map11.o: ../../include/mail_conf.h
|
||||||
|
cleanup_map11.o: ../../include/mime_state.h
|
||||||
|
cleanup_map11.o: ../../include/header_opts.h
|
||||||
cleanup_map1n.o: cleanup_map1n.c
|
cleanup_map1n.o: cleanup_map1n.c
|
||||||
cleanup_map1n.o: ../../include/sys_defs.h
|
cleanup_map1n.o: ../../include/sys_defs.h
|
||||||
cleanup_map1n.o: ../../include/mymalloc.h
|
cleanup_map1n.o: ../../include/mymalloc.h
|
||||||
@@ -231,6 +243,8 @@ cleanup_map1n.o: ../../include/tok822.h
|
|||||||
cleanup_map1n.o: ../../include/resolve_clnt.h
|
cleanup_map1n.o: ../../include/resolve_clnt.h
|
||||||
cleanup_map1n.o: ../../include/mail_stream.h
|
cleanup_map1n.o: ../../include/mail_stream.h
|
||||||
cleanup_map1n.o: ../../include/mail_conf.h
|
cleanup_map1n.o: ../../include/mail_conf.h
|
||||||
|
cleanup_map1n.o: ../../include/mime_state.h
|
||||||
|
cleanup_map1n.o: ../../include/header_opts.h
|
||||||
cleanup_masquerade.o: cleanup_masquerade.c
|
cleanup_masquerade.o: cleanup_masquerade.c
|
||||||
cleanup_masquerade.o: ../../include/sys_defs.h
|
cleanup_masquerade.o: ../../include/sys_defs.h
|
||||||
cleanup_masquerade.o: ../../include/msg.h
|
cleanup_masquerade.o: ../../include/msg.h
|
||||||
@@ -253,6 +267,8 @@ cleanup_masquerade.o: ../../include/dict.h
|
|||||||
cleanup_masquerade.o: ../../include/been_here.h
|
cleanup_masquerade.o: ../../include/been_here.h
|
||||||
cleanup_masquerade.o: ../../include/mail_stream.h
|
cleanup_masquerade.o: ../../include/mail_stream.h
|
||||||
cleanup_masquerade.o: ../../include/mail_conf.h
|
cleanup_masquerade.o: ../../include/mail_conf.h
|
||||||
|
cleanup_masquerade.o: ../../include/mime_state.h
|
||||||
|
cleanup_masquerade.o: ../../include/header_opts.h
|
||||||
cleanup_message.o: cleanup_message.c
|
cleanup_message.o: cleanup_message.c
|
||||||
cleanup_message.o: ../../include/sys_defs.h
|
cleanup_message.o: ../../include/sys_defs.h
|
||||||
cleanup_message.o: ../../include/msg.h
|
cleanup_message.o: ../../include/msg.h
|
||||||
@@ -281,6 +297,7 @@ cleanup_message.o: ../../include/ext_prop.h
|
|||||||
cleanup_message.o: ../../include/mail_proto.h
|
cleanup_message.o: ../../include/mail_proto.h
|
||||||
cleanup_message.o: ../../include/iostuff.h
|
cleanup_message.o: ../../include/iostuff.h
|
||||||
cleanup_message.o: ../../include/attr.h
|
cleanup_message.o: ../../include/attr.h
|
||||||
|
cleanup_message.o: ../../include/mime_state.h
|
||||||
cleanup_message.o: cleanup.h
|
cleanup_message.o: cleanup.h
|
||||||
cleanup_message.o: ../../include/maps.h
|
cleanup_message.o: ../../include/maps.h
|
||||||
cleanup_message.o: ../../include/dict.h
|
cleanup_message.o: ../../include/dict.h
|
||||||
@@ -309,6 +326,8 @@ cleanup_out.o: ../../include/resolve_clnt.h
|
|||||||
cleanup_out.o: ../../include/been_here.h
|
cleanup_out.o: ../../include/been_here.h
|
||||||
cleanup_out.o: ../../include/mail_stream.h
|
cleanup_out.o: ../../include/mail_stream.h
|
||||||
cleanup_out.o: ../../include/mail_conf.h
|
cleanup_out.o: ../../include/mail_conf.h
|
||||||
|
cleanup_out.o: ../../include/mime_state.h
|
||||||
|
cleanup_out.o: ../../include/header_opts.h
|
||||||
cleanup_out_recipient.o: cleanup_out_recipient.c
|
cleanup_out_recipient.o: cleanup_out_recipient.c
|
||||||
cleanup_out_recipient.o: ../../include/sys_defs.h
|
cleanup_out_recipient.o: ../../include/sys_defs.h
|
||||||
cleanup_out_recipient.o: ../../include/argv.h
|
cleanup_out_recipient.o: ../../include/argv.h
|
||||||
@@ -329,6 +348,8 @@ cleanup_out_recipient.o: ../../include/tok822.h
|
|||||||
cleanup_out_recipient.o: ../../include/resolve_clnt.h
|
cleanup_out_recipient.o: ../../include/resolve_clnt.h
|
||||||
cleanup_out_recipient.o: ../../include/mail_stream.h
|
cleanup_out_recipient.o: ../../include/mail_stream.h
|
||||||
cleanup_out_recipient.o: ../../include/mail_conf.h
|
cleanup_out_recipient.o: ../../include/mail_conf.h
|
||||||
|
cleanup_out_recipient.o: ../../include/mime_state.h
|
||||||
|
cleanup_out_recipient.o: ../../include/header_opts.h
|
||||||
cleanup_rewrite.o: cleanup_rewrite.c
|
cleanup_rewrite.o: cleanup_rewrite.c
|
||||||
cleanup_rewrite.o: ../../include/sys_defs.h
|
cleanup_rewrite.o: ../../include/sys_defs.h
|
||||||
cleanup_rewrite.o: ../../include/msg.h
|
cleanup_rewrite.o: ../../include/msg.h
|
||||||
@@ -350,6 +371,8 @@ cleanup_rewrite.o: ../../include/dict.h
|
|||||||
cleanup_rewrite.o: ../../include/been_here.h
|
cleanup_rewrite.o: ../../include/been_here.h
|
||||||
cleanup_rewrite.o: ../../include/mail_stream.h
|
cleanup_rewrite.o: ../../include/mail_stream.h
|
||||||
cleanup_rewrite.o: ../../include/mail_conf.h
|
cleanup_rewrite.o: ../../include/mail_conf.h
|
||||||
|
cleanup_rewrite.o: ../../include/mime_state.h
|
||||||
|
cleanup_rewrite.o: ../../include/header_opts.h
|
||||||
cleanup_state.o: cleanup_state.c
|
cleanup_state.o: cleanup_state.c
|
||||||
cleanup_state.o: ../../include/sys_defs.h
|
cleanup_state.o: ../../include/sys_defs.h
|
||||||
cleanup_state.o: ../../include/mymalloc.h
|
cleanup_state.o: ../../include/mymalloc.h
|
||||||
@@ -359,6 +382,8 @@ cleanup_state.o: ../../include/argv.h
|
|||||||
cleanup_state.o: ../../include/htable.h
|
cleanup_state.o: ../../include/htable.h
|
||||||
cleanup_state.o: ../../include/been_here.h
|
cleanup_state.o: ../../include/been_here.h
|
||||||
cleanup_state.o: ../../include/mail_params.h
|
cleanup_state.o: ../../include/mail_params.h
|
||||||
|
cleanup_state.o: ../../include/mime_state.h
|
||||||
|
cleanup_state.o: ../../include/header_opts.h
|
||||||
cleanup_state.o: cleanup.h
|
cleanup_state.o: cleanup.h
|
||||||
cleanup_state.o: ../../include/vstream.h
|
cleanup_state.o: ../../include/vstream.h
|
||||||
cleanup_state.o: ../../include/nvtable.h
|
cleanup_state.o: ../../include/nvtable.h
|
||||||
|
@@ -48,6 +48,8 @@
|
|||||||
/* in case of trouble.
|
/* in case of trouble.
|
||||||
/* STANDARDS
|
/* STANDARDS
|
||||||
/* RFC 822 (ARPA Internet Text Messages)
|
/* RFC 822 (ARPA Internet Text Messages)
|
||||||
|
/* RFC 2045 (MIME: Format of Internet Message Bodies)
|
||||||
|
/* RFC 2046 (MIME: Media Types)
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||||
/* BUGS
|
/* BUGS
|
||||||
@@ -66,7 +68,12 @@
|
|||||||
/* These filters see physical lines one at a time, in chunks of
|
/* These filters see physical lines one at a time, in chunks of
|
||||||
/* at most line_length_limit bytes.
|
/* at most line_length_limit bytes.
|
||||||
/* .IP \fBheader_checks\fR
|
/* .IP \fBheader_checks\fR
|
||||||
/* Lookup tables with content filters for message header lines.
|
/* .IP "\fBmime_header_checks\fR (default: \fB$header_checks\fR)"
|
||||||
|
/* .IP "\fBnested_header_checks\fR (default: \fB$header_checks\fR)"
|
||||||
|
/* Lookup tables with content filters for message header lines:
|
||||||
|
/* respectively, these are applied to the primary message headers
|
||||||
|
/* (not including MIME headers), to the MIME headers anywhere in
|
||||||
|
/* the message, and to the initial headers of attached messages.
|
||||||
/* These filters see logical headers one at a time, including headers
|
/* These filters see logical headers one at a time, including headers
|
||||||
/* that span multiple lines.
|
/* that span multiple lines.
|
||||||
/* .SH Miscellaneous
|
/* .SH Miscellaneous
|
||||||
@@ -219,6 +226,16 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Can't do header checks if the MIME structure is nested too deeply.
|
||||||
|
*/
|
||||||
|
if ((state->mime_errs & MIME_ERR_NESTING)
|
||||||
|
&& (*var_header_checks || *var_mimehdr_checks || *var_nesthdr_checks)
|
||||||
|
&& state->reason == 0) {
|
||||||
|
state->errs |= CLEANUP_STAT_CONT;
|
||||||
|
state->reason = mystrdup("too much MIME nesting");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep reading in case of problems, until the sender is ready to receive
|
* Keep reading in case of problems, until the sender is ready to receive
|
||||||
* our status report.
|
* our status report.
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include <been_here.h>
|
#include <been_here.h>
|
||||||
#include <mail_stream.h>
|
#include <mail_stream.h>
|
||||||
#include <mail_conf.h>
|
#include <mail_conf.h>
|
||||||
|
#include <mime_state.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These state variables are accessed by many functions, and there is only
|
* These state variables are accessed by many functions, and there is only
|
||||||
@@ -46,9 +47,7 @@ typedef struct CLEANUP_STATE {
|
|||||||
int flags; /* processing options */
|
int flags; /* processing options */
|
||||||
int errs; /* any badness experienced */
|
int errs; /* any badness experienced */
|
||||||
int err_mask; /* allowed badness */
|
int err_mask; /* allowed badness */
|
||||||
VSTRING *header_buf; /* multi-record header */
|
|
||||||
int headers_seen; /* which headers were seen */
|
int headers_seen; /* which headers were seen */
|
||||||
int prev_header_type; /* multi-record physical header line */
|
|
||||||
int hop_count; /* count of received: headers */
|
int hop_count; /* count of received: headers */
|
||||||
ARGV *recipients; /* recipients from regular headers */
|
ARGV *recipients; /* recipients from regular headers */
|
||||||
ARGV *resent_recip; /* recipients from resent headers */
|
ARGV *resent_recip; /* recipients from resent headers */
|
||||||
@@ -63,8 +62,12 @@ typedef struct CLEANUP_STATE {
|
|||||||
int rcpt_count; /* recipient count */
|
int rcpt_count; /* recipient count */
|
||||||
char *reason; /* failure reason */
|
char *reason; /* failure reason */
|
||||||
NVTABLE *attr; /* queue file attribute list */
|
NVTABLE *attr; /* queue file attribute list */
|
||||||
|
MIME_STATE *mime_state; /* MIME state engine */
|
||||||
|
int mime_errs; /* MIME error flags */
|
||||||
} CLEANUP_STATE;
|
} CLEANUP_STATE;
|
||||||
|
|
||||||
|
#define CLEANUP_CURR_HEADERS (1<<0) /* in main headers section */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mappings.
|
* Mappings.
|
||||||
*/
|
*/
|
||||||
@@ -72,6 +75,8 @@ extern MAPS *cleanup_comm_canon_maps;
|
|||||||
extern MAPS *cleanup_send_canon_maps;
|
extern MAPS *cleanup_send_canon_maps;
|
||||||
extern MAPS *cleanup_rcpt_canon_maps;
|
extern MAPS *cleanup_rcpt_canon_maps;
|
||||||
extern MAPS *cleanup_header_checks;
|
extern MAPS *cleanup_header_checks;
|
||||||
|
extern MAPS *cleanup_mimehdr_checks;
|
||||||
|
extern MAPS *cleanup_nesthdr_checks;
|
||||||
extern MAPS *cleanup_body_checks;
|
extern MAPS *cleanup_body_checks;
|
||||||
extern MAPS *cleanup_virtual_maps;
|
extern MAPS *cleanup_virtual_maps;
|
||||||
extern ARGV *cleanup_masq_domains;
|
extern ARGV *cleanup_masq_domains;
|
||||||
@@ -121,9 +126,9 @@ extern CONFIG_TIME_TABLE cleanup_time_table[];
|
|||||||
/*
|
/*
|
||||||
* cleanup_out.c
|
* cleanup_out.c
|
||||||
*/
|
*/
|
||||||
extern void cleanup_out(CLEANUP_STATE *, int, char *, int);
|
extern void cleanup_out(CLEANUP_STATE *, int, const char *, int);
|
||||||
extern void cleanup_out_string(CLEANUP_STATE *, int, char *);
|
extern void cleanup_out_string(CLEANUP_STATE *, int, const char *);
|
||||||
extern void PRINTFLIKE(3, 4) cleanup_out_format(CLEANUP_STATE *, int, char *,...);
|
extern void PRINTFLIKE(3, 4) cleanup_out_format(CLEANUP_STATE *, int, const char *,...);
|
||||||
|
|
||||||
#define CLEANUP_OUT_BUF(s, t, b) \
|
#define CLEANUP_OUT_BUF(s, t, b) \
|
||||||
cleanup_out((s), (t), vstring_str((b)), VSTRING_LEN((b)))
|
cleanup_out((s), (t), vstring_str((b)), VSTRING_LEN((b)))
|
||||||
|
@@ -91,14 +91,15 @@ char *cleanup_path; /* queue file name */
|
|||||||
* Tunable parameters.
|
* Tunable parameters.
|
||||||
*/
|
*/
|
||||||
int var_hopcount_limit; /* max mailer hop count */
|
int var_hopcount_limit; /* max mailer hop count */
|
||||||
int var_header_limit; /* max header length */
|
|
||||||
char *var_canonical_maps; /* common canonical maps */
|
char *var_canonical_maps; /* common canonical maps */
|
||||||
char *var_send_canon_maps; /* sender canonical maps */
|
char *var_send_canon_maps; /* sender canonical maps */
|
||||||
char *var_rcpt_canon_maps; /* recipient canonical maps */
|
char *var_rcpt_canon_maps; /* recipient canonical maps */
|
||||||
char *var_virtual_maps; /* virtual maps */
|
char *var_virtual_maps; /* virtual maps */
|
||||||
char *var_masq_domains; /* masquerade domains */
|
char *var_masq_domains; /* masquerade domains */
|
||||||
char *var_masq_exceptions; /* users not masqueraded */
|
char *var_masq_exceptions; /* users not masqueraded */
|
||||||
char *var_header_checks; /* any header checks */
|
char *var_header_checks; /* primary header checks */
|
||||||
|
char *var_mimehdr_checks; /* mime header checks */
|
||||||
|
char *var_nesthdr_checks; /* nested header checks */
|
||||||
char *var_body_checks; /* any body checks */
|
char *var_body_checks; /* any body checks */
|
||||||
int var_dup_filter_limit; /* recipient dup filter */
|
int var_dup_filter_limit; /* recipient dup filter */
|
||||||
char *var_empty_addr; /* destination of bounced bounces */
|
char *var_empty_addr; /* destination of bounced bounces */
|
||||||
@@ -112,7 +113,6 @@ int var_qattr_count_limit; /* named attribute limit */
|
|||||||
|
|
||||||
CONFIG_INT_TABLE cleanup_int_table[] = {
|
CONFIG_INT_TABLE cleanup_int_table[] = {
|
||||||
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
|
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
|
||||||
VAR_HEADER_LIMIT, DEF_HEADER_LIMIT, &var_header_limit, 1, 0,
|
|
||||||
VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0,
|
VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0,
|
||||||
VAR_EXTRA_RCPT_LIMIT, DEF_EXTRA_RCPT_LIMIT, &var_extra_rcpt_limit, 0, 0,
|
VAR_EXTRA_RCPT_LIMIT, DEF_EXTRA_RCPT_LIMIT, &var_extra_rcpt_limit, 0, 0,
|
||||||
VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0,
|
VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0,
|
||||||
@@ -133,6 +133,8 @@ CONFIG_STR_TABLE cleanup_str_table[] = {
|
|||||||
VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
|
VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
|
||||||
VAR_MASQ_EXCEPTIONS, DEF_MASQ_EXCEPTIONS, &var_masq_exceptions, 0, 0,
|
VAR_MASQ_EXCEPTIONS, DEF_MASQ_EXCEPTIONS, &var_masq_exceptions, 0, 0,
|
||||||
VAR_HEADER_CHECKS, DEF_HEADER_CHECKS, &var_header_checks, 0, 0,
|
VAR_HEADER_CHECKS, DEF_HEADER_CHECKS, &var_header_checks, 0, 0,
|
||||||
|
VAR_MIMEHDR_CHECKS, DEF_MIMEHDR_CHECKS, &var_mimehdr_checks, 0, 0,
|
||||||
|
VAR_NESTHDR_CHECKS, DEF_NESTHDR_CHECKS, &var_nesthdr_checks, 0, 0,
|
||||||
VAR_BODY_CHECKS, DEF_BODY_CHECKS, &var_body_checks, 0, 0,
|
VAR_BODY_CHECKS, DEF_BODY_CHECKS, &var_body_checks, 0, 0,
|
||||||
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
|
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
|
||||||
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
|
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
|
||||||
@@ -148,6 +150,8 @@ MAPS *cleanup_comm_canon_maps;
|
|||||||
MAPS *cleanup_send_canon_maps;
|
MAPS *cleanup_send_canon_maps;
|
||||||
MAPS *cleanup_rcpt_canon_maps;
|
MAPS *cleanup_rcpt_canon_maps;
|
||||||
MAPS *cleanup_header_checks;
|
MAPS *cleanup_header_checks;
|
||||||
|
MAPS *cleanup_mimehdr_checks;
|
||||||
|
MAPS *cleanup_nesthdr_checks;
|
||||||
MAPS *cleanup_body_checks;
|
MAPS *cleanup_body_checks;
|
||||||
MAPS *cleanup_virtual_maps;
|
MAPS *cleanup_virtual_maps;
|
||||||
ARGV *cleanup_masq_domains;
|
ARGV *cleanup_masq_domains;
|
||||||
@@ -197,6 +201,12 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv)
|
|||||||
if (*var_header_checks)
|
if (*var_header_checks)
|
||||||
cleanup_header_checks =
|
cleanup_header_checks =
|
||||||
maps_create(VAR_HEADER_CHECKS, var_header_checks, DICT_FLAG_LOCK);
|
maps_create(VAR_HEADER_CHECKS, var_header_checks, DICT_FLAG_LOCK);
|
||||||
|
if (*var_mimehdr_checks)
|
||||||
|
cleanup_mimehdr_checks =
|
||||||
|
maps_create(VAR_MIMEHDR_CHECKS, var_mimehdr_checks, DICT_FLAG_LOCK);
|
||||||
|
if (*var_nesthdr_checks)
|
||||||
|
cleanup_nesthdr_checks =
|
||||||
|
maps_create(VAR_NESTHDR_CHECKS, var_nesthdr_checks, DICT_FLAG_LOCK);
|
||||||
if (*var_body_checks)
|
if (*var_body_checks)
|
||||||
cleanup_body_checks =
|
cleanup_body_checks =
|
||||||
maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
|
maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
|
||||||
|
@@ -78,19 +78,17 @@
|
|||||||
#include <is_header.h>
|
#include <is_header.h>
|
||||||
#include <ext_prop.h>
|
#include <ext_prop.h>
|
||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
|
#include <mime_state.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
#include "cleanup.h"
|
#include "cleanup.h"
|
||||||
|
|
||||||
static void cleanup_message_header(CLEANUP_STATE *, int, char *, int);
|
|
||||||
static void cleanup_message_body(CLEANUP_STATE *, int, char *, int);
|
|
||||||
|
|
||||||
/* cleanup_out_header - output one header as a bunch of records */
|
/* cleanup_out_header - output one header as a bunch of records */
|
||||||
|
|
||||||
static void cleanup_out_header(CLEANUP_STATE *state)
|
static void cleanup_out_header(CLEANUP_STATE *state, VSTRING *header_buf)
|
||||||
{
|
{
|
||||||
char *start = vstring_str(state->header_buf);
|
char *start = vstring_str(header_buf);
|
||||||
char *line;
|
char *line;
|
||||||
char *next_line;
|
char *next_line;
|
||||||
|
|
||||||
@@ -113,9 +111,9 @@ static void cleanup_out_header(CLEANUP_STATE *state)
|
|||||||
|
|
||||||
/* cleanup_fold_header - wrap address list header */
|
/* cleanup_fold_header - wrap address list header */
|
||||||
|
|
||||||
static void cleanup_fold_header(CLEANUP_STATE *state)
|
static void cleanup_fold_header(CLEANUP_STATE *state, VSTRING *header_buf)
|
||||||
{
|
{
|
||||||
char *start_line = vstring_str(state->header_buf);
|
char *start_line = vstring_str(header_buf);
|
||||||
char *end_line;
|
char *end_line;
|
||||||
char *next_line;
|
char *next_line;
|
||||||
char *line;
|
char *line;
|
||||||
@@ -138,7 +136,7 @@ static void cleanup_fold_header(CLEANUP_STATE *state)
|
|||||||
}
|
}
|
||||||
next_line = *end_line ? end_line + 1 : 0;
|
next_line = *end_line ? end_line + 1 : 0;
|
||||||
}
|
}
|
||||||
cleanup_out_header(state);
|
cleanup_out_header(state, header_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_extract_internal - save unquoted copy of extracted address */
|
/* cleanup_extract_internal - save unquoted copy of extracted address */
|
||||||
@@ -156,11 +154,13 @@ static char *cleanup_extract_internal(VSTRING *buffer, TOK822 *addr)
|
|||||||
|
|
||||||
/* cleanup_rewrite_sender - sender address rewriting */
|
/* cleanup_rewrite_sender - sender address rewriting */
|
||||||
|
|
||||||
static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
|
static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
|
||||||
|
VSTRING *header_buf)
|
||||||
{
|
{
|
||||||
TOK822 *tree;
|
TOK822 *tree;
|
||||||
TOK822 **addr_list;
|
TOK822 **addr_list;
|
||||||
TOK822 **tpp;
|
TOK822 **tpp;
|
||||||
|
char *addr;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("rewrite_sender: %s", hdr_opts->name);
|
msg_info("rewrite_sender: %s", hdr_opts->name);
|
||||||
@@ -170,8 +170,11 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
|
|||||||
* sender addresses, and regenerate the header line. Finally, pipe the
|
* sender addresses, and regenerate the header line. Finally, pipe the
|
||||||
* result through the header line folding routine.
|
* result through the header line folding routine.
|
||||||
*/
|
*/
|
||||||
tree = tok822_parse(vstring_str(state->header_buf)
|
#define SKIP_HEADER_THRASH(cp) { while (ISSPACE(*cp)) cp++; cp++; }
|
||||||
+ strlen(hdr_opts->name) + 1);
|
|
||||||
|
addr = vstring_str(header_buf) + strlen(hdr_opts->name);
|
||||||
|
SKIP_HEADER_THRASH(addr);
|
||||||
|
tree = tok822_parse(addr);
|
||||||
addr_list = tok822_grep(tree, TOK822_ADDR);
|
addr_list = tok822_grep(tree, TOK822_ADDR);
|
||||||
for (tpp = addr_list; *tpp; tpp++) {
|
for (tpp = addr_list; *tpp; tpp++) {
|
||||||
cleanup_rewrite_tree(*tpp);
|
cleanup_rewrite_tree(*tpp);
|
||||||
@@ -185,33 +188,35 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
|
|||||||
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
|
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
|
||||||
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
|
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
|
||||||
if (hdr_opts->type == HDR_FROM && state->from == 0)
|
if (hdr_opts->type == HDR_FROM && state->from == 0)
|
||||||
state->from = cleanup_extract_internal(state->header_buf, *tpp);
|
state->from = cleanup_extract_internal(header_buf, *tpp);
|
||||||
if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0)
|
if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0)
|
||||||
state->resent_from =
|
state->resent_from =
|
||||||
cleanup_extract_internal(state->header_buf, *tpp);
|
cleanup_extract_internal(header_buf, *tpp);
|
||||||
if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
|
if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
|
||||||
state->return_receipt =
|
state->return_receipt =
|
||||||
cleanup_extract_internal(state->header_buf, *tpp);
|
cleanup_extract_internal(header_buf, *tpp);
|
||||||
if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
|
if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
|
||||||
state->errors_to =
|
state->errors_to =
|
||||||
cleanup_extract_internal(state->header_buf, *tpp);
|
cleanup_extract_internal(header_buf, *tpp);
|
||||||
}
|
}
|
||||||
vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name);
|
vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
|
||||||
tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD);
|
tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
|
||||||
myfree((char *) addr_list);
|
myfree((char *) addr_list);
|
||||||
tok822_free_tree(tree);
|
tok822_free_tree(tree);
|
||||||
if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
|
if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
|
||||||
cleanup_fold_header(state);
|
cleanup_fold_header(state, header_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_rewrite_recip - recipient address rewriting */
|
/* cleanup_rewrite_recip - recipient address rewriting */
|
||||||
|
|
||||||
static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
|
static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
|
||||||
|
VSTRING *header_buf)
|
||||||
{
|
{
|
||||||
TOK822 *tree;
|
TOK822 *tree;
|
||||||
TOK822 **addr_list;
|
TOK822 **addr_list;
|
||||||
TOK822 **tpp;
|
TOK822 **tpp;
|
||||||
ARGV *rcpt;
|
ARGV *rcpt;
|
||||||
|
char *addr;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("rewrite_recip: %s", hdr_opts->name);
|
msg_info("rewrite_recip: %s", hdr_opts->name);
|
||||||
@@ -221,8 +226,9 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
|
|||||||
* recipient addresses, and regenerate the header line. Finally, pipe the
|
* recipient addresses, and regenerate the header line. Finally, pipe the
|
||||||
* result through the header line folding routine.
|
* result through the header line folding routine.
|
||||||
*/
|
*/
|
||||||
tree = tok822_parse(vstring_str(state->header_buf)
|
addr = vstring_str(header_buf) + strlen(hdr_opts->name);
|
||||||
+ strlen(hdr_opts->name) + 1);
|
SKIP_HEADER_THRASH(addr);
|
||||||
|
tree = tok822_parse(addr);
|
||||||
addr_list = tok822_grep(tree, TOK822_ADDR);
|
addr_list = tok822_grep(tree, TOK822_ADDR);
|
||||||
for (tpp = addr_list; *tpp; tpp++) {
|
for (tpp = addr_list; *tpp; tpp++) {
|
||||||
cleanup_rewrite_tree(*tpp);
|
cleanup_rewrite_tree(*tpp);
|
||||||
@@ -249,17 +255,17 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
|
|||||||
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
|
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
|
||||||
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
|
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
|
||||||
}
|
}
|
||||||
vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name);
|
vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
|
||||||
tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD);
|
tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
|
||||||
myfree((char *) addr_list);
|
myfree((char *) addr_list);
|
||||||
tok822_free_tree(tree);
|
tok822_free_tree(tree);
|
||||||
if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
|
if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
|
||||||
cleanup_fold_header(state);
|
cleanup_fold_header(state, header_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_act - act upon a header/body match */
|
/* cleanup_act - act upon a header/body match */
|
||||||
|
|
||||||
static int cleanup_act(CLEANUP_STATE *state, char *context, char *buf,
|
static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf,
|
||||||
const char *value, const char *map_class)
|
const char *value, const char *map_class)
|
||||||
{
|
{
|
||||||
const char *optional_text = value + strcspn(value, " \t");
|
const char *optional_text = value + strcspn(value, " \t");
|
||||||
@@ -308,12 +314,13 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, char *buf,
|
|||||||
return (CLEANUP_ACT_KEEP);
|
return (CLEANUP_ACT_KEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_header - process one complete header line */
|
/* cleanup_header_callback - process one complete header line */
|
||||||
|
|
||||||
static void cleanup_header(CLEANUP_STATE *state)
|
static void cleanup_header_callback(void *context, int header_class,
|
||||||
|
HEADER_OPTS *hdr_opts, VSTRING *header_buf)
|
||||||
{
|
{
|
||||||
char *myname = "cleanup_header";
|
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
|
||||||
HEADER_OPTS *hdr_opts;
|
const char *myname = "cleanup_header_callback";
|
||||||
char *hdrval;
|
char *hdrval;
|
||||||
struct code_map {
|
struct code_map {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -328,16 +335,31 @@ static void cleanup_header(CLEANUP_STATE *state)
|
|||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
struct code_map *cmp;
|
struct code_map *cmp;
|
||||||
|
MAPS *checks;
|
||||||
|
const char *map_class;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: '%s'", myname, vstring_str(state->header_buf));
|
msg_info("%s: '%s'", myname, vstring_str(header_buf));
|
||||||
|
|
||||||
if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_header_checks) {
|
/*
|
||||||
char *header = vstring_str(state->header_buf);
|
* Crude header filtering. This stops malware that isn't sophisticated
|
||||||
|
* enough to use fancy header encodings.
|
||||||
|
*/
|
||||||
|
#define CHECK(class, maps, var_name) \
|
||||||
|
(header_class == class && (map_class = var_name, checks = maps) != 0)
|
||||||
|
|
||||||
|
if (hdr_opts && (hdr_opts->flags & HDR_OPT_MIME))
|
||||||
|
header_class = MIME_HDR_MULTIPART;
|
||||||
|
|
||||||
|
if ((state->flags & CLEANUP_FLAG_FILTER)
|
||||||
|
&& (CHECK(MIME_HDR_PRIMARY, cleanup_header_checks, VAR_HEADER_CHECKS)
|
||||||
|
|| CHECK(MIME_HDR_MULTIPART, cleanup_mimehdr_checks, VAR_MIMEHDR_CHECKS)
|
||||||
|
|| CHECK(MIME_HDR_NESTED, cleanup_nesthdr_checks, VAR_NESTHDR_CHECKS))) {
|
||||||
|
char *header = vstring_str(header_buf);
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) {
|
if ((value = maps_find(checks, header, 0)) != 0) {
|
||||||
if (cleanup_act(state, "header", header, value, VAR_HEADER_CHECKS)
|
if (cleanup_act(state, "header", header, value, map_class)
|
||||||
== CLEANUP_ACT_DROP)
|
== CLEANUP_ACT_DROP)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -346,10 +368,38 @@ static void cleanup_header(CLEANUP_STATE *state)
|
|||||||
/*
|
/*
|
||||||
* If this is an "unknown" header, just copy it to the output without
|
* If this is an "unknown" header, just copy it to the output without
|
||||||
* even bothering to fold long lines. cleanup_out() will split long
|
* even bothering to fold long lines. cleanup_out() will split long
|
||||||
* headers that do not fit in a REC_TYPE_NORM record.
|
* headers that do not fit a REC_TYPE_NORM record.
|
||||||
*/
|
*/
|
||||||
if ((hdr_opts = header_opts_find(vstring_str(state->header_buf))) == 0) {
|
if (hdr_opts == 0) {
|
||||||
cleanup_out_header(state);
|
cleanup_out_header(state, header_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow 8-bit type info to override 7-bit type info. XXX Should reuse
|
||||||
|
* the effort that went into MIME header parsing.
|
||||||
|
*/
|
||||||
|
hdrval = vstring_str(header_buf) + strlen(hdr_opts->name);
|
||||||
|
SKIP_HEADER_THRASH(hdrval);
|
||||||
|
/* trimblanks(hdrval, 0)[0] = 0; */
|
||||||
|
if (hdr_opts->type == HDR_CONTENT_TRANSFER_ENCODING) {
|
||||||
|
for (cmp = code_map; cmp->name != 0; cmp++) {
|
||||||
|
if (strcasecmp(hdrval, cmp->name) == 0) {
|
||||||
|
if (nvtable_find(state->attr, MAIL_ATTR_ENCODING) == 0
|
||||||
|
|| strcmp(cmp->encoding, MAIL_ATTR_ENC_8BIT) == 0)
|
||||||
|
nvtable_update(state->attr, MAIL_ATTR_ENCODING,
|
||||||
|
cmp->encoding);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy attachment etc. header blocks without further inspection.
|
||||||
|
*/
|
||||||
|
if (header_class != MIME_HDR_PRIMARY) {
|
||||||
|
cleanup_out_header(state, header_buf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -383,10 +433,6 @@ static void cleanup_header(CLEANUP_STATE *state)
|
|||||||
*/
|
*/
|
||||||
else {
|
else {
|
||||||
state->headers_seen |= (1 << hdr_opts->type);
|
state->headers_seen |= (1 << hdr_opts->type);
|
||||||
hdrval = vstring_str(state->header_buf) + strlen(hdr_opts->name) + 2;
|
|
||||||
while (ISSPACE(*hdrval))
|
|
||||||
hdrval++;
|
|
||||||
trimblanks(hdrval, 0);
|
|
||||||
if (hdr_opts->type == HDR_MESSAGE_ID)
|
if (hdr_opts->type == HDR_MESSAGE_ID)
|
||||||
msg_info("%s: message-id=%s", state->queue_id, hdrval);
|
msg_info("%s: message-id=%s", state->queue_id, hdrval);
|
||||||
if (hdr_opts->type == HDR_RESENT_MESSAGE_ID)
|
if (hdr_opts->type == HDR_RESENT_MESSAGE_ID)
|
||||||
@@ -394,35 +440,25 @@ static void cleanup_header(CLEANUP_STATE *state)
|
|||||||
if (hdr_opts->type == HDR_RECEIVED)
|
if (hdr_opts->type == HDR_RECEIVED)
|
||||||
if (++state->hop_count >= var_hopcount_limit)
|
if (++state->hop_count >= var_hopcount_limit)
|
||||||
state->errs |= CLEANUP_STAT_HOPS;
|
state->errs |= CLEANUP_STAT_HOPS;
|
||||||
if (hdr_opts->type == HDR_CONTENT_TRANSFER_ENCODING) {
|
|
||||||
if (nvtable_find(state->attr, MAIL_ATTR_ENCODING) == 0) {
|
|
||||||
for (cmp = code_map; cmp->name != 0; cmp++) {
|
|
||||||
if (strcasecmp(hdrval, cmp->name) == 0) {
|
|
||||||
nvtable_update(state->attr, MAIL_ATTR_ENCODING,
|
|
||||||
cmp->encoding);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CLEANUP_OUT_OK(state)) {
|
if (CLEANUP_OUT_OK(state)) {
|
||||||
if (hdr_opts->flags & HDR_OPT_RR)
|
if (hdr_opts->flags & HDR_OPT_RR)
|
||||||
state->resent = "Resent-";
|
state->resent = "Resent-";
|
||||||
if (hdr_opts->flags & HDR_OPT_SENDER) {
|
if (hdr_opts->flags & HDR_OPT_SENDER) {
|
||||||
cleanup_rewrite_sender(state, hdr_opts);
|
cleanup_rewrite_sender(state, hdr_opts, header_buf);
|
||||||
} else if (hdr_opts->flags & HDR_OPT_RECIP) {
|
} else if (hdr_opts->flags & HDR_OPT_RECIP) {
|
||||||
cleanup_rewrite_recip(state, hdr_opts);
|
cleanup_rewrite_recip(state, hdr_opts, header_buf);
|
||||||
} else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
|
} else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
|
||||||
cleanup_out_header(state);
|
cleanup_out_header(state, header_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_missing_headers - insert missing message headers */
|
/* cleanup_header_done_callback - insert missing message headers */
|
||||||
|
|
||||||
static void cleanup_missing_headers(CLEANUP_STATE *state)
|
static void cleanup_header_done_callback(void *context)
|
||||||
{
|
{
|
||||||
|
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
|
||||||
char time_stamp[1024]; /* XXX locale dependent? */
|
char time_stamp[1024]; /* XXX locale dependent? */
|
||||||
struct tm *tp;
|
struct tm *tp;
|
||||||
TOK822 *token;
|
TOK822 *token;
|
||||||
@@ -507,6 +543,74 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
|
|||||||
|
|
||||||
if ((state->headers_seen & VISIBLE_RCPT) == 0)
|
if ((state->headers_seen & VISIBLE_RCPT) == 0)
|
||||||
cleanup_out_format(state, REC_TYPE_NORM, "%s", var_rcpt_witheld);
|
cleanup_out_format(state, REC_TYPE_NORM, "%s", var_rcpt_witheld);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header buffer overflow is an unrecoverable error only if we extract
|
||||||
|
* recipients from the main message headers.
|
||||||
|
*/
|
||||||
|
if (state->mime_errs & MIME_ERR_TRUNC_HEADER)
|
||||||
|
state->errs |= CLEANUP_STAT_HOVFL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup_body_callback - output one body record */
|
||||||
|
|
||||||
|
static void cleanup_body_callback(void *context, int type, const char *buf, int len)
|
||||||
|
{
|
||||||
|
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crude message body content filter for emergencies. This code has
|
||||||
|
* several problems: it sees one line at a time; it looks at long lines
|
||||||
|
* only in chunks of line_length_limit (2048) characters; it is easily
|
||||||
|
* bypassed with encodings and other tricks.
|
||||||
|
*/
|
||||||
|
if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_body_checks) {
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) {
|
||||||
|
if (cleanup_act(state, "body", buf, value, VAR_BODY_CHECKS)
|
||||||
|
== CLEANUP_ACT_DROP)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup_out(state, type, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup_message_headerbody - process message content, header and body */
|
||||||
|
|
||||||
|
static void cleanup_message_headerbody(CLEANUP_STATE *state, int type,
|
||||||
|
char *buf, int len)
|
||||||
|
{
|
||||||
|
char *myname = "cleanup_message_headerbody";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy text record to the output.
|
||||||
|
*/
|
||||||
|
if (type == REC_TYPE_NORM || type == REC_TYPE_CONT) {
|
||||||
|
state->mime_errs = mime_state_update(state->mime_state, type, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To avoid complications elsewhere, text must not end in REC_TYPE_CONT.
|
||||||
|
*
|
||||||
|
* If we have reached the end of the message content segment, record the
|
||||||
|
* current file position so we can compute the message size lateron.
|
||||||
|
*/
|
||||||
|
else if (type == REC_TYPE_XTRA) {
|
||||||
|
state->mime_errs = mime_state_update(state->mime_state, type, buf, len);
|
||||||
|
state->mime_state = mime_state_free(state->mime_state);
|
||||||
|
if ((state->xtra_offset = vstream_ftell(state->dst)) < 0)
|
||||||
|
msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path);
|
||||||
|
state->action = cleanup_extracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should never happen.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
msg_warn("%s: unexpected record type: %d", myname, type);
|
||||||
|
state->errs |= CLEANUP_STAT_BAD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_message - initialize message content segment */
|
/* cleanup_message - initialize message content segment */
|
||||||
@@ -529,136 +633,12 @@ void cleanup_message(CLEANUP_STATE *state, int type, char *buf, int len)
|
|||||||
/*
|
/*
|
||||||
* Pass control to the header processing routine.
|
* Pass control to the header processing routine.
|
||||||
*/
|
*/
|
||||||
state->action = cleanup_message_header;
|
state->mime_state = mime_state_alloc(MIME_OPT_REPORT_TRUNC_HEADER,
|
||||||
cleanup_message_header(state, type, buf, len);
|
cleanup_header_callback,
|
||||||
}
|
cleanup_header_done_callback,
|
||||||
|
cleanup_body_callback,
|
||||||
/* cleanup_message_header - process message content, header */
|
(MIME_STATE_ANY_END) 0,
|
||||||
|
(void *) state);
|
||||||
static void cleanup_message_header(CLEANUP_STATE *state, int type, char *buf, int len)
|
state->action = cleanup_message_headerbody;
|
||||||
{
|
cleanup_message_headerbody(state, type, buf, len);
|
||||||
char *myname = "cleanup_message_header";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sanity check.
|
|
||||||
*/
|
|
||||||
if (strchr(REC_TYPE_CONTENT, type) == 0) {
|
|
||||||
msg_warn("%s: %s: unexpected record type %d",
|
|
||||||
state->queue_id, myname, type);
|
|
||||||
state->errs |= CLEANUP_STAT_BAD;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, deal with header information that we have accumulated from
|
|
||||||
* previous input records.
|
|
||||||
*
|
|
||||||
* If a physical header line exceeds the capacity of a Postfix queue file
|
|
||||||
* record, reconstruct the long line from multiple records (up to the
|
|
||||||
* header size limit), and break the long line up into multiple Postfix
|
|
||||||
* records upon output to the queue file. Discard text that does not fit
|
|
||||||
* in a header buffer, so as to avoid breaking MIME formatting.
|
|
||||||
*
|
|
||||||
* It is left up to delivery agents to glue long lines back together and to
|
|
||||||
* enforce an appropriate output line length limit.
|
|
||||||
*/
|
|
||||||
if (VSTRING_LEN(state->header_buf) > 0) {
|
|
||||||
if (type != REC_TYPE_XTRA) {
|
|
||||||
if (state->prev_header_type == REC_TYPE_CONT) {
|
|
||||||
if (VSTRING_LEN(state->header_buf) < var_header_limit)
|
|
||||||
vstring_strcat(state->header_buf, buf);
|
|
||||||
else
|
|
||||||
state->errs |= CLEANUP_STAT_HOVFL;
|
|
||||||
state->prev_header_type = type;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ISSPACE(*buf)) {
|
|
||||||
if (VSTRING_LEN(state->header_buf) < var_header_limit) {
|
|
||||||
VSTRING_ADDCH(state->header_buf, '\n');
|
|
||||||
vstring_strcat(state->header_buf, buf);
|
|
||||||
} else
|
|
||||||
state->errs |= CLEANUP_STAT_HOVFL;
|
|
||||||
state->prev_header_type = type;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No more input to append to this saved header. Do output processing
|
|
||||||
* and reset the saved header buffer.
|
|
||||||
*/
|
|
||||||
VSTRING_TERMINATE(state->header_buf);
|
|
||||||
cleanup_header(state);
|
|
||||||
VSTRING_RESET(state->header_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Switch to body processing if this is not a header. Generate missing
|
|
||||||
* headers. Add one blank line when the message headers are immediately
|
|
||||||
* followed by a non-empty message body.
|
|
||||||
*/
|
|
||||||
if (type == REC_TYPE_XTRA || !is_header(buf)) {
|
|
||||||
cleanup_missing_headers(state);
|
|
||||||
if (type != REC_TYPE_XTRA && *buf) /* output blank line */
|
|
||||||
cleanup_out_string(state, REC_TYPE_NORM, "");
|
|
||||||
state->action = cleanup_message_body;
|
|
||||||
cleanup_message_body(state, type, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Save this header record until we know that the header is complete.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
vstring_strcpy(state->header_buf, buf);
|
|
||||||
state->prev_header_type = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cleanup_message_body - process message segment, body */
|
|
||||||
|
|
||||||
static void cleanup_message_body(CLEANUP_STATE *state, int type, char *buf, int len)
|
|
||||||
{
|
|
||||||
char *myname = "cleanup_message_body";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy body record to the output.
|
|
||||||
*/
|
|
||||||
if (type == REC_TYPE_NORM || type == REC_TYPE_CONT) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Crude message body content filter for emergencies. This code has
|
|
||||||
* several problems: it sees one line at a time, and therefore does
|
|
||||||
* not recognize multi-line MIME headers in the body; it looks at
|
|
||||||
* long lines only in chunks of line_length_limit (2048) characters;
|
|
||||||
* it is easily bypassed with encodings and with multi-line tricks.
|
|
||||||
*/
|
|
||||||
if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_body_checks) {
|
|
||||||
const char *value;
|
|
||||||
|
|
||||||
if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) {
|
|
||||||
if (cleanup_act(state, "body", buf, value, VAR_BODY_CHECKS)
|
|
||||||
== CLEANUP_ACT_DROP)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cleanup_out(state, type, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have reached the end of the message content segment, record the
|
|
||||||
* current file position so we can compute the message size lateron.
|
|
||||||
*/
|
|
||||||
else if (type == REC_TYPE_XTRA) {
|
|
||||||
if ((state->xtra_offset = vstream_ftell(state->dst)) < 0)
|
|
||||||
msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path);
|
|
||||||
state->action = cleanup_extracted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This should never happen.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
msg_warn("%s: unexpected record type: %d", myname, type);
|
|
||||||
state->errs |= CLEANUP_STAT_BAD;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -12,13 +12,13 @@
|
|||||||
/* void cleanup_out(state, type, data, len)
|
/* void cleanup_out(state, type, data, len)
|
||||||
/* CLEANUP_STATE *state;
|
/* CLEANUP_STATE *state;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *data;
|
/* const char *data;
|
||||||
/* int len;
|
/* int len;
|
||||||
/*
|
/*
|
||||||
/* void cleanup_out_string(state, type, str)
|
/* void cleanup_out_string(state, type, str)
|
||||||
/* CLEANUP_STATE *state;
|
/* CLEANUP_STATE *state;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *str;
|
/* const char *str;
|
||||||
/*
|
/*
|
||||||
/* void CLEANUP_OUT_BUF(state, type, buf)
|
/* void CLEANUP_OUT_BUF(state, type, buf)
|
||||||
/* CLEANUP_STATE *state;
|
/* CLEANUP_STATE *state;
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
/* void cleanup_out_format(state, type, format, ...)
|
/* void cleanup_out_format(state, type, format, ...)
|
||||||
/* CLEANUP_STATE *state;
|
/* CLEANUP_STATE *state;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *format;
|
/* const char *format;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module writes records to the output stream.
|
/* This module writes records to the output stream.
|
||||||
/*
|
/*
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
|
|
||||||
/* cleanup_out - output one single record */
|
/* cleanup_out - output one single record */
|
||||||
|
|
||||||
void cleanup_out(CLEANUP_STATE *state, int type, char *string, int len)
|
void cleanup_out(CLEANUP_STATE *state, int type, const char *string, int len)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@@ -129,14 +129,14 @@ void cleanup_out(CLEANUP_STATE *state, int type, char *string, int len)
|
|||||||
|
|
||||||
/* cleanup_out_string - output string to one single record */
|
/* cleanup_out_string - output string to one single record */
|
||||||
|
|
||||||
void cleanup_out_string(CLEANUP_STATE *state, int type, char *string)
|
void cleanup_out_string(CLEANUP_STATE *state, int type, const char *string)
|
||||||
{
|
{
|
||||||
cleanup_out(state, type, string, strlen(string));
|
cleanup_out(state, type, string, strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup_out_format - output one formatted record */
|
/* cleanup_out_format - output one formatted record */
|
||||||
|
|
||||||
void cleanup_out_format(CLEANUP_STATE *state, int type, char *fmt,...)
|
void cleanup_out_format(CLEANUP_STATE *state, int type, const char *fmt,...)
|
||||||
{
|
{
|
||||||
static VSTRING *vp;
|
static VSTRING *vp;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include <been_here.h>
|
#include <been_here.h>
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
|
#include <mime_state.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@@ -71,9 +72,7 @@ CLEANUP_STATE *cleanup_state_alloc(void)
|
|||||||
state->flags = 0;
|
state->flags = 0;
|
||||||
state->errs = 0;
|
state->errs = 0;
|
||||||
state->err_mask = 0;
|
state->err_mask = 0;
|
||||||
state->header_buf = vstring_alloc(100);
|
|
||||||
state->headers_seen = 0;
|
state->headers_seen = 0;
|
||||||
state->prev_header_type = 0;
|
|
||||||
state->hop_count = 0;
|
state->hop_count = 0;
|
||||||
state->recipients = argv_alloc(2);
|
state->recipients = argv_alloc(2);
|
||||||
state->resent_recip = argv_alloc(2);
|
state->resent_recip = argv_alloc(2);
|
||||||
@@ -88,6 +87,8 @@ CLEANUP_STATE *cleanup_state_alloc(void)
|
|||||||
state->rcpt_count = 0;
|
state->rcpt_count = 0;
|
||||||
state->reason = 0;
|
state->reason = 0;
|
||||||
state->attr = nvtable_create(10);
|
state->attr = nvtable_create(10);
|
||||||
|
state->mime_state = 0;
|
||||||
|
state->mime_errs = 0;
|
||||||
return (state);
|
return (state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +112,6 @@ void cleanup_state_free(CLEANUP_STATE *state)
|
|||||||
myfree(state->return_receipt);
|
myfree(state->return_receipt);
|
||||||
if (state->errors_to)
|
if (state->errors_to)
|
||||||
myfree(state->errors_to);
|
myfree(state->errors_to);
|
||||||
vstring_free(state->header_buf);
|
|
||||||
argv_free(state->recipients);
|
argv_free(state->recipients);
|
||||||
argv_free(state->resent_recip);
|
argv_free(state->resent_recip);
|
||||||
if (state->queue_id)
|
if (state->queue_id)
|
||||||
@@ -120,5 +120,7 @@ void cleanup_state_free(CLEANUP_STATE *state)
|
|||||||
if (state->reason)
|
if (state->reason)
|
||||||
myfree(state->reason);
|
myfree(state->reason);
|
||||||
nvtable_free(state->attr);
|
nvtable_free(state->attr);
|
||||||
|
if (state->mime_state)
|
||||||
|
mime_state_free(state->mime_state);
|
||||||
myfree((char *) state);
|
myfree((char *) state);
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
|
|||||||
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
|
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
|
||||||
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
|
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
|
||||||
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
|
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
|
||||||
verp_sender.c match_parent_style.c
|
verp_sender.c match_parent_style.c mime_state.c header_token.c
|
||||||
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
||||||
debug_peer.o debug_process.o defer.o deliver_completed.o \
|
debug_peer.o debug_process.o defer.o deliver_completed.o \
|
||||||
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
||||||
@@ -40,7 +40,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
|||||||
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
|
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
|
||||||
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
|
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
|
||||||
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
|
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
|
||||||
verp_sender.o match_parent_style.o
|
verp_sender.o match_parent_style.o mime_state.o header_token.o
|
||||||
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
||||||
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
|
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
|
||||||
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
|
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
|
||||||
@@ -57,7 +57,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
|||||||
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
||||||
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
|
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
|
||||||
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
|
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
|
||||||
match_parent_style.h quote_flags.h
|
match_parent_style.h quote_flags.h mime_state.h header_token.h
|
||||||
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
||||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||||
@@ -70,7 +70,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
|
|||||||
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
|
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
|
||||||
off_cvt quote_822_local rec2stream recdump resolve_clnt \
|
off_cvt quote_822_local rec2stream recdump resolve_clnt \
|
||||||
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
||||||
quote_821_local mail_conf_time
|
quote_821_local mail_conf_time mime_state
|
||||||
|
|
||||||
LIBS = ../../lib/libutil.a
|
LIBS = ../../lib/libutil.a
|
||||||
LIB_DIR = ../../lib
|
LIB_DIR = ../../lib
|
||||||
@@ -213,13 +213,23 @@ mail_conf_time: $(LIB) $(LIBS)
|
|||||||
$(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
$(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||||
mv junk $@.o
|
mv junk $@.o
|
||||||
|
|
||||||
tests: tok822_test
|
mime_state: $(LIB) $(LIBS)
|
||||||
|
mv $@.o junk
|
||||||
|
$(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||||
|
mv junk $@.o
|
||||||
|
|
||||||
|
tests: tok822_test mime_test
|
||||||
|
|
||||||
tok822_test: tok822_parse tok822_parse.in tok822_parse.ref
|
tok822_test: tok822_parse tok822_parse.in tok822_parse.ref
|
||||||
./tok822_parse <tok822_parse.in >tok822_parse.tmp
|
./tok822_parse <tok822_parse.in >tok822_parse.tmp
|
||||||
diff tok822_parse.ref tok822_parse.tmp
|
diff tok822_parse.ref tok822_parse.tmp
|
||||||
rm -f tok822_parse.tmp
|
rm -f tok822_parse.tmp
|
||||||
|
|
||||||
|
mime_test: mime_state mime_test.in mime_test.ref
|
||||||
|
./mime_state <mime_test.in >mime_test.tmp
|
||||||
|
diff mime_test.ref mime_test.tmp
|
||||||
|
rm -f mime_test.tmp
|
||||||
|
|
||||||
printfck: $(OBJS) $(PROG)
|
printfck: $(OBJS) $(PROG)
|
||||||
rm -rf printfck
|
rm -rf printfck
|
||||||
mkdir printfck
|
mkdir printfck
|
||||||
@@ -441,7 +451,14 @@ header_opts.o: ../../include/msg.h
|
|||||||
header_opts.o: ../../include/htable.h
|
header_opts.o: ../../include/htable.h
|
||||||
header_opts.o: ../../include/vstring.h
|
header_opts.o: ../../include/vstring.h
|
||||||
header_opts.o: ../../include/vbuf.h
|
header_opts.o: ../../include/vbuf.h
|
||||||
|
header_opts.o: ../../include/stringops.h
|
||||||
header_opts.o: header_opts.h
|
header_opts.o: header_opts.h
|
||||||
|
header_token.o: header_token.c
|
||||||
|
header_token.o: ../../include/sys_defs.h
|
||||||
|
header_token.o: ../../include/msg.h
|
||||||
|
header_token.o: ../../include/vstring.h
|
||||||
|
header_token.o: ../../include/vbuf.h
|
||||||
|
header_token.o: header_token.h
|
||||||
is_header.o: is_header.c
|
is_header.o: is_header.c
|
||||||
is_header.o: ../../include/sys_defs.h
|
is_header.o: ../../include/sys_defs.h
|
||||||
is_header.o: is_header.h
|
is_header.o: is_header.h
|
||||||
@@ -766,6 +783,18 @@ mbox_open.o: ../../include/myflock.h
|
|||||||
mbox_open.o: mbox_conf.h
|
mbox_open.o: mbox_conf.h
|
||||||
mbox_open.o: ../../include/argv.h
|
mbox_open.o: ../../include/argv.h
|
||||||
mbox_open.o: mbox_open.h
|
mbox_open.o: mbox_open.h
|
||||||
|
mime_state.o: mime_state.c
|
||||||
|
mime_state.o: ../../include/sys_defs.h
|
||||||
|
mime_state.o: ../../include/mymalloc.h
|
||||||
|
mime_state.o: ../../include/msg.h
|
||||||
|
mime_state.o: ../../include/vstring.h
|
||||||
|
mime_state.o: ../../include/vbuf.h
|
||||||
|
mime_state.o: rec_type.h
|
||||||
|
mime_state.o: is_header.h
|
||||||
|
mime_state.o: header_opts.h
|
||||||
|
mime_state.o: mail_params.h
|
||||||
|
mime_state.o: header_token.h
|
||||||
|
mime_state.o: mime_state.h
|
||||||
mkmap_db.o: mkmap_db.c
|
mkmap_db.o: mkmap_db.c
|
||||||
mkmap_db.o: ../../include/sys_defs.h
|
mkmap_db.o: ../../include/sys_defs.h
|
||||||
mkmap_db.o: ../../include/msg.h
|
mkmap_db.o: ../../include/msg.h
|
||||||
|
32
postfix/src/global/foobar
Normal file
32
postfix/src/global/foobar
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
Delivered-To: wietse@porcupine.watson.ibm.com
|
||||||
|
Received: from mailhub.watson.ibm.com (mailhub.watson.ibm.com [9.2.250.97])
|
||||||
|
by porcupine.watson.ibm.com (Postfix) with ESMTP for <wietse@porcupine.watson.ibm.com>
|
||||||
|
id 2F0FC188CE; Tue, 12 Jan 1999 15:08:46 -0500 (EST)
|
||||||
|
Received: from wzv.watson.ibm.com (wzv.watson.ibm.com [9.2.84.53]) by mailhub.watson.ibm.com (8.8.7/Feb-20-98) with ESMTP id PAA07748 for <wietse@porcupine.watson.ibm.com>; Tue, 12 Jan 1999 15:08:45 -0500
|
||||||
|
Received: by wzv.watson.ibm.com (Postfix, from userid 309)
|
||||||
|
id 9AC44827; Tue, 12 Jan 1999 15:08:45 -0500 (EST)
|
||||||
|
Delivered-To: wietse@[9.2.84.53]
|
||||||
|
From: wietse
|
||||||
|
To: wietse
|
||||||
|
Subject: testje
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: "multipart" ; boundary = "abcdef" foobar
|
||||||
|
Status: RO
|
||||||
|
|
||||||
|
prolog
|
||||||
|
|
||||||
|
--abcdef
|
||||||
|
|
||||||
|
part01
|
||||||
|
|
||||||
|
--abcdef
|
||||||
|
|
||||||
|
part02
|
||||||
|
|
||||||
|
--abcdef
|
||||||
|
|
||||||
|
part03
|
||||||
|
|
||||||
|
--abcdef--
|
||||||
|
|
||||||
|
epilog
|
@@ -38,6 +38,7 @@
|
|||||||
#include <msg.h>
|
#include <msg.h>
|
||||||
#include <htable.h>
|
#include <htable.h>
|
||||||
#include <vstring.h>
|
#include <vstring.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
@@ -51,14 +52,19 @@ static HEADER_OPTS header_opts[] = {
|
|||||||
"Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
|
"Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
|
||||||
"Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP,
|
"Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP,
|
||||||
"Cc", HDR_CC, HDR_OPT_XRECIP,
|
"Cc", HDR_CC, HDR_OPT_XRECIP,
|
||||||
"Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, 0,
|
"Content-Description", HDR_CONTENT_DESCRIPTION, HDR_OPT_MIME,
|
||||||
|
"Content-Disposition", HDR_CONTENT_DISPOSITION, HDR_OPT_MIME,
|
||||||
|
"Content-ID", HDR_CONTENT_ID, HDR_OPT_MIME,
|
||||||
"Content-Length", HDR_CONTENT_LENGTH, HDR_OPT_DROP,
|
"Content-Length", HDR_CONTENT_LENGTH, HDR_OPT_DROP,
|
||||||
|
"Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, HDR_OPT_MIME,
|
||||||
|
"Content-Type", HDR_CONTENT_TYPE, HDR_OPT_MIME,
|
||||||
"Delivered-To", HDR_DELIVERED_TO, 0,
|
"Delivered-To", HDR_DELIVERED_TO, 0,
|
||||||
"Date", HDR_DATE, 0,
|
"Date", HDR_DATE, 0,
|
||||||
"Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
|
"Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
|
||||||
"From", HDR_FROM, HDR_OPT_SENDER,
|
"From", HDR_FROM, HDR_OPT_SENDER,
|
||||||
"Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
|
"Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
|
||||||
"Message-Id", HDR_MESSAGE_ID, 0,
|
"Message-Id", HDR_MESSAGE_ID, 0,
|
||||||
|
"MIME-Version", HDR_MIME_VERSION, HDR_OPT_MIME,
|
||||||
"Received", HDR_RECEIVED, 0,
|
"Received", HDR_RECEIVED, 0,
|
||||||
"Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
|
"Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
|
||||||
"Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP | HDR_OPT_RR,
|
"Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP | HDR_OPT_RR,
|
||||||
@@ -120,6 +126,9 @@ HEADER_OPTS *header_opts_find(const char *string)
|
|||||||
msg_panic("header_opts_find: no colon in header: %.30s", string);
|
msg_panic("header_opts_find: no colon in header: %.30s", string);
|
||||||
VSTRING_ADDCH(header_key, TOLOWER(*cp));
|
VSTRING_ADDCH(header_key, TOLOWER(*cp));
|
||||||
}
|
}
|
||||||
|
vstring_truncate(header_key,
|
||||||
|
trimblanks(vstring_str(header_key), cp - string)
|
||||||
|
- vstring_str(header_key));
|
||||||
VSTRING_TERMINATE(header_key);
|
VSTRING_TERMINATE(header_key);
|
||||||
return ((HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
|
return ((HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
|
||||||
}
|
}
|
||||||
|
@@ -49,6 +49,10 @@ typedef struct {
|
|||||||
#define HDR_SENDER 24
|
#define HDR_SENDER 24
|
||||||
#define HDR_TO 25
|
#define HDR_TO 25
|
||||||
#define HDR_MAIL_FOLLOWUP_TO 26
|
#define HDR_MAIL_FOLLOWUP_TO 26
|
||||||
|
#define HDR_CONTENT_DESCRIPTION 27
|
||||||
|
#define HDR_CONTENT_DISPOSITION 28
|
||||||
|
#define HDR_CONTENT_ID 29
|
||||||
|
#define HDR_MIME_VERSION 30
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header flags.
|
* Header flags.
|
||||||
@@ -58,6 +62,7 @@ typedef struct {
|
|||||||
#define HDR_OPT_RECIP (1<<2) /* recipient address */
|
#define HDR_OPT_RECIP (1<<2) /* recipient address */
|
||||||
#define HDR_OPT_RR (1<<3) /* Resent- header */
|
#define HDR_OPT_RR (1<<3) /* Resent- header */
|
||||||
#define HDR_OPT_EXTRACT (1<<4) /* extract flag */
|
#define HDR_OPT_EXTRACT (1<<4) /* extract flag */
|
||||||
|
#define HDR_OPT_MIME (1<<5) /* MIME header */
|
||||||
|
|
||||||
#define HDR_OPT_XRECIP (HDR_OPT_RECIP | HDR_OPT_EXTRACT)
|
#define HDR_OPT_XRECIP (HDR_OPT_RECIP | HDR_OPT_EXTRACT)
|
||||||
|
|
||||||
|
263
postfix/src/global/header_token.c
Normal file
263
postfix/src/global/header_token.c
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* header_token 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* mail header parser
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <header_token.h>
|
||||||
|
/*
|
||||||
|
/* typedef struct {
|
||||||
|
/* .in +4
|
||||||
|
/* int type;
|
||||||
|
/* const char *u.value;
|
||||||
|
/* /* ... */
|
||||||
|
/* .in
|
||||||
|
/* } HEADER_TOKEN;
|
||||||
|
/*
|
||||||
|
/* int header_token(token, token_len, token_buffer, ptr,
|
||||||
|
/* specials, terminator)
|
||||||
|
/* HEADER_TOKEN *token;
|
||||||
|
/* int token_len;
|
||||||
|
/* VSTRING *token_buffer;
|
||||||
|
/* const char **ptr;
|
||||||
|
/* const char *specials;
|
||||||
|
/* int terminator;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* This module parses a mail header value (text after field-name:)
|
||||||
|
/* into tokens. The parser understands RFC 822 linear white space,
|
||||||
|
/* quoted-string, comment, control characters, and a set of
|
||||||
|
/* user-specified special characters.
|
||||||
|
/*
|
||||||
|
/* A token type is one of the following:
|
||||||
|
/* .IP HEADER_TOK_QSTRING
|
||||||
|
/* Quoted string as per RFC 822.
|
||||||
|
/* .IP HEADER_TOK_TOKEN
|
||||||
|
/* Token as per RFC 822, and the special characters supplied by the
|
||||||
|
/* caller.
|
||||||
|
/* .IP other
|
||||||
|
/* The value of a control character or special character.
|
||||||
|
/* .PP
|
||||||
|
/* header_token() tokenizes the input and stops after a user-specified
|
||||||
|
/* terminator (ignoring all tokens that exceed the capacity of
|
||||||
|
/* the result storage), or when it runs out of space for the result.
|
||||||
|
/* The terminator is not stored. The result value is the number of
|
||||||
|
/* tokens stored, or -1 when the input was exhausted before any tokens
|
||||||
|
/* were found.
|
||||||
|
/*
|
||||||
|
/* Arguments:
|
||||||
|
/* .IP token
|
||||||
|
/* Result array of HEADER_TOKEN structures.
|
||||||
|
/* .IP token_len
|
||||||
|
/* Length of the array of HEADER_TOKEN structures.
|
||||||
|
/* .IP token_buffer
|
||||||
|
/* Storage for result token values.
|
||||||
|
/* .IP ptr
|
||||||
|
/* Input/output read position. The input is a null-terminated string.
|
||||||
|
/* .IP specials
|
||||||
|
/* Special characters according to the relevant RFC, or a
|
||||||
|
/* null pointer (default to the RFC 822 special characters).
|
||||||
|
/* This must include the optional terminator if one is specified.
|
||||||
|
/* .IP terminator
|
||||||
|
/* The special character to stop after, or zero.
|
||||||
|
/* BUGS
|
||||||
|
/* Eight-bit characters are not given special treatment.
|
||||||
|
/* SEE ALSO
|
||||||
|
/* RFC 822 (ARPA Internet Text Messages)
|
||||||
|
/* DIAGNOSTICS
|
||||||
|
/* Fatal errors: memory allocation problem.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <vstring.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <header_token.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special characters and linear white space, as per RFC 822.
|
||||||
|
*/
|
||||||
|
#define RFC822_SPECIALS "()<>@,;:\\\".[]"
|
||||||
|
#define RFC822_LWSP(ch) (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Silly little macros.
|
||||||
|
*/
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
#define LEN(x) VSTRING_LEN(x)
|
||||||
|
#define CU_CHAR_PTR(x) ((const unsigned char *) (x))
|
||||||
|
|
||||||
|
/* header_token - parse out the next item in a message header */
|
||||||
|
|
||||||
|
int header_token(HEADER_TOKEN *token, int token_len,
|
||||||
|
VSTRING *token_buffer, const char **ptr,
|
||||||
|
const char *user_specials, int user_terminator)
|
||||||
|
{
|
||||||
|
int comment_level;
|
||||||
|
const unsigned char *cp;
|
||||||
|
int len;
|
||||||
|
int ch;
|
||||||
|
int tok_count;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize.
|
||||||
|
*/
|
||||||
|
VSTRING_RESET(token_buffer);
|
||||||
|
cp = CU_CHAR_PTR(*ptr);
|
||||||
|
tok_count = 0;
|
||||||
|
if (user_specials == 0)
|
||||||
|
user_specials = RFC822_SPECIALS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main parsing loop.
|
||||||
|
*/
|
||||||
|
while ((ch = *cp) != 0 && (user_terminator != 0 || tok_count < token_len)) {
|
||||||
|
cp++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip RFC 822 linear white space.
|
||||||
|
*/
|
||||||
|
if (RFC822_LWSP(ch))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminator.
|
||||||
|
*/
|
||||||
|
if (ch == user_terminator)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip RFC 822 comment.
|
||||||
|
*/
|
||||||
|
if (ch == '(') {
|
||||||
|
comment_level = 1;
|
||||||
|
while ((ch = *cp) != 0) {
|
||||||
|
cp++;
|
||||||
|
if (ch == '(') { /* comments can nest! */
|
||||||
|
comment_level++;
|
||||||
|
} else if (ch == ')') {
|
||||||
|
if (--comment_level == 0)
|
||||||
|
break;
|
||||||
|
} else if (ch == '\\') {
|
||||||
|
if ((ch = *cp) == 0)
|
||||||
|
break;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy quoted text according to RFC 822.
|
||||||
|
*/
|
||||||
|
if (ch == '"') {
|
||||||
|
if (tok_count < token_len) {
|
||||||
|
token[tok_count].u.offset = LEN(token_buffer);
|
||||||
|
token[tok_count].type = HEADER_TOK_QSTRING;
|
||||||
|
}
|
||||||
|
while ((ch = *cp) != 0) {
|
||||||
|
cp++;
|
||||||
|
if (ch == '"')
|
||||||
|
break;
|
||||||
|
if (ch == '\n') { /* unfold */
|
||||||
|
len = LEN(token_buffer);
|
||||||
|
while (len > 0 && RFC822_LWSP(STR(token_buffer)[len - 1]))
|
||||||
|
len--;
|
||||||
|
if (len < LEN(token_buffer))
|
||||||
|
vstring_truncate(token_buffer, len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ch == '\\') {
|
||||||
|
if ((ch = *cp) == 0)
|
||||||
|
break;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
if (tok_count < token_len)
|
||||||
|
VSTRING_ADDCH(token_buffer, ch);
|
||||||
|
}
|
||||||
|
if (tok_count < token_len) {
|
||||||
|
VSTRING_ADDCH(token_buffer, 0);
|
||||||
|
tok_count++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control, or special.
|
||||||
|
*/
|
||||||
|
if (strchr(user_specials, ch) || ISCNTRL(ch)) {
|
||||||
|
if (tok_count < token_len) {
|
||||||
|
token[tok_count].u.offset = LEN(token_buffer);
|
||||||
|
token[tok_count].type = ch;
|
||||||
|
VSTRING_ADDCH(token_buffer, ch);
|
||||||
|
VSTRING_ADDCH(token_buffer, 0);
|
||||||
|
tok_count++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Token.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
if (tok_count < token_len) {
|
||||||
|
token[tok_count].u.offset = LEN(token_buffer);
|
||||||
|
token[tok_count].type = HEADER_TOK_TOKEN;
|
||||||
|
VSTRING_ADDCH(token_buffer, ch);
|
||||||
|
}
|
||||||
|
while ((ch = *cp) != 0 && !RFC822_LWSP(ch)
|
||||||
|
&& !ISCNTRL(ch) && !strchr(user_specials, ch)) {
|
||||||
|
cp++;
|
||||||
|
if (tok_count < token_len)
|
||||||
|
VSTRING_ADDCH(token_buffer, ch);
|
||||||
|
}
|
||||||
|
if (tok_count < token_len) {
|
||||||
|
VSTRING_ADDCH(token_buffer, 0);
|
||||||
|
tok_count++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore a zero-length item after the last terminator.
|
||||||
|
*/
|
||||||
|
if (tok_count == 0 && ch == 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finalize. Fill in the string pointer array, now that the token buffer
|
||||||
|
* is no longer dynamically reallocated as it grows.
|
||||||
|
*/
|
||||||
|
*ptr = (const char *) cp;
|
||||||
|
for (n = 0; n < tok_count; n++)
|
||||||
|
token[n].u.value = STR(token_buffer) + token[n].u.offset;
|
||||||
|
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("header_token: %s %s %s",
|
||||||
|
tok_count > 0 ? token[0].u.value : "",
|
||||||
|
tok_count > 1 ? token[1].u.value : "",
|
||||||
|
tok_count > 2 ? token[2].u.value : "");
|
||||||
|
|
||||||
|
return (tok_count);
|
||||||
|
}
|
47
postfix/src/global/header_token.h
Normal file
47
postfix/src/global/header_token.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef _HEADER_TOKEN_H_INCLUDED_
|
||||||
|
#define _HEADER_TOKEN_H_INCLUDED_
|
||||||
|
|
||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* header_token 3h
|
||||||
|
/* SUMMARY
|
||||||
|
/* mail header parser
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include "header_token.h"
|
||||||
|
DESCRIPTION
|
||||||
|
.nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility library.
|
||||||
|
*/
|
||||||
|
#include <vstring.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HEADER header parser tokens. Specials and controls are represented by
|
||||||
|
* themselves. Character pointers point to substrings in a token buffer.
|
||||||
|
*/
|
||||||
|
typedef struct HEADER_TOKEN {
|
||||||
|
int type; /* see below */
|
||||||
|
union {
|
||||||
|
const char *value; /* just a pointer, not a copy */
|
||||||
|
int offset; /* index into token buffer */
|
||||||
|
} u; /* indent beats any alternative */
|
||||||
|
} HEADER_TOKEN;
|
||||||
|
|
||||||
|
#define HEADER_TOK_TOKEN 256
|
||||||
|
#define HEADER_TOK_QSTRING 257
|
||||||
|
|
||||||
|
extern int header_token(HEADER_TOKEN *, int, VSTRING *, const char **, const char *, int);
|
||||||
|
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
#endif
|
@@ -10,8 +10,8 @@
|
|||||||
/* const char *string;
|
/* const char *string;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* is_header() examines the given string and returns non-zero (true)
|
/* is_header() examines the given string and returns non-zero (true)
|
||||||
/* when it begins with a mail header name + colon. This routine
|
/* when it begins with a mail header name + optional space + colon.
|
||||||
/* permits 8-bit data in header labels.
|
/* The result is the length of the mail header name.
|
||||||
/* STANDARDS
|
/* STANDARDS
|
||||||
/* RFC 822 (ARPA Internet Text Messages)
|
/* RFC 822 (ARPA Internet Text Messages)
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
@@ -38,21 +38,42 @@
|
|||||||
|
|
||||||
int is_header(const char *str)
|
int is_header(const char *str)
|
||||||
{
|
{
|
||||||
const char *cp;
|
const unsigned char *cp;
|
||||||
|
int state;
|
||||||
int c;
|
int c;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
#define INIT 0
|
||||||
|
#define IN_CHAR 1
|
||||||
|
#define IN_CHAR_SPACE 2
|
||||||
|
#define CU_CHAR_PTR(x) ((const unsigned char *) (x))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX RFC 2822 Section 4.5.2, Obsolete header fields: whitespace may
|
* XXX RFC 2822 Section 4.5, Obsolete header fields: whitespace may
|
||||||
* appear between header label and ":" (see: RFC 822, Section 3.4.2.).
|
* appear between header label and ":" (see: RFC 822, Section 3.4.2.).
|
||||||
*
|
|
||||||
* The code below allows no such whitespace. This has never been a problem,
|
|
||||||
* and therefore we're not inclined to add code for it.
|
|
||||||
*/
|
*/
|
||||||
for (cp = str; (c = *(unsigned char *) cp) != 0; cp++) {
|
for (len = 0, state = INIT, cp = CU_CHAR_PTR(str); (c = *cp) != 0; cp++) {
|
||||||
if (c == ':')
|
switch (c) {
|
||||||
return (cp > str);
|
default:
|
||||||
if ( /* !ISASCII(c) || */ ISSPACE(c) || ISCNTRL(c))
|
if (!ISASCII(c) || ISCNTRL(c))
|
||||||
break;
|
return (0);
|
||||||
|
if (state == INIT)
|
||||||
|
state = IN_CHAR;
|
||||||
|
if (state == IN_CHAR) {
|
||||||
|
len++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
if (state == IN_CHAR)
|
||||||
|
state = IN_CHAR_SPACE;
|
||||||
|
if (state == IN_CHAR_SPACE)
|
||||||
|
continue;
|
||||||
|
return (0);
|
||||||
|
case ':':
|
||||||
|
return ((state == IN_CHAR || state == IN_CHAR_SPACE) ? len : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
73
postfix/src/global/is_header.c+
Normal file
73
postfix/src/global/is_header.c+
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* is_header 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* message header classification
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <is_header.h>
|
||||||
|
/*
|
||||||
|
/* int is_header(string)
|
||||||
|
/* const char *string;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* is_header() examines the given string and returns non-zero (true)
|
||||||
|
/* when it begins with a mail header name + colon. This routine
|
||||||
|
/* permits 8-bit data in header labels.
|
||||||
|
/* STANDARDS
|
||||||
|
/* RFC 822 (ARPA Internet Text Messages)
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include "sys_defs.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include "is_header.h"
|
||||||
|
|
||||||
|
/* is_header - determine if this can be a header line */
|
||||||
|
|
||||||
|
int is_header(const char *str)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
int state;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
#define INITIAL 0
|
||||||
|
#define IN_CHAR 1
|
||||||
|
#define IN_CHAR_SPACE 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX RFC 2822 Section 4.5, Obsolete header fields: whitespace may
|
||||||
|
* appear between header label and ":" (see: RFC 822, Section 3.4.2.).
|
||||||
|
*
|
||||||
|
* The code below allows no such whitespace. This has never been a problem,
|
||||||
|
* and therefore we're not inclined to add code for it.
|
||||||
|
*
|
||||||
|
* XXX It may, however, present another ambiguity with respect to finding
|
||||||
|
* attachment message headers. Sendmail rewrites obsolete forms.
|
||||||
|
*/
|
||||||
|
for (state = INITIAL, cp = str; (c = *(unsigned char *) cp) != 0; cp++) {
|
||||||
|
if (c == ':')
|
||||||
|
return (state == IN_CHAR || state == IN_CHAR_SPACE);
|
||||||
|
if (c == ' ') {
|
||||||
|
if (state == IN_CHAR)
|
||||||
|
state = IN_CHAR_SPACE;
|
||||||
|
if (state != IN_CHAR_SPACE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ISASCII(c) || ISCNTRL(c))
|
||||||
|
break;
|
||||||
|
if (state == INITIAL) state = IN_CHAR
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
@@ -87,6 +87,9 @@
|
|||||||
/* char *var_flush_service;
|
/* char *var_flush_service;
|
||||||
/* int var_db_create_buf;
|
/* int var_db_create_buf;
|
||||||
/* int var_db_read_buf;
|
/* int var_db_read_buf;
|
||||||
|
/* int var_mime_maxdepth;
|
||||||
|
/* int var_mime_bound_len;
|
||||||
|
/* int var_header_limit;
|
||||||
/*
|
/*
|
||||||
/* void mail_params_init()
|
/* void mail_params_init()
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
@@ -230,6 +233,9 @@ char *var_error_service;
|
|||||||
char *var_flush_service;
|
char *var_flush_service;
|
||||||
int var_db_create_buf;
|
int var_db_create_buf;
|
||||||
int var_db_read_buf;
|
int var_db_read_buf;
|
||||||
|
int var_mime_maxdepth;
|
||||||
|
int var_mime_bound_len;
|
||||||
|
int var_header_limit;
|
||||||
|
|
||||||
#define MAIN_CONF_FILE "main.cf"
|
#define MAIN_CONF_FILE "main.cf"
|
||||||
|
|
||||||
@@ -465,6 +471,9 @@ void mail_params_init()
|
|||||||
VAR_FAULT_INJ_CODE, DEF_FAULT_INJ_CODE, &var_fault_inj_code, 0, 0,
|
VAR_FAULT_INJ_CODE, DEF_FAULT_INJ_CODE, &var_fault_inj_code, 0, 0,
|
||||||
VAR_DB_CREATE_BUF, DEF_DB_CREATE_BUF, &var_db_create_buf, 1, 0,
|
VAR_DB_CREATE_BUF, DEF_DB_CREATE_BUF, &var_db_create_buf, 1, 0,
|
||||||
VAR_DB_READ_BUF, DEF_DB_READ_BUF, &var_db_read_buf, 1, 0,
|
VAR_DB_READ_BUF, DEF_DB_READ_BUF, &var_db_read_buf, 1, 0,
|
||||||
|
VAR_HEADER_LIMIT, DEF_HEADER_LIMIT, &var_header_limit, 1, 0,
|
||||||
|
VAR_MIME_MAXDEPTH, DEF_MIME_MAXDEPTH, &var_mime_maxdepth, 1, 0,
|
||||||
|
VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_TIME_TABLE time_defaults[] = {
|
static CONFIG_TIME_TABLE time_defaults[] = {
|
||||||
|
@@ -984,6 +984,14 @@ extern int var_queue_minfree;
|
|||||||
#define DEF_HEADER_CHECKS ""
|
#define DEF_HEADER_CHECKS ""
|
||||||
extern char *var_header_checks;
|
extern char *var_header_checks;
|
||||||
|
|
||||||
|
#define VAR_MIMEHDR_CHECKS "mime_header_checks"
|
||||||
|
#define DEF_MIMEHDR_CHECKS "$header_checks"
|
||||||
|
extern char *var_mimehdr_checks;
|
||||||
|
|
||||||
|
#define VAR_NESTHDR_CHECKS "nested_header_checks"
|
||||||
|
#define DEF_NESTHDR_CHECKS "$header_checks"
|
||||||
|
extern char *var_nesthdr_checks;
|
||||||
|
|
||||||
#define VAR_BODY_CHECKS "body_checks"
|
#define VAR_BODY_CHECKS "body_checks"
|
||||||
#define DEF_BODY_CHECKS ""
|
#define DEF_BODY_CHECKS ""
|
||||||
extern char *var_body_checks;
|
extern char *var_body_checks;
|
||||||
@@ -1504,6 +1512,17 @@ extern int var_db_read_buf;
|
|||||||
#define DEF_QATTR_COUNT_LIMIT 100
|
#define DEF_QATTR_COUNT_LIMIT 100
|
||||||
extern int var_qattr_count_limit;
|
extern int var_qattr_count_limit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MIME support.
|
||||||
|
*/
|
||||||
|
#define VAR_MIME_MAXDEPTH "mime_nesting_limit"
|
||||||
|
#define DEF_MIME_MAXDEPTH 100
|
||||||
|
extern int var_mime_maxdepth;
|
||||||
|
|
||||||
|
#define VAR_MIME_BOUND_LEN "mime_boundary_length_limit"
|
||||||
|
#define DEF_MIME_BOUND_LEN 100
|
||||||
|
extern int var_mime_bound_len;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change the patchlevel and the release date. Snapshots change the
|
* Patches change the patchlevel and the release date. Snapshots change the
|
||||||
* release date only, unless they include the same bugfix as a patch release.
|
* release date only, unless they include the same bugfix as a patch release.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20020514"
|
#define MAIL_RELEASE_DATE "20020524"
|
||||||
|
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "1.1.10-" MAIL_RELEASE_DATE
|
#define DEF_MAIL_VERSION "1.1.10-" MAIL_RELEASE_DATE
|
||||||
|
1061
postfix/src/global/mime_state.c
Normal file
1061
postfix/src/global/mime_state.c
Normal file
File diff suppressed because it is too large
Load Diff
84
postfix/src/global/mime_state.h
Normal file
84
postfix/src/global/mime_state.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#ifndef _MIME_STATE_H_INCLUDED_
|
||||||
|
#define _MIME_STATE_H_INCLUDED_
|
||||||
|
|
||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* mime_state 3h
|
||||||
|
/* SUMMARY
|
||||||
|
/* MIME parser state engine
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include "mime_state.h"
|
||||||
|
DESCRIPTION
|
||||||
|
.nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility library.
|
||||||
|
*/
|
||||||
|
#include <vstring.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global library.
|
||||||
|
*/
|
||||||
|
#include <header_opts.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External interface. All MIME_STATE structure members are private.
|
||||||
|
*/
|
||||||
|
typedef struct MIME_STATE MIME_STATE;
|
||||||
|
typedef void (*MIME_STATE_HEAD_OUT) (void *, int, HEADER_OPTS *, VSTRING *);
|
||||||
|
typedef void (*MIME_STATE_BODY_OUT) (void *, int, const char *, int);
|
||||||
|
typedef void (*MIME_STATE_ANY_END) (void *);
|
||||||
|
|
||||||
|
extern MIME_STATE *mime_state_alloc(int, MIME_STATE_HEAD_OUT, MIME_STATE_ANY_END, MIME_STATE_BODY_OUT, MIME_STATE_ANY_END, void *);
|
||||||
|
extern int mime_state_update(MIME_STATE *, int, const char *, int);
|
||||||
|
extern MIME_STATE *mime_state_free(MIME_STATE *);
|
||||||
|
extern const char *mime_state_error(int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Processing options.
|
||||||
|
*/
|
||||||
|
#define MIME_OPT_NONE (0)
|
||||||
|
#define MIME_OPT_DOWNGRADE (1<<0)
|
||||||
|
#define MIME_OPT_REPORT_8BIT_IN_7BIT_BODY (1<<1)
|
||||||
|
#define MIME_OPT_REPORT_8BIT_IN_HEADER (1<<2)
|
||||||
|
#define MIME_OPT_REPORT_ENCODING_DOMAIN (1<<3)
|
||||||
|
#define MIME_OPT_RECURSE_ALL_MESSAGE (1<<4)
|
||||||
|
#define MIME_OPT_REPORT_TRUNC_HEADER (1<<5)
|
||||||
|
#define MIME_OPT_DISABLE_MIME (1<<6)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Body encoding domains.
|
||||||
|
*/
|
||||||
|
#define MIME_ENC_7BIT (7)
|
||||||
|
#define MIME_ENC_8BIT (8)
|
||||||
|
#define MIME_ENC_BINARY (9)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Processing errors, not necessarily lethal.
|
||||||
|
*/
|
||||||
|
#define MIME_ERR_NESTING (1<<0)
|
||||||
|
#define MIME_ERR_TRUNC_HEADER (1<<1)
|
||||||
|
#define MIME_ERR_8BIT_IN_HEADER (1<<2)
|
||||||
|
#define MIME_ERR_8BIT_IN_7BIT_BODY (1<<3)
|
||||||
|
#define MIME_ERR_ENCODING_DOMAIN (1<<4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header classes. Look at the header_opts argument to find out if something
|
||||||
|
* is a MIME header in a primary or nested section.
|
||||||
|
*/
|
||||||
|
#define MIME_HDR_PRIMARY (1) /* initial headers */
|
||||||
|
#define MIME_HDR_MULTIPART (2) /* headers after multipart boundary */
|
||||||
|
#define MIME_HDR_NESTED (3) /* attached message initial headers */
|
||||||
|
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
#endif
|
38
postfix/src/global/mime_test.in
Normal file
38
postfix/src/global/mime_test.in
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
subject: primary subject
|
||||||
|
content-type : multipart/(co\m\)ment)mumble mumble; boundary = "ab\cd
|
||||||
|
ef" mumble
|
||||||
|
|
||||||
|
abcdef prolog
|
||||||
|
|
||||||
|
--abcd ef
|
||||||
|
content-type: message/rfc822; mumble
|
||||||
|
|
||||||
|
subject: nested subject
|
||||||
|
content-type: multipart/mumble; boundary(comment)="pqrs"
|
||||||
|
content-transfer-encoding: base64
|
||||||
|
|
||||||
|
pqrs prolog
|
||||||
|
|
||||||
|
--pqrs
|
||||||
|
header: pqrs part 01
|
||||||
|
|
||||||
|
body pqrs part 01
|
||||||
|
|
||||||
|
--pqrs
|
||||||
|
header: pqrs part 02
|
||||||
|
|
||||||
|
body pqrs part 02
|
||||||
|
|
||||||
|
--bogus-boundary
|
||||||
|
header: wietse
|
||||||
|
|
||||||
|
body asdasads
|
||||||
|
|
||||||
|
--abcd ef
|
||||||
|
header: abcdef part 02
|
||||||
|
|
||||||
|
body abcdef part 02
|
||||||
|
|
||||||
|
--abcd ef--
|
||||||
|
|
||||||
|
epilog
|
51
postfix/src/global/mime_test.ref
Normal file
51
postfix/src/global/mime_test.ref
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
MAIN subject: primary subject
|
||||||
|
mime_state: header_token: multipart / mumble
|
||||||
|
mime_state: header_token: boundary = abcd ef
|
||||||
|
mime_state: PUSH boundary abcd ef
|
||||||
|
MAIN content-type: multipart/(co\m\)ment)mumble mumble; boundary = "ab\cd
|
||||||
|
ef" mumble
|
||||||
|
HEADER END
|
||||||
|
BODY
|
||||||
|
BODY abcdef prolog
|
||||||
|
BODY
|
||||||
|
BODY --abcd ef
|
||||||
|
mime_state: header_token: message / rfc822
|
||||||
|
MULT content-type: message/rfc822; mumble
|
||||||
|
BODY
|
||||||
|
NEST subject: nested subject
|
||||||
|
mime_state: header_token: multipart / mumble
|
||||||
|
mime_state: header_token: boundary = pqrs
|
||||||
|
mime_state: PUSH boundary pqrs
|
||||||
|
NEST content-type: multipart/mumble; boundary(comment)="pqrs"
|
||||||
|
mime_state: header_token: base64
|
||||||
|
NEST content-transfer-encoding: base64
|
||||||
|
BODY
|
||||||
|
BODY pqrs prolog
|
||||||
|
BODY
|
||||||
|
BODY --pqrs
|
||||||
|
MULT header: pqrs part 01
|
||||||
|
BODY
|
||||||
|
BODY body pqrs part 01
|
||||||
|
BODY
|
||||||
|
BODY --pqrs
|
||||||
|
MULT header: pqrs part 02
|
||||||
|
BODY
|
||||||
|
BODY body pqrs part 02
|
||||||
|
BODY
|
||||||
|
BODY --bogus-boundary
|
||||||
|
BODY header: wietse
|
||||||
|
BODY
|
||||||
|
BODY body asdasads
|
||||||
|
BODY
|
||||||
|
mime_state: POP boundary pqrs
|
||||||
|
BODY --abcd ef
|
||||||
|
MULT header: abcdef part 02
|
||||||
|
BODY
|
||||||
|
BODY body abcdef part 02
|
||||||
|
BODY
|
||||||
|
mime_state: POP boundary abcd ef
|
||||||
|
BODY --abcd ef--
|
||||||
|
BODY
|
||||||
|
BODY epilog
|
||||||
|
BODY END
|
||||||
|
mime_state: warning: improper message/* or multipart/* encoding domain
|
@@ -25,7 +25,7 @@
|
|||||||
/* This module implements record I/O on top of stream-lf files.
|
/* This module implements record I/O on top of stream-lf files.
|
||||||
/*
|
/*
|
||||||
/* rec_streamlf_get() reads one record from the specified stream.
|
/* rec_streamlf_get() reads one record from the specified stream.
|
||||||
/* The result is not null-terminated and may contain embedded null
|
/* The result is null-terminated and may contain embedded null
|
||||||
/* characters.
|
/* characters.
|
||||||
/* The \fImaxlen\fR argument specifies an upper bound to the amount
|
/* The \fImaxlen\fR argument specifies an upper bound to the amount
|
||||||
/* of data read. The result is REC_TYPE_NORM when the record was
|
/* of data read. The result is REC_TYPE_NORM when the record was
|
||||||
@@ -87,10 +87,13 @@ int rec_streamlf_get(VSTREAM *stream, VSTRING *buf, int maxlen)
|
|||||||
while (n-- > 0) {
|
while (n-- > 0) {
|
||||||
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF)
|
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF)
|
||||||
return (VSTRING_LEN(buf) > 0 ? REC_TYPE_CONT : REC_TYPE_EOF);
|
return (VSTRING_LEN(buf) > 0 ? REC_TYPE_CONT : REC_TYPE_EOF);
|
||||||
if (ch == '\n')
|
if (ch == '\n') {
|
||||||
|
VSTRING_TERMINATE(buf);
|
||||||
return (REC_TYPE_NORM);
|
return (REC_TYPE_NORM);
|
||||||
|
}
|
||||||
VSTRING_ADDCH(buf, ch);
|
VSTRING_ADDCH(buf, ch);
|
||||||
}
|
}
|
||||||
|
VSTRING_TERMINATE(buf);
|
||||||
return (REC_TYPE_CONT);
|
return (REC_TYPE_CONT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -173,6 +173,15 @@ char *xfer_states[LMTP_STATE_LAST] = {
|
|||||||
"sending QUIT",
|
"sending QUIT",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *xfer_request[LMTP_STATE_LAST] = {
|
||||||
|
"MAIL FROM command",
|
||||||
|
"RCPT TO command",
|
||||||
|
"DATA command",
|
||||||
|
"end of DATA command",
|
||||||
|
"final RSET command",
|
||||||
|
"QUIT command",
|
||||||
|
};
|
||||||
|
|
||||||
/* lmtp_lhlo - perform initial handshake with LMTP server */
|
/* lmtp_lhlo - perform initial handshake with LMTP server */
|
||||||
|
|
||||||
int lmtp_lhlo(LMTP_STATE *state)
|
int lmtp_lhlo(LMTP_STATE *state)
|
||||||
@@ -488,8 +497,10 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
case LMTP_STATE_MAIL:
|
case LMTP_STATE_MAIL:
|
||||||
if (resp->code / 100 != 2) {
|
if (resp->code / 100 != 2) {
|
||||||
lmtp_mesg_fail(state, resp->code,
|
lmtp_mesg_fail(state, resp->code,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[LMTP_STATE_MAIL]);
|
||||||
mail_from_rejected = 1;
|
mail_from_rejected = 1;
|
||||||
}
|
}
|
||||||
recv_state = LMTP_STATE_RCPT;
|
recv_state = LMTP_STATE_RCPT;
|
||||||
@@ -522,8 +533,10 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
survivors[nrcpt++] = recv_rcpt;
|
survivors[nrcpt++] = recv_rcpt;
|
||||||
} else {
|
} else {
|
||||||
lmtp_rcpt_fail(state, resp->code, rcpt,
|
lmtp_rcpt_fail(state, resp->code, rcpt,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[LMTP_STATE_RCPT]);
|
||||||
rcpt->offset = 0; /* in case deferred */
|
rcpt->offset = 0; /* in case deferred */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,8 +553,10 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
if (resp->code / 100 != 3) {
|
if (resp->code / 100 != 3) {
|
||||||
if (nrcpt > 0)
|
if (nrcpt > 0)
|
||||||
lmtp_mesg_fail(state, resp->code,
|
lmtp_mesg_fail(state, resp->code,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[LMTP_STATE_DATA]);
|
||||||
nrcpt = -1;
|
nrcpt = -1;
|
||||||
}
|
}
|
||||||
recv_state = LMTP_STATE_DOT;
|
recv_state = LMTP_STATE_DOT;
|
||||||
@@ -570,8 +585,10 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lmtp_rcpt_fail(state, resp->code, rcpt,
|
lmtp_rcpt_fail(state, resp->code, rcpt,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[LMTP_STATE_DOT]);
|
||||||
rcpt->offset = 0; /* in case deferred */
|
rcpt->offset = 0; /* in case deferred */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -415,9 +415,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
message->queue_id, error_text, start);
|
message->queue_id, error_text, start);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strcmp(name, MAIL_ATTR_ENCODING) == 0)
|
/* Allow extra segment to override envelope segment info. */
|
||||||
if (message->encoding == 0)
|
if (strcmp(name, MAIL_ATTR_ENCODING) == 0) {
|
||||||
message->encoding = mystrdup(value);
|
if (message->encoding != 0)
|
||||||
|
myfree(message->encoding);
|
||||||
|
message->encoding = mystrdup(value);
|
||||||
|
}
|
||||||
} else if (rec_type == REC_TYPE_ERTO) {
|
} else if (rec_type == REC_TYPE_ERTO) {
|
||||||
if (message->errors_to == 0) {
|
if (message->errors_to == 0) {
|
||||||
message->errors_to = mystrdup(start);
|
message->errors_to = mystrdup(start);
|
||||||
|
@@ -86,6 +86,9 @@
|
|||||||
/* The output is a hashed file, named \fIfile_name\fB.db\fR.
|
/* The output is a hashed file, named \fIfile_name\fB.db\fR.
|
||||||
/* This is available only on systems with support for \fBdb\fR databases.
|
/* This is available only on systems with support for \fBdb\fR databases.
|
||||||
/* .PP
|
/* .PP
|
||||||
|
/* Use the command \fBpostconf -m\fR to find out what types of database
|
||||||
|
/* your Postfix installation can support.
|
||||||
|
/*
|
||||||
/* When no \fIfile_type\fR is specified, the software uses the database
|
/* When no \fIfile_type\fR is specified, the software uses the database
|
||||||
/* type specified via the \fBdatabase_type\fR configuration parameter.
|
/* type specified via the \fBdatabase_type\fR configuration parameter.
|
||||||
/* The default value for this parameter depends on the host environment.
|
/* The default value for this parameter depends on the host environment.
|
||||||
|
@@ -48,6 +48,48 @@
|
|||||||
/* .RE
|
/* .RE
|
||||||
/* .IP \fB-m\fR
|
/* .IP \fB-m\fR
|
||||||
/* List the names of all supported lookup table types.
|
/* List the names of all supported lookup table types.
|
||||||
|
/* .RS
|
||||||
|
/* .IP \fBbtree\fR
|
||||||
|
/* A sorted, balanced tree structure.
|
||||||
|
/* This is available only on systems with support for Berkeley DB
|
||||||
|
/* databases.
|
||||||
|
/* .IP \fBdbm\fR
|
||||||
|
/* An indexed file type based on hashing.
|
||||||
|
/* This is available only on systems with support for DBM databases.
|
||||||
|
/* .IP \fBenviron\fR
|
||||||
|
/* The UNIX process environment array. The lookup key is the variable
|
||||||
|
/* name. Originally implemented for testing, someone may find this
|
||||||
|
/* useful someday.
|
||||||
|
/* .IP \fBhash\fR
|
||||||
|
/* An indexed file type based on hashing.
|
||||||
|
/* This is available only on systems with support for Berkeley DB
|
||||||
|
/* databases.
|
||||||
|
/* .IP \fBldap\fR
|
||||||
|
/* Perform lookups using the LDAP protocol. This is described
|
||||||
|
/* in an LDAP_README file.
|
||||||
|
/* .IP \fBpcre\fR
|
||||||
|
/* A lookup table based on Perl Compatible Regular Expressions. The
|
||||||
|
/* file format is described in \fBpcre_table\fR(5).
|
||||||
|
/* .IP \fBregexp\fR
|
||||||
|
/* A lookup table based on regular expressions. The file format is
|
||||||
|
/* described in \fBregexp_table\fR(5).
|
||||||
|
/* .IP \fBstatic\fR
|
||||||
|
/* A table that always returns the same result. For example,
|
||||||
|
/* \fBstatic:foobar\fR always returns the string \fBfoobar\fR.
|
||||||
|
/* .IP \fBunix\fR
|
||||||
|
/* A limited way to query the UNIX authentication database. The
|
||||||
|
/* following tables are implemented:
|
||||||
|
/* .RS
|
||||||
|
/*. IP \fBunix:passwd.byname\fR
|
||||||
|
/* The table is the UNIX password database. The key is a login name.
|
||||||
|
/* The result is a password file entry in passwd(5) format.
|
||||||
|
/* .IP \fBunix:group.byname\fR
|
||||||
|
/* The table is the UNIX group database. The key is a group name.
|
||||||
|
/* The result is a group file entry in group(5) format.
|
||||||
|
/* .RE
|
||||||
|
/* .RE
|
||||||
|
/* .sp
|
||||||
|
/* Other table types may exist depending on how Postfix was built.
|
||||||
/* .IP \fB-n\fR
|
/* .IP \fB-n\fR
|
||||||
/* Print non-default parameter settings only.
|
/* Print non-default parameter settings only.
|
||||||
/* .IP \fB-v\fR
|
/* .IP \fB-v\fR
|
||||||
|
@@ -107,6 +107,9 @@
|
|||||||
/* The output file is a hashed file, named \fIfile_name\fB.db\fR.
|
/* The output file is a hashed file, named \fIfile_name\fB.db\fR.
|
||||||
/* This is available only on systems with support for \fBdb\fR databases.
|
/* This is available only on systems with support for \fBdb\fR databases.
|
||||||
/* .PP
|
/* .PP
|
||||||
|
/* Use the command \fBpostconf -m\fR to find out what types of database
|
||||||
|
/* your Postfix installation can support.
|
||||||
|
/*
|
||||||
/* When no \fIfile_type\fR is specified, the software uses the database
|
/* When no \fIfile_type\fR is specified, the software uses the database
|
||||||
/* type specified via the \fBdatabase_type\fR configuration parameter.
|
/* type specified via the \fBdatabase_type\fR configuration parameter.
|
||||||
/* .RE
|
/* .RE
|
||||||
|
@@ -305,9 +305,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
message->queue_id, error_text, start);
|
message->queue_id, error_text, start);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strcmp(name, MAIL_ATTR_ENCODING) == 0)
|
/* Allow extra segment to override envelope segment info. */
|
||||||
if (message->encoding == 0)
|
if (strcmp(name, MAIL_ATTR_ENCODING) == 0) {
|
||||||
message->encoding = mystrdup(value);
|
if (message->encoding != 0)
|
||||||
|
myfree(message->encoding);
|
||||||
|
message->encoding = mystrdup(value);
|
||||||
|
}
|
||||||
} else if (rec_type == REC_TYPE_ERTO) {
|
} else if (rec_type == REC_TYPE_ERTO) {
|
||||||
if (message->errors_to == 0)
|
if (message->errors_to == 0)
|
||||||
message->errors_to = mystrdup(start);
|
message->errors_to = mystrdup(start);
|
||||||
|
@@ -376,7 +376,7 @@ static void qmqpd_write_content(QMQPD_STATE *state)
|
|||||||
if (first) {
|
if (first) {
|
||||||
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
||||||
rec_fprintf(state->cleanup, rec_type,
|
rec_fprintf(state->cleanup, rec_type,
|
||||||
"Mailbox-Line: %*s", len, start);
|
"X-Mailbox-Line: %*s", len, start);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
|
@@ -152,6 +152,7 @@ smtp_proto.o: ../../include/vstring_vstream.h
|
|||||||
smtp_proto.o: ../../include/stringops.h
|
smtp_proto.o: ../../include/stringops.h
|
||||||
smtp_proto.o: ../../include/mymalloc.h
|
smtp_proto.o: ../../include/mymalloc.h
|
||||||
smtp_proto.o: ../../include/iostuff.h
|
smtp_proto.o: ../../include/iostuff.h
|
||||||
|
smtp_proto.o: ../../include/split_at.h
|
||||||
smtp_proto.o: ../../include/mail_params.h
|
smtp_proto.o: ../../include/mail_params.h
|
||||||
smtp_proto.o: ../../include/smtp_stream.h
|
smtp_proto.o: ../../include/smtp_stream.h
|
||||||
smtp_proto.o: ../../include/mail_queue.h
|
smtp_proto.o: ../../include/mail_queue.h
|
||||||
@@ -169,6 +170,8 @@ smtp_proto.o: ../../include/quote_821_local.h
|
|||||||
smtp_proto.o: ../../include/quote_flags.h
|
smtp_proto.o: ../../include/quote_flags.h
|
||||||
smtp_proto.o: ../../include/mail_proto.h
|
smtp_proto.o: ../../include/mail_proto.h
|
||||||
smtp_proto.o: ../../include/attr.h
|
smtp_proto.o: ../../include/attr.h
|
||||||
|
smtp_proto.o: ../../include/mime_state.h
|
||||||
|
smtp_proto.o: ../../include/header_opts.h
|
||||||
smtp_proto.o: smtp.h
|
smtp_proto.o: smtp.h
|
||||||
smtp_proto.o: ../../include/argv.h
|
smtp_proto.o: ../../include/argv.h
|
||||||
smtp_proto.o: smtp_sasl.h
|
smtp_proto.o: smtp_sasl.h
|
||||||
@@ -224,6 +227,8 @@ smtp_state.o: ../../include/vstring.h
|
|||||||
smtp_state.o: ../../include/vbuf.h
|
smtp_state.o: ../../include/vbuf.h
|
||||||
smtp_state.o: ../../include/vstream.h
|
smtp_state.o: ../../include/vstream.h
|
||||||
smtp_state.o: ../../include/mail_conf.h
|
smtp_state.o: ../../include/mail_conf.h
|
||||||
|
smtp_state.o: ../../include/mime_state.h
|
||||||
|
smtp_state.o: ../../include/header_opts.h
|
||||||
smtp_state.o: smtp.h
|
smtp_state.o: smtp.h
|
||||||
smtp_state.o: ../../include/argv.h
|
smtp_state.o: ../../include/argv.h
|
||||||
smtp_state.o: ../../include/deliver_request.h
|
smtp_state.o: ../../include/deliver_request.h
|
||||||
|
@@ -37,9 +37,12 @@
|
|||||||
/* run chrooted at fixed low privilege.
|
/* run chrooted at fixed low privilege.
|
||||||
/* STANDARDS
|
/* STANDARDS
|
||||||
/* RFC 821 (SMTP protocol)
|
/* RFC 821 (SMTP protocol)
|
||||||
|
/* RFC 822 (ARPA Internet Text Messages)
|
||||||
/* RFC 1651 (SMTP service extensions)
|
/* RFC 1651 (SMTP service extensions)
|
||||||
/* RFC 1652 (8bit-MIME transport)
|
/* RFC 1652 (8bit-MIME transport)
|
||||||
/* RFC 1870 (Message Size Declaration)
|
/* RFC 1870 (Message Size Declaration)
|
||||||
|
/* RFC 2045 (MIME: Format of Internet Message Bodies)
|
||||||
|
/* RFC 2046 (MIME: Media Types)
|
||||||
/* RFC 2197 (Pipelining)
|
/* RFC 2197 (Pipelining)
|
||||||
/* RFC 2554 (AUTH command)
|
/* RFC 2554 (AUTH command)
|
||||||
/* RFC 2821 (SMTP protocol)
|
/* RFC 2821 (SMTP protocol)
|
||||||
@@ -328,6 +331,7 @@ static int deliver_message(DELIVER_REQUEST *request)
|
|||||||
&& (state->error_mask & name_mask(VAR_NOTIFY_CLASSES,
|
&& (state->error_mask & name_mask(VAR_NOTIFY_CLASSES,
|
||||||
mail_error_masks, var_notify_classes)))
|
mail_error_masks, var_notify_classes)))
|
||||||
smtp_chat_notify(state);
|
smtp_chat_notify(state);
|
||||||
|
/* XXX smtp_xfer() may abort in the middle of DATA. */
|
||||||
smtp_session_free(state->session);
|
smtp_session_free(state->session);
|
||||||
debug_peer_restore();
|
debug_peer_restore();
|
||||||
}
|
}
|
||||||
|
@@ -53,6 +53,8 @@ typedef struct SMTP_STATE {
|
|||||||
sasl_callback_t *sasl_callbacks; /* stateful callbacks */
|
sasl_callback_t *sasl_callbacks; /* stateful callbacks */
|
||||||
#endif
|
#endif
|
||||||
off_t size_limit; /* server limit or unknown */
|
off_t size_limit; /* server limit or unknown */
|
||||||
|
int space_left; /* output length control */
|
||||||
|
struct MIME_STATE *mime_state; /* mime state machine */
|
||||||
} SMTP_STATE;
|
} SMTP_STATE;
|
||||||
|
|
||||||
#define SMTP_FEATURE_ESMTP (1<<0)
|
#define SMTP_FEATURE_ESMTP (1<<0)
|
||||||
|
@@ -149,6 +149,14 @@ void smtp_chat_cmd(SMTP_STATE *state, char *fmt,...)
|
|||||||
* Send the command to the SMTP server.
|
* Send the command to the SMTP server.
|
||||||
*/
|
*/
|
||||||
smtp_fputs(STR(state->buffer), LEN(state->buffer), session->stream);
|
smtp_fputs(STR(state->buffer), LEN(state->buffer), session->stream);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush unsent output if no I/O happened for a while. This avoids
|
||||||
|
* timeouts with pipelined SMTP sessions that have lots of delays
|
||||||
|
* (typically, DNS lookups for sender/recipient unaliasing).
|
||||||
|
*/
|
||||||
|
if (time((time_t *) 0) - vstream_ftime(session->stream) > 10)
|
||||||
|
vstream_fflush(session->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* smtp_chat_resp - read and process SMTP server response */
|
/* smtp_chat_resp - read and process SMTP server response */
|
||||||
|
@@ -83,6 +83,7 @@
|
|||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
#include <mymalloc.h>
|
#include <mymalloc.h>
|
||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
|
#include <split_at.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
@@ -101,6 +102,7 @@
|
|||||||
#include <mark_corrupt.h>
|
#include <mark_corrupt.h>
|
||||||
#include <quote_821_local.h>
|
#include <quote_821_local.h>
|
||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
|
#include <mime_state.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@@ -147,6 +149,15 @@ char *xfer_states[SMTP_STATE_LAST] = {
|
|||||||
"sending QUIT",
|
"sending QUIT",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *xfer_request[SMTP_STATE_LAST] = {
|
||||||
|
"MAIL FROM command",
|
||||||
|
"RCPT TO command",
|
||||||
|
"DATA command",
|
||||||
|
"end of DATA command",
|
||||||
|
"final RSET command",
|
||||||
|
"QUIT command",
|
||||||
|
};
|
||||||
|
|
||||||
/* smtp_helo - perform initial handshake with SMTP server */
|
/* smtp_helo - perform initial handshake with SMTP server */
|
||||||
|
|
||||||
int smtp_helo(SMTP_STATE *state)
|
int smtp_helo(SMTP_STATE *state)
|
||||||
@@ -273,6 +284,64 @@ int smtp_helo(SMTP_STATE *state)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* smtp_text_out - output one header/body record */
|
||||||
|
|
||||||
|
static void smtp_text_out(void *context, int rec_type,
|
||||||
|
const char *text, int len)
|
||||||
|
{
|
||||||
|
SMTP_STATE *state = (SMTP_STATE *) context;
|
||||||
|
SMTP_SESSION *session = state->session;
|
||||||
|
int data_left;
|
||||||
|
const char *data_start;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deal with an impedance mismatch between Postfix queue files (record
|
||||||
|
* length <= $message_line_length_limit) and SMTP (DATA record length <=
|
||||||
|
* $smtp_line_length_limit). The code below does a little too much work
|
||||||
|
* when the SMTP line length limit is disabled, but it avoids code
|
||||||
|
* duplication, and thus, it avoids testing and maintenance problems.
|
||||||
|
*/
|
||||||
|
data_left = len;
|
||||||
|
data_start = text;
|
||||||
|
do {
|
||||||
|
if (var_smtp_line_limit > 0 && data_left >= state->space_left) {
|
||||||
|
smtp_fputs(data_start, state->space_left, session->stream);
|
||||||
|
data_start += state->space_left;
|
||||||
|
data_left -= state->space_left;
|
||||||
|
state->space_left = var_smtp_line_limit;
|
||||||
|
if (data_left > 0 || rec_type == REC_TYPE_CONT) {
|
||||||
|
smtp_fputc(' ', session->stream);
|
||||||
|
state->space_left -= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rec_type == REC_TYPE_CONT) {
|
||||||
|
smtp_fwrite(data_start, data_left, session->stream);
|
||||||
|
state->space_left -= data_left;
|
||||||
|
} else {
|
||||||
|
smtp_fputs(data_start, data_left, session->stream);
|
||||||
|
state->space_left = var_smtp_line_limit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (data_left > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtp_header_out - output one message header */
|
||||||
|
|
||||||
|
static void smtp_header_out(void *context, int unused_header_class,
|
||||||
|
HEADER_OPTS *unused_info, VSTRING *buf)
|
||||||
|
{
|
||||||
|
char *start = vstring_str(buf);
|
||||||
|
char *line;
|
||||||
|
char *next_line;
|
||||||
|
|
||||||
|
for (line = start; line; line = next_line) {
|
||||||
|
next_line = split_at(line, '\n');
|
||||||
|
smtp_text_out(context, REC_TYPE_NORM, line, next_line ?
|
||||||
|
next_line - line - 1 : strlen(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* smtp_xfer - send a batch of envelope information and the message data */
|
/* smtp_xfer - send a batch of envelope information and the message data */
|
||||||
|
|
||||||
int smtp_xfer(SMTP_STATE *state)
|
int smtp_xfer(SMTP_STATE *state)
|
||||||
@@ -297,9 +366,8 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
int sndbuffree;
|
int sndbuffree;
|
||||||
SOCKOPT_SIZE optlen = sizeof(sndbufsize);
|
SOCKOPT_SIZE optlen = sizeof(sndbufsize);
|
||||||
int mail_from_rejected;
|
int mail_from_rejected;
|
||||||
int space_left = var_smtp_line_limit;
|
int downgrading;
|
||||||
int data_left;
|
int mime_errs;
|
||||||
char *data_start;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros for readability.
|
* Macros for readability.
|
||||||
@@ -362,6 +430,8 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
if (getsockopt(vstream_fileno(state->session->stream), SOL_SOCKET,
|
if (getsockopt(vstream_fileno(state->session->stream), SOL_SOCKET,
|
||||||
SO_SNDBUF, (char *) &sndbufsize, &optlen) < 0)
|
SO_SNDBUF, (char *) &sndbufsize, &optlen) < 0)
|
||||||
msg_fatal("%s: getsockopt: %m", myname);
|
msg_fatal("%s: getsockopt: %m", myname);
|
||||||
|
if (sndbufsize > VSTREAM_BUFSIZE)
|
||||||
|
sndbufsize = VSTREAM_BUFSIZE;
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("Using ESMTP PIPELINING, TCP send buffer size is %d",
|
msg_info("Using ESMTP PIPELINING, TCP send buffer size is %d",
|
||||||
sndbufsize);
|
sndbufsize);
|
||||||
@@ -416,10 +486,10 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
}
|
}
|
||||||
vstring_sprintf(next_command, "MAIL FROM:<%s>",
|
vstring_sprintf(next_command, "MAIL FROM:<%s>",
|
||||||
vstring_str(state->scratch));
|
vstring_str(state->scratch));
|
||||||
if (state->features & SMTP_FEATURE_SIZE) /* RFC 1652 */
|
if (state->features & SMTP_FEATURE_SIZE) /* RFC 1870 */
|
||||||
vstring_sprintf_append(next_command, " SIZE=%lu",
|
vstring_sprintf_append(next_command, " SIZE=%lu",
|
||||||
request->data_size);
|
request->data_size);
|
||||||
if (state->features & SMTP_FEATURE_8BITMIME) {
|
if (state->features & SMTP_FEATURE_8BITMIME) { /* RFC 1652 */
|
||||||
if (strcmp(request->encoding, MAIL_ATTR_ENC_8BIT) == 0)
|
if (strcmp(request->encoding, MAIL_ATTR_ENC_8BIT) == 0)
|
||||||
vstring_strcat(next_command, " BODY=8BITMIME");
|
vstring_strcat(next_command, " BODY=8BITMIME");
|
||||||
else if (strcmp(request->encoding, MAIL_ATTR_ENC_7BIT) == 0)
|
else if (strcmp(request->encoding, MAIL_ATTR_ENC_7BIT) == 0)
|
||||||
@@ -537,8 +607,10 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
case SMTP_STATE_MAIL:
|
case SMTP_STATE_MAIL:
|
||||||
if (resp->code / 100 != 2) {
|
if (resp->code / 100 != 2) {
|
||||||
smtp_mesg_fail(state, resp->code,
|
smtp_mesg_fail(state, resp->code,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[SMTP_STATE_MAIL]);
|
||||||
mail_from_rejected = 1;
|
mail_from_rejected = 1;
|
||||||
}
|
}
|
||||||
recv_state = SMTP_STATE_RCPT;
|
recv_state = SMTP_STATE_RCPT;
|
||||||
@@ -567,8 +639,10 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
} else {
|
} else {
|
||||||
rcpt = request->rcpt_list.info + recv_rcpt;
|
rcpt = request->rcpt_list.info + recv_rcpt;
|
||||||
smtp_rcpt_fail(state, resp->code, rcpt,
|
smtp_rcpt_fail(state, resp->code, rcpt,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[SMTP_STATE_RCPT]);
|
||||||
rcpt->offset = 0; /* in case deferred */
|
rcpt->offset = 0; /* in case deferred */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,8 +659,10 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
if (resp->code / 100 != 3) {
|
if (resp->code / 100 != 3) {
|
||||||
if (nrcpt > 0)
|
if (nrcpt > 0)
|
||||||
smtp_mesg_fail(state, resp->code,
|
smtp_mesg_fail(state, resp->code,
|
||||||
"host %s said: %s", session->namaddr,
|
"host %s said: %s (in reply to %s)",
|
||||||
translit(resp->str, "\n", " "));
|
session->namaddr,
|
||||||
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[SMTP_STATE_DATA]);
|
||||||
nrcpt = -1;
|
nrcpt = -1;
|
||||||
}
|
}
|
||||||
recv_state = SMTP_STATE_DOT;
|
recv_state = SMTP_STATE_DOT;
|
||||||
@@ -605,9 +681,10 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
if (nrcpt > 0) {
|
if (nrcpt > 0) {
|
||||||
if (resp->code / 100 != 2) {
|
if (resp->code / 100 != 2) {
|
||||||
smtp_mesg_fail(state, resp->code,
|
smtp_mesg_fail(state, resp->code,
|
||||||
"host %s said: %s",
|
"host %s said: %s (in reply to %s)",
|
||||||
session->namaddr,
|
session->namaddr,
|
||||||
translit(resp->str, "\n", " "));
|
translit(resp->str, "\n", " "),
|
||||||
|
xfer_request[SMTP_STATE_DOT]);
|
||||||
} else {
|
} else {
|
||||||
for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) {
|
for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) {
|
||||||
rcpt = request->rcpt_list.info + nrcpt;
|
rcpt = request->rcpt_list.info + nrcpt;
|
||||||
@@ -678,8 +755,24 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
* Special case if the server accepted the DATA command. If the
|
* Special case if the server accepted the DATA command. If the
|
||||||
* server accepted at least one recipient send the entire message.
|
* server accepted at least one recipient send the entire message.
|
||||||
* Otherwise, just send "." as per RFC 2197.
|
* Otherwise, just send "." as per RFC 2197.
|
||||||
|
*
|
||||||
|
* XXX If there is a hard MIME error while downgrading to 7-bit mail,
|
||||||
|
* disconnect ungracefully, because there is no other way to cancel a
|
||||||
|
* transaction in progress.
|
||||||
*/
|
*/
|
||||||
if (send_state == SMTP_STATE_DOT && nrcpt > 0) {
|
if (send_state == SMTP_STATE_DOT && nrcpt > 0) {
|
||||||
|
downgrading = ((state->features & SMTP_FEATURE_8BITMIME) == 0
|
||||||
|
&& strcmp(request->encoding, MAIL_ATTR_ENC_7BIT) != 0);
|
||||||
|
if (downgrading)
|
||||||
|
state->mime_state = mime_state_alloc(MIME_OPT_DOWNGRADE
|
||||||
|
| MIME_OPT_REPORT_8BIT_IN_7BIT_BODY
|
||||||
|
| MIME_OPT_REPORT_8BIT_IN_HEADER,
|
||||||
|
smtp_header_out,
|
||||||
|
(MIME_STATE_ANY_END) 0,
|
||||||
|
smtp_text_out,
|
||||||
|
(MIME_STATE_ANY_END) 0,
|
||||||
|
(void *) state);
|
||||||
|
state->space_left = var_smtp_line_limit;
|
||||||
smtp_timeout_setup(state->session->stream,
|
smtp_timeout_setup(state->session->stream,
|
||||||
var_smtp_data1_tmout);
|
var_smtp_data1_tmout);
|
||||||
if ((except = vstream_setjmp(state->session->stream)) != 0)
|
if ((except = vstream_setjmp(state->session->stream)) != 0)
|
||||||
@@ -695,38 +788,21 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
if (prev_type != REC_TYPE_CONT)
|
if (prev_type != REC_TYPE_CONT)
|
||||||
if (vstring_str(state->scratch)[0] == '.')
|
if (vstring_str(state->scratch)[0] == '.')
|
||||||
smtp_fputc('.', session->stream);
|
smtp_fputc('.', session->stream);
|
||||||
|
if (downgrading == 0) {
|
||||||
/*
|
smtp_text_out((void *) state, rec_type,
|
||||||
* Deal with an impedance mismatch between Postfix queue
|
vstring_str(state->scratch),
|
||||||
* files (record length <= $message_line_length_limit) and
|
VSTRING_LEN(state->scratch));
|
||||||
* SMTP (DATA record length <= $smtp_line_length_limit). The
|
} else {
|
||||||
* code below does a little too much work when the SMTP line
|
mime_errs =
|
||||||
* length limit is disabled, but it avoids code duplication,
|
mime_state_update(state->mime_state, rec_type,
|
||||||
* and thus, it avoids testing and maintenance problems.
|
vstring_str(state->scratch),
|
||||||
*/
|
VSTRING_LEN(state->scratch));
|
||||||
data_left = VSTRING_LEN(state->scratch);
|
if (mime_errs) {
|
||||||
data_start = vstring_str(state->scratch);
|
smtp_mesg_fail(state, 554, "MIME 7-bit conversion failed: %s",
|
||||||
do {
|
mime_state_error(mime_errs));
|
||||||
if (var_smtp_line_limit > 0 && data_left >= space_left) {
|
RETURN(0);
|
||||||
smtp_fputs(data_start, space_left, session->stream);
|
|
||||||
data_start += space_left;
|
|
||||||
data_left -= space_left;
|
|
||||||
space_left = var_smtp_line_limit;
|
|
||||||
if (data_left > 0 || rec_type == REC_TYPE_CONT) {
|
|
||||||
smtp_fputc(' ', session->stream);
|
|
||||||
space_left -= 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (rec_type == REC_TYPE_CONT) {
|
|
||||||
smtp_fwrite(data_start, data_left, session->stream);
|
|
||||||
space_left -= data_left;
|
|
||||||
} else {
|
|
||||||
smtp_fputs(data_start, data_left, session->stream);
|
|
||||||
space_left = var_smtp_line_limit;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (data_left > 0);
|
}
|
||||||
prev_type = rec_type;
|
prev_type = rec_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
#include <mail_conf.h>
|
#include <mail_conf.h>
|
||||||
|
#include <mime_state.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@@ -69,6 +70,8 @@ SMTP_STATE *smtp_state_alloc(void)
|
|||||||
smtp_sasl_connect(state);
|
smtp_sasl_connect(state);
|
||||||
#endif
|
#endif
|
||||||
state->size_limit = 0;
|
state->size_limit = 0;
|
||||||
|
state->space_left = 0;
|
||||||
|
state->mime_state = 0;
|
||||||
return (state);
|
return (state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,5 +85,7 @@ void smtp_state_free(SMTP_STATE *state)
|
|||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
smtp_sasl_cleanup(state);
|
smtp_sasl_cleanup(state);
|
||||||
#endif
|
#endif
|
||||||
|
if (state->mime_state)
|
||||||
|
mime_state_free(state->mime_state);
|
||||||
myfree((char *) state);
|
myfree((char *) state);
|
||||||
}
|
}
|
||||||
|
@@ -617,6 +617,8 @@ static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg,
|
|||||||
/*
|
/*
|
||||||
* Report trouble. Log a warning only if we are going to sleep+reject so
|
* Report trouble. Log a warning only if we are going to sleep+reject so
|
||||||
* that attackers can't flood our logfiles.
|
* that attackers can't flood our logfiles.
|
||||||
|
*
|
||||||
|
* XXX !allow_empty_addr should also reject <"">.
|
||||||
*/
|
*/
|
||||||
if ((naddr < 1 && !allow_empty_addr)
|
if ((naddr < 1 && !allow_empty_addr)
|
||||||
|| naddr > 1
|
|| naddr > 1
|
||||||
@@ -776,15 +778,17 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
if (encoding != 0)
|
if (encoding != 0)
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||||
MAIL_ATTR_ENCODING, encoding);
|
MAIL_ATTR_ENCODING, encoding);
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
if (SMTPD_STAND_ALONE(state) == 0) {
|
||||||
MAIL_ATTR_CLIENT_NAME, state->name);
|
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
|
||||||
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
|
||||||
MAIL_ATTR_ORIGIN, state->namaddr);
|
|
||||||
if (state->helo_name != 0)
|
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||||
MAIL_ATTR_HELO_NAME, state->helo_name);
|
MAIL_ATTR_CLIENT_NAME, state->name);
|
||||||
|
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||||
|
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
||||||
|
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||||
|
MAIL_ATTR_ORIGIN, state->namaddr);
|
||||||
|
if (state->helo_name != 0)
|
||||||
|
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||||
|
MAIL_ATTR_HELO_NAME, state->helo_name);
|
||||||
|
}
|
||||||
if (verp_delims)
|
if (verp_delims)
|
||||||
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
||||||
state->sender = mystrdup(argv[2].strval);
|
state->sender = mystrdup(argv[2].strval);
|
||||||
@@ -956,7 +960,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
state->protocol, state->queue_id);
|
state->protocol, state->queue_id);
|
||||||
quote_822_local(state->buffer, state->recipient);
|
quote_822_local(state->buffer, state->recipient);
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||||
"\tfor <%s>; %s", STR(state->buffer), mail_date(state->time));
|
"\tfor <%s>; %s", STR(state->buffer), mail_date(state->time));
|
||||||
} else {
|
} else {
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||||
"\tby %s (%s) with %s",
|
"\tby %s (%s) with %s",
|
||||||
@@ -996,7 +1000,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
if (first) {
|
if (first) {
|
||||||
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
||||||
rec_fprintf(state->cleanup, curr_rec_type,
|
rec_fprintf(state->cleanup, curr_rec_type,
|
||||||
"Mailbox-Line: %s", start);
|
"X-Mailbox-Line: %s", start);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
|
@@ -49,7 +49,7 @@
|
|||||||
/* argument. The result is null-terminated. This routine uses mymalloc().
|
/* argument. The result is null-terminated. This routine uses mymalloc().
|
||||||
/*
|
/*
|
||||||
/* mymemdup() makes a copy of the memory pointed to by \fIptr\fR
|
/* mymemdup() makes a copy of the memory pointed to by \fIptr\fR
|
||||||
/* with length \fIlen\fR. The result is null-terminated.
|
/* with length \fIlen\fR. The result is NOT null-terminated.
|
||||||
/* This routine uses mymalloc().
|
/* This routine uses mymalloc().
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* msg(3) diagnostics interface
|
/* msg(3) diagnostics interface
|
||||||
|
Reference in New Issue
Block a user