2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-28 20:57:56 +00:00

snapshot-20000918

This commit is contained in:
Wietse Venema 2000-09-18 00:00:00 +00:00
parent 77741d9964
commit 5a94b2d36d
28 changed files with 333 additions and 345 deletions

View File

@ -1,7 +1,6 @@
This is a very first implementation of Postfix content filtering.
A Postfix content filter re-injects filtered mail back into Postfix.
If all you want is content _inspection_, see the INSPECT_README
file instead.
A Postfix content filter receives unfiltered mail from Postfix and
re-injects filtered mail back into Postfix.
It involves an incompatible change to queue file formats. Older
Postfix versions will reject mail that needs to be content filtered,

View File

@ -4055,12 +4055,6 @@ Apologies for any names omitted.
lying around after unsuccessful delivery (problem reported
by Brian Laughton @ Corp.Axxent.Ca).
20000619
Workaround: if append_dot_mydomain=no, turn on parent domain
search in the Postfix SMTP client, so that mail does not
bounce. Files: smtp/smtp.c, smtp/smtp_unalias.c.
20000621
AIX 4.x had POSIX regular expression support all the time
@ -4127,7 +4121,7 @@ Apologies for any names omitted.
not exist, defer mail instead of bouncing it (which would
lose the mail if the bounce would have to be delivered to
that same non-existent relayhost). Problem reported by
Chris Cooper @ maths.ox.ac.uk.
Chris Cooper @ maths.ox.ac.uk. File: smtp/smtp_connect.c.
20000821
@ -4136,6 +4130,7 @@ Apologies for any names omitted.
Cleanup: smtpd now replies with 555 when the client sends
unrecognized RCPT TO parameters, as required by RFC 1869
(problem report by Robert Norris @ its.monash.edu.au).
File: smtpd/smtpd.c.
20000822
@ -4156,3 +4151,58 @@ Apologies for any names omitted.
access controls, for example, hold off mail from an unknown
client or sender until we have completed some investigation,
after which we will either reject or accept.
20000905
Robustness: the dns client now rejects malformed domain
names rather than depending on the DNS to report that the
name does not exist. Linux returns a rather misleading
server failure code as found out by Patrik Rak. File:
dns/dns_lookup.c.
20000911
Feature: added IGNORE keyword to header_checks and body_checks
to pretend that certain data does not exist. File:
cleanup/cleanup_message.c.
20000911
Bugfix: the SASL code did not allow MAIL FROM... AUTH=sender
without prior authentication. The RFC allows this, although
one wonders what the reasoning behind this is. File:
smtpd/smtpd_sasl_proto.c.
20000913
Bugfix: the rmail script did not handle remote UUCP systems
that send a from_ line with unqualified envelope sender.
Reported by Luciano Mannucci.
Compatibility: don't insert Sender: header lines. Sendmail
has not done so for at least 10 years, if it ever did.
Problem reported by Brad Knowles. File: cleanup/cleanup_message.c.
20000916
Bugfix: when propagating an address extension in a virtual
or canonical mapping, cleanup accesses memory that is no
longer allocated. This can happen when the result address
length is more than 100 characters. Problem reported by
Adi Prasaja @ satunet.com. File: global/mail_addr_crunch.c.
Bugfix: fixed a misleading error message when the cleanup
server reaches the queue file size limit. Fix by Robby
Griffin @ MIT.EDU. File: cleanup/cleanup_extracted.c.
20000917
Bugfix: postalias -i would complain about duplicate entries
for the Sendmail-compatible @ entry and for the NIS-compatible
YP_LAST_MODIFIED and YP_MASTER_NAME entries.
20000918
Gross hack: prevent looping a bad recipient by always
forwarding recipients in :include: files, even when
owner-listname is not set. File: local/recipient.c.

View File

@ -1,181 +0,0 @@
This is a very first implementation of Postfix content inspection.
A Postfix content inspector causes "bad" mail to be bounced. All
other mail is delivered normally. If you want content _inspection_,
which allows you to modify mail content or destination, see the
FILTER_README file instead.
Content inspection involves an incompatible change to queue file
formats. Older Postfix versions will reject mail that needs to be
content inspected, and will move the queue file to the "corrupt"
mail queue subdirectory.
This document describes two approaches to content inspection.
Simple content inspection example
=================================
The example is relatively simple to set up, but is resource intensive
because it runs a shell script for each message.
With the shell script as shown you can lose a factor in Postfix
performance for each temporary file that is created and deleted in
the process of content inspection. The performance impact is less
for mail that is submitted or delivered locally, because such
deliveries are not as fast as SMTP transit mail.
The example assumes that only mail received via SMTP needs to be
content inspected.
..................................
. Postfix .
------smtpd \ /local-----
. -cleanup->queue- .
-----pickup / \smtp------
. | .
. \pipe------>inspector
..................................
Create a dedicated local user account called "inspect". The user
will never log in, and can be given a "*" password and non-existent
shell and home.
Create a directory /var/spool/inspect that is accessible only to
the "inspect" user. This is where the content inspection software
will store any temporary files.
Define a content inspection entry in the Postfix master file:
/etc/postfix/master.cf:
inspect unix - n n - - pipe
user=inspect argv=/some/where/inspect ${sender} ${recipient}
The filter program can start out as a simple shell script like this:
#!/bin/sh
# Localize this
INSPECT_DIR=/var/spool/inspect
# Exit codes from <sysexits.h>
EX_TEMPFAIL=75
EX_UNAVAILABLE=69
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
# Clean up when done or when aborting.
trap "rm -f in.$$; exit" 0 1 2 3 15
cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
# inspect <in.$$ || { echo Message content rejected; exit $EX_UNAVAILABLE; }
exit 0
The idea is to first capture the message to file and then run the
content through run a third-party content inspection program. If
the mail cannot be captured to file, mail delivery is deferred by
terminating with exit status 75 (EX_TEMPFAIL). If the content
inspection program finds a problem, the mail is bounced by terminating
the shell script with exit status 69 (EX_UNAVAILABLE). An exit
status of zero means everything is hunky-dory and the mail can
be delivered to its recipients.
If mail is rejected, another possible action is to mail a copy to
the local postmaster. If you do that, be sure not to enable content
inspection for locally-posted mail or else rejected mail will loop.
The problem with content inspection sotware like this is that it is
not very robust, because the software does not talk a well-defined
protocol with Postfix. If the shell scripts aborts because the
shell runs into some memory allocation problem, the script will
not produce a nice exit status as per /usr/include/sysexits.h and
mail will probably bounce. The same lack of robustness is possible
when the content inspection software itself runs into a resource
problem.
I suggest that you play with this script for a while until you are
satisfied with the results. Run it as root or as the filter user,
with a real message (headers+body) as input:
# /some/where/inspect sender recipient... <message-file
Turn on content inspection for mail arriving via SMTP only, by
appending "-o content_inspector=inspect:dummy" to the master.cf
entry that defines the Postfix SMTP server:
/etc/postfix/master.cf:
smtp inet ...stuff... smtpd
-o content_inspector=inspect:dummy
The content_inspector configuration parameter accepts the same
syntax as the right-hand side in a Postfix transport table.
Advanced content inspection example
===================================
The second example is more complex, but can give better performance,
and is less likely to bounce mail when the machine runs into a
resource problem. This approach uses content inspection software
that can receive mail via SMTP, and that can run as a resident
server. You can expect to lose about a factor in Postfix performance
for every temporary file created.
We will set up a content inspection program listening on localhost
port 10025 that receives mail via the SMTP protocol.
..................................
. Postfix .
------smtpd \ /local-----
. -cleanup->queue- .
-----pickup / | \smtp------
. v .
. smtp .
. | .
......................|...........
|
v
.................
. 10025 .
. inspection .
. .
.................
To enable content inspection in this manner, specify in main.cf a
new parameter:
/etc/postfix/main.cf:
content_filter = smtp:localhost:10025
This causes Postfix to add one extra content inspection record to
each incoming mail message, with content smtp:localhost:10025.
You can use the same syntax as in the right-hand side of a Postfix
transport table. The content inspection records are added by the
smtpd and pickup servers.
When a queue file has content inspection information, the queue
manager will deliver the mail to the specified content inspector
before attempting final delivery.
The content filter can be set up with the Postfix spawn service,
which is the Postfix equivalent of inetd. For example, to instantiate
up to 10 content inspection processes on demand:
/etc/postfix/master.cf:
localhost:10025 inet n n n - 10 spawn
user=inspect argv=/some/where/inspect
"inspect" is a dedicated local user account. The user will never
log in, and can be given a "*" password and non-existent shell and
home.
The spawn server is part of Postfix but is not installed by default.
Edit the top-level Makefile.in file, run "make makefiles", "make",
and "make install". The manual page isn't installed by default,
either. See the spawn.c source file.
The /some/where/inspect command is most likely a PERL script. PERL
has modules that make talking SMTP easy.
For now, it is left up to the Postfix users to come up with a
PERL/SMTP framework for Postfix content inspection. If done well,
it can be used with other mailers too, which is a nice spin-off.

View File

@ -3,6 +3,11 @@
# Dummy UUCP rmail command for postfix/qmail systems
SENDMAIL="/usr/sbin/sendmail"
IFS=" " read junk from junk
IFS=" " read junk from junk junk junk junk junk junk junk relay
case "$from" in
*[@!]*) ;;
*) from="$from@$relay";;
esac
exec $SENDMAIL -f "$from" -- "$@"

View File

@ -183,10 +183,13 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf,
*/
if (vstream_fflush(state->dst)) {
msg_warn("%s: write queue file: %m", state->queue_id);
if (errno == EFBIG)
if (errno == EFBIG) {
msg_warn("%s: queue file size limit exceeded", state->queue_id);
state->errs |= CLEANUP_STAT_SIZE;
else
} else {
msg_warn("%s: write queue file: %m", state->queue_id);
state->errs |= CLEANUP_STAT_WRITE;
}
return;
}

View File

@ -267,6 +267,8 @@ static void cleanup_header(CLEANUP_STATE *state)
state->queue_id, header, state->sender,
state->recip ? state->recip : "unknown");
state->errs |= CLEANUP_STAT_CONT;
} else if (strcasecmp(value, "IGNORE") == 0) {
return;
}
}
}
@ -346,12 +348,8 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
}
/*
* Add a missing (Resent-)From: header. If a (Resent-)From: header is
* present, see if we need a (Resent-)Sender: header.
* Add a missing (Resent-)From: header.
*/
#define NOT_SPECIAL_SENDER(addr) (*(addr) != 0 \
&& strcasecmp(addr, mail_addr_double_bounce()) != 0)
if ((state->headers_seen & (1 << (state->resent[0] ?
HDR_RESENT_FROM : HDR_FROM))) == 0) {
quote_822_local(state->temp1, *state->sender ?
@ -366,15 +364,6 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
tok822_free_tree(token);
}
CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2);
} else if ((state->headers_seen & (1 << (state->resent[0] ?
HDR_RESENT_SENDER : HDR_SENDER))) == 0
&& NOT_SPECIAL_SENDER(state->sender)) {
from = (state->resent[0] ? state->resent_from : state->from);
if (from == 0 || strcasecmp(state->sender, from) != 0) {
quote_822_local(state->temp1, state->sender);
cleanup_out_format(state, REC_TYPE_NORM, "%sSender: %s",
state->resent, vstring_str(state->temp1));
}
}
/*
@ -508,6 +497,8 @@ static void cleanup_message_body(CLEANUP_STATE *state, int type, char *buf, int
state->queue_id, buf, state->sender,
state->recip ? state->recip : "unknown");
state->errs |= CLEANUP_STAT_CONT;
} else if (strcasecmp(value, "IGNORE") == 0) {
return;
}
}
}

View File

@ -109,6 +109,7 @@
#include <msg.h>
#include <valid_hostname.h>
#include <stringops.h>
#include <valid_hostname.h>
/* DNS library. */
@ -430,6 +431,16 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
int count;
int status;
/*
* The Linux resolver misbehaves when given an invalid domain name.
*/
if (!valid_hostname(name)) {
if (why)
vstring_sprintf(why, "Name service error for %s: invalid name",
name);
return (DNS_NOTFOUND);
}
/*
* Perform the lookup. Follow CNAME chains, but only up to a
* pre-determined maximum.

View File

@ -8,11 +8,9 @@ POSTFIX_DIR=${POSTFIX_DIR-/var/spool/postfix}
cd ${POSTFIX_DIR}
mkdir etc
cp /etc/localtime /etc/services /etc/resolv.conf etc
cp /etc/localtime /etc/services /etc/resolv.conf /etc/nsswitch.conf etc
mkdir -p usr/lib/zoneinfo
ln -s /etc/localtime usr/lib/zoneinfo
if [ -e /lib/libnss_dns.so.1 ]; then
mkdir lib
cp /lib/libnss_dns.so.1 lib
fi
cp /lib/libnss_* lib

View File

@ -84,10 +84,10 @@ ARGV *mail_addr_crunch(const char *string, const char *extension)
tok822_externalize(extern_addr, tpp[0]->head, TOK822_STR_DEFL);
canon_addr_external(canon_addr, STR(extern_addr));
if (extension) {
VSTRING_SPACE(canon_addr, extlen + 1);
if ((ratsign = strrchr(STR(canon_addr), '@')) == 0) {
vstring_strcat(canon_addr, extension);
} else {
VSTRING_SPACE(canon_addr, extlen + 1);
memmove(ratsign + extlen, ratsign, strlen(ratsign) + 1);
memcpy(ratsign, extension, extlen);
VSTRING_SKIP(canon_addr);

View File

@ -42,8 +42,9 @@
/* data to stable storage, and truncate the destination
/* file to its original length in case of problems.
/* .IP MAIL_COPY_FROM
/* Prepend a UNIX-style From_ line to the message, and append
/* an empty line to the end of the message.
/* Prepend a UNIX-style From_ line to the message.
/* .IP MAIL_COPY_BLANK
/* Append an empty line to the end of the message.
/* .IP MAIL_COPY_DELIVERED
/* Prepend a Delivered-To: header with the name of the
/* \fIdelivered\fR attribute.

View File

@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20000823"
#define DEF_MAIL_VERSION "Snapshot-20000918"
extern char *var_mail_version;
/* LICENSE

View File

@ -41,9 +41,7 @@ PIPE(8) PIPE(8)
<b>F</b> Prepend a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope
header to the message content. This is
expected by, for example, <b>UUCP</b> software. The
<b>F</b> flag also causes an empty line to be
appended to the message.
expected by, for example, <b>UUCP</b> software.
<b>R</b> Prepend a <b>Return-Path:</b> message header with
the envelope sender address.
@ -59,6 +57,8 @@ PIPE(8) PIPE(8)
<b>user</b>=<i>username</i>:<i>groupname</i>
The external command is executed with the rights of
the specified <i>username</i>. The software refuses to
execute commands with root privileges, or with the
@ -71,8 +71,6 @@ PIPE(8) PIPE(8)
PIPE(8) PIPE(8)
the specified <i>username</i>. The software refuses to
execute commands with root privileges, or with the
privileges of the mail system owner. If <i>groupname</i>
is specified, the corresponding group ID is used
instead of the group ID of <i>username</i>.
@ -125,6 +123,8 @@ PIPE(8) PIPE(8)
tains <b>${recipient</b>} expands into as many com-
mand-line arguments as there are recipients.
<b>${sender</b>}
This macro expands to the envelope sender
@ -137,8 +137,6 @@ PIPE(8) PIPE(8)
PIPE(8) PIPE(8)
<b>${sender</b>}
This macro expands to the envelope sender
address.
<b>${size</b>}
@ -190,7 +188,9 @@ PIPE(8) PIPE(8)
<i>transport_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
destination, for delivery via the named <i>transport</i>.
The default limit is taken from the
The default limit is taken from the <b>default</b><i>_</i><b>desti-</b>
<b>nation</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter. The limit is
enforced by the Postfix queue manager.
@ -203,9 +203,6 @@ PIPE(8) PIPE(8)
PIPE(8) PIPE(8)
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
The limit is enforced by the Postfix queue manager.
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
Limit the number of recipients per message deliv-
ery, for delivery via the named <i>transport</i>. The
@ -256,6 +253,9 @@ PIPE(8) PIPE(8)

View File

@ -75,9 +75,6 @@ SMTP(8) SMTP(8)
command after a configuration change.
<b>Miscellaneous</b>
<b>append</b><i>_</i><b>dot</b><i>_</i><b>mydomain</b>
Rewrite <i>user</i>@<i>host</i> to <i>user</i>@<i>host</i>.$<b>mydomain</b>.
<b>best</b><i>_</i><b>mx</b><i>_</i><b>transport</b>
Name of the delivery transport to use when the
local machine is the most-preferred mail exchanger
@ -126,6 +123,9 @@ SMTP(8) SMTP(8)
<b>smtp</b><i>_</i><b>always</b><i>_</i><b>send</b><i>_</i><b>ehlo</b>
Always send EHLO at the start of a connection.
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
Skip servers that greet us with a 4xx status code.
2
@ -137,9 +137,6 @@ SMTP(8) SMTP(8)
SMTP(8) SMTP(8)
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
Skip servers that greet us with a 4xx status code.
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>5xx</b><i>_</i><b>greeting</b>
Skip servers that greet us with a 5xx status code.
@ -191,6 +188,9 @@ SMTP(8) SMTP(8)
ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Timeout</b> <b>controls</b>
<b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
Timeout in seconds for completing a TCP connection.
@ -203,9 +203,6 @@ SMTP(8) SMTP(8)
SMTP(8) SMTP(8)
<b>Timeout</b> <b>controls</b>
<b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
Timeout in seconds for completing a TCP connection.
When no connection can be made within the deadline,
the SMTP client tries the next address on the mail
exchanger list.
@ -257,6 +254,9 @@ SMTP(8) SMTP(8)
The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
Wietse Venema
IBM T.J. Watson Research
@ -269,9 +269,6 @@ SMTP(8) SMTP(8)
SMTP(8) SMTP(8)
<b>AUTHOR(S)</b>
Wietse Venema
IBM T.J. Watson Research
P.O. Box 704
Yorktown Heights, NY 10598, USA
@ -322,6 +319,9 @@ SMTP(8) SMTP(8)

View File

@ -84,47 +84,47 @@ TRANSPORT(5) TRANSPORT(5)
names.
<b>EXAMPLES</b>
In order to send mail for <b>foo.org</b> and its subdomains
via the <b>uucp</b> transport to the UUCP host named <b>foo</b>:
In order to send mail for <b>foo.org</b> and its subdomains via
the <b>uucp</b> transport to the UUCP host named <b>foo</b>:
<b>foo.org</b> <b>uucp:foo</b>
<b>.foo.org</b> <b>uucp:foo</b>
When no <i>nexthop</i> host name is specified, the destination domain
name is used instead. For example, the following directs mail for
<i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a mail
exchanger for <b>foo.org</b>. The <b>slow</b> transport could be
something that runs at most one delivery process at a time:
When no <i>nexthop</i> host name is specified, the destination
domain name is used instead. For example, the following
directs mail for <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a
mail exchanger for <b>foo.org</b>. The <b>slow</b> transport could be
something that runs at most one delivery process at a
time:
<b>foo.org</b> <b>slow:</b>
When no <i>transport</i> is specified, the default transport is
used, as specified via the <b>default</b><i>_</i><b>transport</b> configuration
parameter. The following sends all mail for <b>foo.org</b> and its
subdomains to host <b>gateway.foo.org</b>:
parameter. The following sends all mail for <b>foo.org</b> and
its subdomains to host <b>gateway.foo.org</b>:
<b>foo.org</b> <b>:[gateway.foo.org]</b>
<b>.foo.org</b> <b>:[gateway.foo.org]</b>
In the above example, the [] are used to suppress MX lookups.
The result would likely point to your local machine.
In the above example, the [] are used to suppress MX
lookups. The result would likely point to your local
machine.
In the case of delivery via SMTP, one may specify
<i>hostname</i>:<i>service</i> instead of just a host:
In the case of delivery via SMTP, one may specify <i>host-</i>
<i>name</i>:<i>service</i> instead of just a host:
<b>foo.org</b> <b>smtp:bar.org:2025</b>
This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b>
port <b>2025</b>. Instead of a numerical port a symbolic name may be
used. Specify [] around the destination in order to disable MX lookups.
This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b> port
<b>2025</b>. Instead of a numerical port a symbolic name may be
used. Specify [] around the destination in order to dis-
able MX lookups.
The error mailer can be used to bounce mail:
<b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliverable</b>
This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b>
to be bounced.
<b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliv-</b>
<b>erable</b>
@ -137,6 +137,9 @@ TRANSPORT(5) TRANSPORT(5)
TRANSPORT(5) TRANSPORT(5)
This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b> to be
bounced.
<b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>
This section describes how the table lookups change when
the table is given in the form of regular expressions. For
@ -188,13 +191,76 @@ TRANSPORT(5) TRANSPORT(5)
Wietse Venema
IBM T.J. Watson Research
P.O. Box 704
Yorktown Heights, NY 10598, USA
3
TRANSPORT(5) TRANSPORT(5)
Yorktown Heights, NY 10598, USA
4
</pre> </body> </html>

View File

@ -43,6 +43,7 @@ VIRTUAL(5) VIRTUAL(5)
lowing:
<i>virtual.domain</i> <i>anything</i> (right-hand content does not matter)
<i>postmaster@virtual.domain</i> <i>postmaster</i>
<i>user1@virtual.domain</i> <i>address1</i>
<i>user2@virtual.domain</i> <i>address2,</i> <i>address3</i>
@ -57,8 +58,7 @@ VIRTUAL(5) VIRTUAL(5)
Blank lines are ignored, as are lines beginning
with `#'.
<i>pattern</i> <i>result</i>
When <i>pattern</i> matches a mail address, replace it by
@ -71,6 +71,8 @@ VIRTUAL(5) VIRTUAL(5)
VIRTUAL(5) VIRTUAL(5)
<i>pattern</i> <i>result</i>
When <i>pattern</i> matches a mail address, replace it by
the corresponding <i>result</i>.
With lookups from indexed files such as DB or DBM, or from
@ -124,8 +126,6 @@ VIRTUAL(5) VIRTUAL(5)
table, until a pattern is found that matches the search
string.
Results are the same as with normal indexed file lookups,
2
@ -137,6 +137,7 @@ VIRTUAL(5) VIRTUAL(5)
VIRTUAL(5) VIRTUAL(5)
Results are the same as with normal indexed file lookups,
with the additional feature that parenthesized substrings
from the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
@ -193,7 +194,6 @@ VIRTUAL(5) VIRTUAL(5)
3

View File

@ -158,6 +158,12 @@ static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
&& strcasecmp(state.msg_attr.owner, state.msg_attr.user) != 0)
return (deliver_indirect(state));
/*
* Always forward recipients in :include: files.
*/
if (state.msg_attr.exp_type = EXPAND_TYPE_INCL)
return (deliver_indirect(state));
/*
* Delivery to local user. First try expansion of the recipient's
* $HOME/.forward file, then mailbox delivery.

View File

@ -70,6 +70,7 @@ can also be used with IP addresses instead of hostnames.
.na
.nf
.ad
.fi
In order to send mail for \fBfoo.org\fR and its subdomains
via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR:

View File

@ -43,6 +43,7 @@ Typical support for a virtual domain looks like the following:
.in +4
.nf
\fIvirtual.domain anything\fR (right-hand content does not matter)
\fIpostmaster@virtual.domain postmaster\fR
\fIuser1@virtual.domain address1\fR
\fIuser2@virtual.domain address2, address3\fR
.fi

View File

@ -41,8 +41,7 @@ when preceded by a blank line.
.IP \fBF\fR
Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
the message content.
This is expected by, for example, \fBUUCP\fR software. The \fBF\fR
flag also causes an empty line to be appended to the message.
This is expected by, for example, \fBUUCP\fR software.
.IP \fBR\fR
Prepend a \fBReturn-Path:\fR message header with the envelope sender
address.

View File

@ -72,8 +72,6 @@ a configuration change.
.SH Miscellaneous
.ad
.fi
.IP \fBappend_dot_mydomain\fR
Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
.IP \fBbest_mx_transport\fR
Name of the delivery transport to use when the local machine
is the most-preferred mail exchanger (by default, a mailer

View File

@ -33,8 +33,7 @@
/* .IP \fBF\fR
/* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
/* the message content.
/* This is expected by, for example, \fBUUCP\fR software. The \fBF\fR
/* flag also causes an empty line to be appended to the message.
/* This is expected by, for example, \fBUUCP\fR software.
/* .IP \fBR\fR
/* Prepend a \fBReturn-Path:\fR message header with the envelope sender
/* address.

View File

@ -263,6 +263,12 @@ static void postalias(char *map_type, char *path_name,
mkmap_append(mkmap, STR(key_buffer), STR(value_buffer));
}
/*
* Update or append sendmail and NIS signatures.
*/
if ((open_flags & O_TRUNC) == 0)
mkmap->dict->flags |= DICT_FLAG_DUP_REPLACE;
/*
* Sendmail compatibility: add the @:@ signature to indicate that the
* database is complete. This might be needed by NIS clients running
@ -328,7 +334,7 @@ static int postalias_delete(const char *map_type, const char *map_name,
dict = dict_open3(map_type, map_name, O_RDWR, DICT_FLAG_LOCK);
status = dict_del(dict, key);
dict_close(dict);
return (status);
return (status == 0);
}
/* usage - explain */

View File

@ -60,6 +60,7 @@
# can also be used with IP addresses instead of hostnames.
# EXAMPLES
# .ad
# .fi
# In order to send mail for \fBfoo.org\fR and its subdomains
# via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR:
#

View File

@ -35,6 +35,7 @@
# .in +4
# .nf
# \fIvirtual.domain anything\fR (right-hand content does not matter)
# \fIpostmaster@virtual.domain postmaster\fR
# \fIuser1@virtual.domain address1\fR
# \fIuser2@virtual.domain address2, address3\fR
# .fi

View File

@ -56,8 +56,6 @@
/* .SH Miscellaneous
/* .ad
/* .fi
/* .IP \fBappend_dot_mydomain\fR
/* Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
/* .IP \fBbest_mx_transport\fR
/* Name of the delivery transport to use when the local machine
/* is the most-preferred mail exchanger (by default, a mailer
@ -241,7 +239,6 @@ char *var_smtp_sasl_opts;
char *var_smtp_sasl_passwd;
bool var_smtp_sasl_enable;
char *var_smtp_bind_addr;
bool var_append_dot_mydomain;
/*
* Global variables. smtp_errno is set by the address lookup routines and by
@ -411,7 +408,6 @@ int main(int argc, char **argv)
VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain,
0,
};

View File

@ -50,10 +50,6 @@
#include <vstring.h>
#include <msg.h>
/* Global library. */
#include <mail_params.h>
/* DNS library. */
#include <dns.h>
@ -77,11 +73,8 @@ const char *smtp_unalias_name(const char *name)
* after servicing a limited number of requests, so there is no need to
* prevent the cache from growing too large, or to expire old entries.
*/
if (cache == 0) {
if (cache == 0)
cache = htable_create(10);
if (var_append_dot_mydomain == 0)
smtp_unalias_flags |= RES_DNSRCH;
}
/*
* Look up the fqdn. If none is found use the query name instead, so that

View File

@ -176,10 +176,12 @@ char *smtpd_sasl_mail_opt(SMTPD_STATE *state, const char *addr)
state->error_mask |= MAIL_ERROR_PROTOCOL;
return ("503 Error: authentication disabled");
}
#if 0
if (state->sasl_username == 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
return ("503 Error: send AUTH command first");
}
#endif
if (state->sasl_sender != 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
return ("503 Error: multiple AUTH= options");

View File

@ -13,21 +13,21 @@
/* DESCRIPTION
/* dict_tcp_open() makes a TCP server accessible via the generic
/* dictionary operations described in dict_open(3).
/* The \fIdummy\fR argument is not used. Server access is read-only
/* (i.e., only lookups are implemented).
/* The \fIdummy\fR argument is not used. The only implemented
/* operation is dictionary lookup.
/*
/* Map names have the form host:port.
/*
/* The map implements a very simple protocol: the query is sent as
/* one line of text, and the reply is sent back in the same format.
/* Data is sent as a newline-terminated string. % and non-printable
/* characters are replaced by %xx, xx being the corresponding
/* hexadecimal value.
/* The TCP map class implements a very simple protocol: a query is sent
/* as one line of text, and a reply is sent back in the same format.
/* % and non-printable characters are replaced by %xx, xx being the
/* corresponding hexadecimal value.
/* SEE ALSO
/* dict(3) generic dictionary manager
/* hex_quote(3) http-style quoting
/* DIAGNOSTICS
/* Fatal errors: out of memory, unknown host or service name,
/* attempt to update map.
/* attempt to update or iterate over map.
/* LICENSE
/* .ad
/* .fi
@ -63,8 +63,8 @@
typedef struct {
DICT dict; /* generic members */
char *map; /* server host:port */
VSTRING *raw_buf; /* raw buffer */
VSTRING *hex_buf; /* hexified buffer */
VSTRING *raw_buf; /* raw I/O buffer */
VSTRING *hex_buf; /* quoted I/O buffer */
VSTREAM *fp; /* I/O stream */
} DICT_TCP;
@ -73,12 +73,48 @@ typedef struct {
#define STR(x) vstring_str(x)
/* dict_tcp_connect - connect to TCP server */
static int dict_tcp_connect(DICT_TCP *dict_tcp)
{
int fd;
/*
* Connect to the server. Enforce a time limit on read/write operations
* so that we do not get stuck.
*/
if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
msg_warn("connect to TCP map %s: %m", dict_tcp->map);
return (-1);
}
dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
vstream_control(dict_tcp->fp,
VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
VSTREAM_CTL_END);
/*
* Allocate per-map I/O buffers on the fly.
*/
if (dict_tcp->raw_buf == 0) {
dict_tcp->raw_buf = vstring_alloc(10);
dict_tcp->hex_buf = vstring_alloc(10);
}
return (0);
}
/* dict_tcp_disconnect - disconnect from TCP server */
static void dict_tcp_disconnect(DICT_TCP *dict_tcp)
{
(void) vstream_fclose(dict_tcp->fp);
dict_tcp->fp = 0;
}
/* dict_tcp_lookup - query TCP server */
static const char *dict_tcp_lookup(DICT *dict, const char *key)
{
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
int fd;
int i;
dict_errno = 0;
@ -86,7 +122,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
for (i = 0; /* see below */ ; i++) {
/*
* Try to connect a few times before giving up.
* Try to connect a limited number of times before giving up.
*/
if (i >= DICT_TCP_MAXTRY) {
dict_errno = DICT_ERR_RETRY;
@ -94,36 +130,22 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
}
/*
* Sleep between connection attempts.
* Sleep between attempts, instead of hammering the server.
*/
if (i > 0)
sleep(1);
/*
* Try to connect to the server.
* Connect to the server.
*/
if (dict_tcp->fp == 0) {
if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
msg_warn("connect to TCP map %s: %m", dict_tcp->map);
if (dict_tcp->fp == 0)
if (dict_tcp_connect(dict_tcp) < 0)
continue;
}
dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
vstream_control(dict_tcp->fp,
VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
VSTREAM_CTL_END);
}
/*
* Allocate per-map buffers on the fly.
*/
if (dict_tcp->raw_buf == 0) {
dict_tcp->raw_buf = vstring_alloc(10);
dict_tcp->hex_buf = vstring_alloc(10);
}
/*
* Send query and receive response. Both are %XX quoted and both are
* terminated by newline.
* terminated by newline. This encoding is convenient for data that
* is mostly text.
*/
hex_quote(dict_tcp->hex_buf, key);
vstream_fprintf(dict_tcp->fp, "%s\n", STR(dict_tcp->hex_buf));
@ -140,8 +162,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
/*
* That did not work. Clean up and try again.
*/
(void) vstream_fclose(dict_tcp->fp);
dict_tcp->fp = 0;
dict_tcp_disconnect(dict_tcp);
}
}
@ -154,6 +175,25 @@ static void dict_tcp_update(DICT *dict, const char *unused_name, const char *unu
msg_fatal("dict_tcp_update: attempt to update map %s", dict_tcp->map);
}
/* dict_tcp_delete - remove table entry */
static int dict_tcp_delete(DICT *dict, const char *unused_name)
{
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
msg_fatal("dict_tcp_delete: attempt to update map %s", dict_tcp->map);
}
/* dict_tcp_sequence - iterate over table */
static int dict_tcp_sequence(DICT *dict, int unused_func,
const char **unused_name, const char **unused_value)
{
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
msg_fatal("dict_tcp_sequence: attempt to iterate map %s", dict_tcp->map);
}
/* dict_tcp_close - close TCP map */
static void dict_tcp_close(DICT *dict)
@ -183,6 +223,8 @@ DICT *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
dict_tcp->raw_buf = dict_tcp->hex_buf = 0;
dict_tcp->dict.lookup = dict_tcp_lookup;
dict_tcp->dict.update = dict_tcp_update;
dict_tcp->dict.delete = dict_tcp_delete;
dict_tcp->dict.sequence = dict_tcp_sequence;
dict_tcp->dict.close = dict_tcp_close;
dict_tcp->dict.fd = -1;
dict_tcp->map = mystrdup(map);