mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
snapshot-20010122
This commit is contained in:
committed by
Viktor Dukhovni
parent
0f4cca51f3
commit
19ca5e1319
@@ -60,23 +60,20 @@ The filter program can start out as a simple shell script like this:
|
||||
# Exit codes from <sysexits.h>
|
||||
EX_TEMPFAIL=75
|
||||
EX_UNAVAILABLE=69
|
||||
STATUS=$EX_TEMPFAIL
|
||||
|
||||
# Clean up when done or when aborting.
|
||||
trap "rm -f in.$$; exit $STATUS" 0 1 2 3 15
|
||||
|
||||
quit() { STATUS=${1-$?}; exit; }
|
||||
trap "rm -f in.$$" 0 1 2 3 15
|
||||
|
||||
# Start processing.
|
||||
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; quit $EX_TEMPFAIL; }
|
||||
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
|
||||
|
||||
cat >in.$$ || { echo Cannot save mail to file; quit $EX_TEMPFAIL; }
|
||||
cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
|
||||
|
||||
# filter <in.$$ || { echo Message content rejected; quit $EX_UNAVAILABLE; }
|
||||
# filter <in.$$ || { echo Message content rejected; exit $EX_UNAVAILABLE; }
|
||||
|
||||
$SENDMAIL "$@" <in.$$
|
||||
|
||||
STATUS=$?
|
||||
exit $?
|
||||
|
||||
The idea is to first capture the message to file and then run the
|
||||
content through run a third-party content filter program. If the
|
||||
|
@@ -4672,13 +4672,6 @@ Apologies for any names omitted.
|
||||
core instead if issuing an error message. This is what I
|
||||
get for accepting code that I cannot test myself.
|
||||
|
||||
20001220
|
||||
|
||||
Feature: merged in Andrew McNamara's virtual delivery agent
|
||||
(a table-driven agent that does not require recipients to
|
||||
have UNIX accounts, and that implements a safe subset of
|
||||
the default local delivery agent). Files: virtual/*.
|
||||
|
||||
20001221
|
||||
|
||||
Code cleanup: configuration parameters that are $name
|
||||
@@ -4708,3 +4701,49 @@ Apologies for any names omitted.
|
||||
Bugfix: soft errors in client hostname lookups would be
|
||||
treated as hard errors. Fix by Michael Herrmann
|
||||
(informatik.tu-muenchen.de). File: smtpd/smtpd_peer.c.
|
||||
|
||||
20010110
|
||||
|
||||
Bugfix: the mkdir() EEXIST race condition workaround was
|
||||
not complete. Matthias Andree, Daniel Roesen. Files:
|
||||
global/mail_queue.c, util/make_dirs.c.
|
||||
|
||||
20010111
|
||||
|
||||
Portability: IRIX 6.5.10 defines sa_len as a macro, causing
|
||||
a name collision with a variable used by Postfix. Roberto
|
||||
Totaro, enigma.ethz.ch. File: smtpstone/smtp-source.c.
|
||||
|
||||
20010116
|
||||
|
||||
Bugfix: REJECT by header/body_checks was flagged in smtpd
|
||||
as a bounce, should be policy, in order to make postmaster
|
||||
notifications more consistent. File: smtpd/smtpd.c.
|
||||
|
||||
Merged updated chroot setup procedure by Matthias Andree.
|
||||
Files: examples/chroot-setup/LINUX2.
|
||||
|
||||
20010117
|
||||
|
||||
Formatting: changed the seconds and days formats in the
|
||||
"your mail is delayed" text so that it does not switch to
|
||||
scientific notation. File: bounce/bounce_notify_util.c.
|
||||
|
||||
20010119
|
||||
|
||||
Feature: SASL support for the LMTP client. Recent CYRUS
|
||||
software requires this for Postfix over TCP sockets.
|
||||
This was just a cloning operation.
|
||||
|
||||
20010120
|
||||
|
||||
Bugfix: the 20001005 revised fallback_relay support caused
|
||||
Postfix to send mail to the fallback even when the local
|
||||
machine was an MX host for the final destination. Result:
|
||||
mailer loop. Found by Laurent Wacrenier (teaser.fr). Files:
|
||||
smtp/smtp_connect.c, smtp/smtp_addr.c.
|
||||
|
||||
20010121
|
||||
|
||||
Workaround: Lotus Domino 5.0.4 violates RFC 2554 and replies
|
||||
to EHLO with AUTH=LOGIN. File: smtp/smtp_proto.c.
|
||||
|
@@ -1,99 +1,346 @@
|
||||
BEGIN WARNING
|
||||
=============
|
||||
|
||||
The information in this file is outdated. The Postfix LMTP server
|
||||
can now make connections over UNIX-domain sockets.
|
||||
|
||||
With connections over TCP sockets, some Cyrus implementations insist
|
||||
on SASL-style authentication, which is not supported by the Postfix
|
||||
LMTP client. In that case, use UNIX-domain sockets instead.
|
||||
|
||||
The precise syntax for UNIX-domain and TCP connection endpoints is
|
||||
given in the lmtp(8) manual page.
|
||||
|
||||
Examples:
|
||||
|
||||
/etc/postfix/transport:
|
||||
domain1.name lmtp1:unix:/path/name
|
||||
domain2.name lmtp2:lmtp2host
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
lmtp1 unix - - n - - lmtp
|
||||
lmtp2 unix - - n - - lmtp
|
||||
|
||||
The first example (domain1) uses UNIX-domain connections, the second
|
||||
example (domain2) uses TCP.
|
||||
|
||||
For optimal use of connection caching, specify separate mail delivery
|
||||
transports for each domain that receives mail via LMTP:
|
||||
|
||||
END WARNING
|
||||
===========
|
||||
[Based on information that was provided by Amous Gouaux]
|
||||
|
||||
Postfix LMTP support
|
||||
====================
|
||||
|
||||
LMTP stands for Local Mail Transfer Protocol, and is detailed in
|
||||
RFC2033. This protocol is used to communicate with the final
|
||||
delivery agent, which may be on the local host or a remote host.
|
||||
|
||||
This protocol opens up interesting possibilities: one Postfix front
|
||||
end system can drive multiple mailbox back end systems over LMTP.
|
||||
As the mail load increases you add Postfix front end systems and
|
||||
LMTP mailbox back end systems. You can use LDAP or mysql to share
|
||||
the user database among the front end and back end systems.
|
||||
|
||||
Postfix LMTP support is based on a modified version of the Postfix
|
||||
SMTP client. The initial version was by Philip A. Prindeville of
|
||||
Mirapoint, Inc., USA. This code was modified further by Amos Gouaux
|
||||
of University of Texas at Dallas, Richardson, USA. Wietse Venema
|
||||
reduced the code to its present shape.
|
||||
|
||||
Postfix can be configured to talk to a local or remote LMTP server.
|
||||
Most people will run the LMTP server on the same machine that runs
|
||||
Postfix. However, a remote LMTP server can be useful if Postfix
|
||||
runs on mail relay server(s) that feed incoming mail directly to
|
||||
the appropriate mailbox server(s). This way, mailbox servers do
|
||||
not need to run an SMTP server at all. Tidy all the way around.
|
||||
|
||||
Configuring the mailbox server (local or remote)
|
||||
================================================
|
||||
Overview
|
||||
========
|
||||
|
||||
On the mailbox server, in this case a CMU Cyrus imapd/popd server,
|
||||
add the following to /etc/services:
|
||||
Most of the examples in this document involve the CMU Cyrus IMAP/POP
|
||||
server, available from:
|
||||
|
||||
pop3 110/tcp # Cyrus POP3
|
||||
imap 143/tcp # Cyrus IMAP4
|
||||
lmtp 24/tcp
|
||||
http://asg.web.cmu.edu/cyrus/
|
||||
|
||||
Next, put the following in /etc/inetd.conf:
|
||||
While certainly not the only application that could make use of LMTP,
|
||||
it tends to be the most discussed. These examples are based on the
|
||||
forthcoming Cyrus 2.0.10, at least at the time of writing. The 2.x
|
||||
branch of Cyrus places greater emphasis on LMTP delivery than the
|
||||
previous releases. Those using older releases of Cyrus can find a
|
||||
discussion in the appendix of this document.
|
||||
|
||||
lmtp stream tcp nowait cyrus /usr/sbin/tcpd /usr/local/cyrus/bin/deliver -e -l
|
||||
There are a variety of ways LMTP delivery can be configured in
|
||||
Postfix. The two basic flavors are delivery over UNIX-domain sockets
|
||||
and delivery over TCP sockets. Both flavors can be specified in
|
||||
either the Postfix main.cf or in a transport map. The best approach
|
||||
to use depends upon the arrangement of your servers and the desired
|
||||
level of parallelization. Please be sure to study this entire
|
||||
document as there are trade-offs in convenience and performance with
|
||||
these different approaches.
|
||||
|
||||
/usr/sbin/tcpd is from the tcp_wrappers package. You want this to
|
||||
make sure only your mail relay(s) can talk to the LMTP server.
|
||||
Postfix by default does multiple deliveries per LMTP session
|
||||
(connection caching), so do not worry about the overhead of
|
||||
tcp_wrapping the LMTP port.
|
||||
The precise syntax for UNIX-domain and TCP connection endpoints is
|
||||
given in the lmtp(8) manual page.
|
||||
|
||||
On some systems, tcpd is built into inetd, so you do not have to
|
||||
specify tcpd in the inetd.conf file. Instead of tcpd/inetd, xinetd
|
||||
can do a similar job of logging and access control.
|
||||
|
||||
Configuring Postfix
|
||||
===================
|
||||
Using main.cf configuration
|
||||
===========================
|
||||
|
||||
Similar changes to /etc/services:
|
||||
This is the simplest LMTP configuration. The settings
|
||||
local_transport, mailbox_transport, and fallback_transport can
|
||||
support the following connections:
|
||||
|
||||
lmtp 24/tcp
|
||||
1. LMTP over TCP sockets.
|
||||
|
||||
You may have to add the following entry to /etc/postfix/master.cf:
|
||||
mailbox_transport = lmtp
|
||||
|
||||
lmtp unix - - n - - lmtp
|
||||
Instead of delivering local mail to a mail box such as
|
||||
/var/mail/$user, a connection will be made over TCP to an LMTP
|
||||
server. Currently the default port for this connection is 24,
|
||||
but this can be customized in the "/etc/services" file.
|
||||
|
||||
NOTE: Root privileges are not necessary!
|
||||
NOTE:
|
||||
|
||||
Put this in /etc/postfix/transport:
|
||||
With connections over TCP sockets, some Cyrus implementations
|
||||
insist on SASL-style authentication, which is not currently
|
||||
supported by the Postfix LMTP client. See the examples below
|
||||
for additional details.
|
||||
|
||||
inbox.domain.org lmtp:inbox.domain.org
|
||||
|
||||
Naturally, this means we also need in /etc/postfix/main.cf:
|
||||
2. LMTP over UNIX-domain sockets.
|
||||
|
||||
transport_maps = hash:/etc/postfix/transport
|
||||
mailbox_transport = lmtp:unix:/path/name
|
||||
|
||||
In this case the LMTP connection will be made over a UNIX-domain
|
||||
socket. This "/path/name" should be the socket created by the
|
||||
LMTP server on the local machine.
|
||||
|
||||
NOTE 1:
|
||||
|
||||
If you configured Cyrus using the "--with-libwrap" option, be
|
||||
sure to allow access to the "lmtpd" service from "0.0.0.0".
|
||||
Otherwise LMTP deliveries over UNIX-domain sockets will be
|
||||
blocked. See the examples below for more on using libwrap.
|
||||
|
||||
NOTE 2:
|
||||
|
||||
If you run the lmtp client chrooted, the interpretation of
|
||||
the /path/name is relative to the Postfix queue directory
|
||||
(typically, /var/spool/postfix).
|
||||
|
||||
NOTE 3:
|
||||
|
||||
By default, the Postfix LMTP client does not run chrooted.
|
||||
With LMTP delivery to the local machine there is no good
|
||||
reason to run the Postfix LMTP client chrooted.
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
1. LMTP over UNIX-domain sockets.
|
||||
|
||||
To utilize UNIX-domain sockets for the communication between
|
||||
Postfix and Cyrus, the corresponding configuration files should
|
||||
look something like this:
|
||||
|
||||
/etc/cyrus.conf:
|
||||
|
||||
SERVICES {
|
||||
...
|
||||
lmtpunix cmd="lmtpd" listen="/var/imap/socket/lmtp" prefork=1
|
||||
...
|
||||
}
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
mailbox_transport = lmtp:unix:/var/imap/socket/lmtp
|
||||
|
||||
In this case, mail that is resolved to be local will be delivered
|
||||
to the Cyrus lmtpd server via the socket "/var/imap/socket/lmtp".
|
||||
|
||||
If you configured Cyrus using the "--with-libwrap" option, you
|
||||
will need the following:
|
||||
|
||||
/etc/hosts.allow:
|
||||
|
||||
lmtpd : 0.0.0.0
|
||||
|
||||
2. LMTP over TCP sockets.
|
||||
|
||||
For this example, suppose the following files are configured
|
||||
thusly:
|
||||
|
||||
/etc/cyrus.conf:
|
||||
|
||||
SERVICES {
|
||||
...
|
||||
lmtp cmd="lmtpd -a" listen="127.0.0.1:lmtp" prefork=0
|
||||
...
|
||||
}
|
||||
|
||||
XXX does this mean that connections will be accepted only on 127.0.0.1?
|
||||
|
||||
/etc/services:
|
||||
|
||||
lmtp 2003/tcp
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
mailbox_transport = lmtp
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
|
||||
lmtp unix - - n - - lmtp
|
||||
|
||||
Mail that Postfix resolves to be local will be delivered via TCP
|
||||
to the Cyrus LMTP server. Postfix will make a connection to port
|
||||
2003 on the local host, subsequently transmitting the message to
|
||||
the lmtpd server managed by the Cyrus master process. Since
|
||||
Postfix does not currently support LMTP-AUTH, the "-a" lmtpd
|
||||
option is required.
|
||||
|
||||
CAUTION:
|
||||
|
||||
If you run lmtpd with the "-a" option, be certain that you
|
||||
restrict what systems can connect to this service. This can
|
||||
be done in either one of two ways:
|
||||
|
||||
a. Compile Cyrus with libwrap support, configuring
|
||||
"/etc/hosts.allow" to restrict access to this service to
|
||||
only your mail server.
|
||||
|
||||
b. In the cyrus.conf file, for the "listen" argument to the
|
||||
"lmtp" service, specify the address (in this case
|
||||
localhost), that the service should bind to. This can
|
||||
also be convenient if you have a private network between
|
||||
your Postfix server and your Cyrus server.
|
||||
|
||||
If neither of these actions are taken, anybody will be able
|
||||
to drop junk into your Cyrus message store!
|
||||
|
||||
|
||||
3. LMTP over TCP sockets, using hosts.allow.
|
||||
|
||||
While similar to the previous example, this one varies in how the
|
||||
lmtpd service is protected from unauthorized use. Instead of
|
||||
binding the lmtpd service to a specific Internet address, access
|
||||
will be controlled using the "/etc/hosts.allow" tcp_wrappers
|
||||
configuration file. The tcp_wrappers package is available from:
|
||||
|
||||
ftp://ftp.porcupine.org/pub/security/index.html
|
||||
|
||||
To take advantage of tcp_wrappers, Cyrus will need to be
|
||||
configured using the "--with-libwrap" option. See the Cyrus
|
||||
documentation for more details.
|
||||
|
||||
Here are excerpts of the pertinent files:
|
||||
|
||||
/etc/hosts.allow:
|
||||
|
||||
lmtpd : localhost : ALLOW
|
||||
lmtpd : ALL@ALL : DENY
|
||||
|
||||
/etc/cyrus.conf:
|
||||
|
||||
SERVICES {
|
||||
...
|
||||
lmtp cmd="lmtpd -a" listen="lmtp" prefork=0
|
||||
...
|
||||
}
|
||||
|
||||
/etc/services:
|
||||
|
||||
lmtp 2003/tcp
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
mailbox_transport = lmtp
|
||||
|
||||
The syntax shown in the hosts.allow excerpt above is valid if
|
||||
tcp_wrappers is compiled using a "make" argument of:
|
||||
|
||||
STYLE=-DPROCESS_OPTIONS
|
||||
|
||||
See the tcp_wrappers hosts_options(5) man page for more details.
|
||||
|
||||
|
||||
Using transport map configuration
|
||||
=================================
|
||||
|
||||
This approach is quite similar to specifying the LMTP service in the
|
||||
Postfix main.cf configuration file. However, now we will use a
|
||||
transport map to route mail to the appropriate LMTP server. Why
|
||||
might this approach be useful? This could be handy if you wish to
|
||||
route mail for multiple domains to their respective mail retrieval
|
||||
(IMAP/POP) server. Example:
|
||||
|
||||
/etc/postfix/transport:
|
||||
|
||||
domain1.name lmtp1:unix:/path/name
|
||||
domain2.name lmtp2:lmtp2host
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
|
||||
lmtp1 unix - - n - - lmtp
|
||||
lmtp2 unix - - n - - lmtp
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
transport_maps = hash:/etc/postfix/transport
|
||||
|
||||
Instead of "hash", use the map type of your choice. Some systems use
|
||||
"dbm" instead. Use "postconf -m" to find out what map types are
|
||||
supported.
|
||||
|
||||
|
||||
Performance considerations
|
||||
==========================
|
||||
|
||||
Hopefully the preceding discussion has seemed pretty straight
|
||||
forward. Now things get interesting. After reading the following
|
||||
you will see that there are more factors to consider when setting up
|
||||
LMTP services.
|
||||
|
||||
|
||||
Single instance message store
|
||||
=============================
|
||||
|
||||
Presently this topic is more pertinent to sites running Cyrus, but
|
||||
may be a factor with other applications as well.
|
||||
|
||||
Since 1.6.22, Cyrus has had the feature that if a message containing
|
||||
multiple recipients is received via the LMTP protocol, and all these
|
||||
recipients were on the same Cyrus partition, only one instance of
|
||||
this message would be written to the file system. The other
|
||||
recipients would then see a hard link of this single instance.
|
||||
Depending on your user base, this can be considerable motivation to
|
||||
using LMTP.
|
||||
|
||||
However, there is a catch: currently the Postfix local delivery
|
||||
mechanisms are only designed to handle one recipient at a time, which
|
||||
in most cases is more than adequate. So, if you wish to support
|
||||
single instance message store delivery, you will have to use a
|
||||
transport table to map these users to the appropriate LMTP
|
||||
destination.
|
||||
|
||||
While the simplest thing to do would be to list the entire domain in
|
||||
the transport map for LMTP delivery, this by-passes alias expansion
|
||||
for otherwise local addresses. If the site is to run software via
|
||||
aliases, like most Mailing List Management (MLM) software, a more
|
||||
complex solution is required. Fortunately, a virtual table should do
|
||||
the trick.
|
||||
|
||||
As an example, suppose we wanted to support single instance message
|
||||
store delivery for the domain "example.org". The configuration files
|
||||
for this domain could look something like this:
|
||||
|
||||
/etc/postfix/virtual:
|
||||
|
||||
mlist@example.org mlist@localhost
|
||||
|
||||
/etc/postfix/transport:
|
||||
|
||||
example.org lmtp:unix:/var/imap/socket/lmtp
|
||||
|
||||
/etc/postfix/aliases:
|
||||
|
||||
mlist: "|/path/to/mlm/software"
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
|
||||
lmtp unix - - n - - lmtp
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
mydestination = localhost, $myhostname, $mydomain
|
||||
virtual_maps = hash:/etc/postfix/virtual
|
||||
transport_maps = hash:/etc/postfix/transport
|
||||
alias_maps = hash:/etc/postfix/aliases
|
||||
alias_database = hash:/etc/postfix/aliases
|
||||
|
||||
/etc/cyrus.conf:
|
||||
|
||||
SERVICES {
|
||||
...
|
||||
lmtpunix cmd="lmtpd" listen="/var/imap/socket/lmtp" prefork=1
|
||||
...
|
||||
}
|
||||
|
||||
Breaking things down, we begin with the address "mlist@example.org",
|
||||
which represents a mailing list. By placing an entry in the virtual
|
||||
map to direct this mail to "mlist@localhost", we can override the
|
||||
transport map that would by default route all "@example.org" mail to
|
||||
a LMTP server via a UNIX-domain socket.
|
||||
|
||||
To summarize, all mail that is to be processed by an alias entry must
|
||||
first be diverted with a virtual table entry so that it does not fall
|
||||
into the more general routing established by the transport table.
|
||||
|
||||
Instead of "hash", use the map type of your choice. Some systems
|
||||
use "dbm" instead. Use "postconf -m" to find out what map types
|
||||
are supported.
|
||||
|
||||
Improving connection caching performance
|
||||
========================================
|
||||
@@ -112,6 +359,7 @@ You can prevent the LMTP client from switching between servers by
|
||||
configuring a separate mail delivery transport for each LMTP server:
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
|
||||
lmtp1 unix - - n - - lmtp
|
||||
lmtp2 unix - - n - - lmtp
|
||||
. . . . . . . .
|
||||
@@ -121,5 +369,99 @@ transport is used for all deliveries to the LMTP server #1, the
|
||||
mail lmtp2 transport for the LMTP server #2, and so on.
|
||||
|
||||
/etc/postfix/transport:
|
||||
|
||||
foo.com lmtp1:lmtp1host
|
||||
bar.com lmtp2:lmtp2host
|
||||
|
||||
|
||||
Appendix: Older Cyrus versions
|
||||
==============================
|
||||
|
||||
First of all, if you are using a Cyrus 2.x version prior to 2.0.10,
|
||||
it would be good to upgrade. The previous 2.x releases were beta
|
||||
releases, and numerous bug fixes and enhancements have been
|
||||
incorporated into the 2.0.10 release.
|
||||
|
||||
Further back, 1.6.24 was the last pre-2.x production release.
|
||||
(Actually, there was a 1.6.25-BETA, but it is uncertain whether this
|
||||
will be released officially as CMU is now focusing support on the 2.x
|
||||
branch.) The following discussion touches on how to configure the
|
||||
Postfix LMTP facilities with Cyrus 1.6.24.
|
||||
|
||||
One of the significant differences between Cyrus 1.x and 2.x is the
|
||||
inclusion of the "master" process in 2.x. This "master" process is
|
||||
responsible for running the various components of Cyrus, such as
|
||||
imapd, pop3d, and lmtpd. Prior to 2.x, these services were managed
|
||||
by inetd, the Internet services daemon.
|
||||
|
||||
To utilize LMTP delivery with Cyrus 1.6.24, the first thing to do is
|
||||
configure inetd. This involves the following file edits:
|
||||
|
||||
/etc/services:
|
||||
|
||||
lmtp 2003/tcp
|
||||
|
||||
/etc/inetd.conf:
|
||||
|
||||
lmtp stream tcp nowait cyrus /usr/sbin/tcpd /usr/cyrus/bin/deliver -e -l
|
||||
|
||||
/etc/hosts.allow:
|
||||
|
||||
deliver : localhost : ALLOW
|
||||
deliver : ALL@ALL : DENY
|
||||
|
||||
The "/usr/sbin/tcpd" is from the tcp_wrappers package, which is
|
||||
discussed in the example "LMTP over TCP sockets, using hosts.allow."
|
||||
It is important that you wrap this LMTP port to protect it from
|
||||
unauthorized access.
|
||||
|
||||
On some systems, tcpd is built into inetd, so you do not have to
|
||||
specify tcpd in the inetd.conf file. Instead of tcpd/inetd, xinetd
|
||||
can do a similar job of logging and access control.
|
||||
|
||||
Now comes the Postfix configuration. Basically, the Cyrus 2.x
|
||||
discussions regarding LMTP delivery over TCP are also applicable to
|
||||
Cyrus 1.x, with the exception of the "/etc/cyrus.conf" file. A
|
||||
typical Postfix configuration might look like this:
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
|
||||
lmtp unix - - n - - lmtp
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
mailbox_transport = lmtp
|
||||
|
||||
It is also possible to use the transport map to route mail to your
|
||||
Cyrus 1.6.24 LMTP server:
|
||||
|
||||
/etc/postfix/transport:
|
||||
|
||||
domain1.name lmtp1:lmtp1host
|
||||
domain2.name lmtp2:lmtp2host
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
|
||||
lmtp1 unix - - n - - lmtp
|
||||
lmtp2 unix - - n - - lmtp
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
|
||||
transport_maps = hash:/etc/postfix/transport
|
||||
|
||||
If you have read the discussion covering the Cyrus 2.x installation,
|
||||
you will notice the one significant difference with the Postfix
|
||||
configuration is the lack of mention of the UNIX-domain sockets.
|
||||
That is because delivery over UNIX-domain sockets is new with Cyrus
|
||||
2.x, yet another reason to upgrade. :-)
|
||||
|
||||
|
||||
|
||||
# Local Variables:
|
||||
# mode: text
|
||||
# mode: flyspell
|
||||
# fill-column: 69
|
||||
# End:
|
||||
|
||||
|
||||
|
||||
|
@@ -6,7 +6,7 @@ DIRS = src/util src/global src/dns src/master src/postfix src/smtpstone \
|
||||
src/lmtp src/trivial-rewrite src/qmgr src/smtp src/bounce src/pipe \
|
||||
src/showq src/postalias src/postcat src/postconf src/postdrop \
|
||||
src/postkick src/postlock src/postlog src/postmap src/postsuper \
|
||||
src/nqmgr src/spawn src/flush src/virtual # src/base64 proto man html
|
||||
src/nqmgr src/spawn src/flush # proto man html
|
||||
|
||||
default: update
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
REJECT by header/body_checks are now flagged as policy violations
|
||||
rather than bounces, for consistency in postmaster notifications.
|
||||
|
||||
Major changes with snapshot-20001217
|
||||
====================================
|
||||
|
||||
|
@@ -1,10 +1,23 @@
|
||||
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||
===============================================================
|
||||
|
||||
Do not use this code. The Postfix SASL support is based on the
|
||||
Cyrus SASL library, which has not enough documentation about how
|
||||
the software is supposed to work. It is not clear if the code is
|
||||
safe enough for security-critical applications.
|
||||
This code is not blessed by Wietse.
|
||||
|
||||
People who go to the trouble of installing Postfix may have the
|
||||
expectation that Postfix is more secure than some other mailers.
|
||||
|
||||
With SASL authentication enabled in the Postfix SMTP client and
|
||||
SMTP server, Postfix becomes no more secure than other mail systems
|
||||
that use the Cyrus SASL library.
|
||||
|
||||
The Cyrus SASL library has too little documentation about how the
|
||||
software is supposed to work; and it is too much code to be used
|
||||
in a security-sensitive program such as an SMTP client or server.
|
||||
|
||||
However, you are pretty much required to build with SASL support
|
||||
if you are going to use the LMTP interface of the Cyrus delivery
|
||||
agent. This interface is much faster than forking a new process
|
||||
for every message delivery.
|
||||
|
||||
Postfix+SASL 1.5.5 appears to work on RedHat 6.1 (pwcheck_method
|
||||
set to shadow or sasldb), Solaris 2.7 (pwcheck_method set to shadow
|
||||
@@ -14,9 +27,6 @@ Note that this seems to be related to the auto_transition switch in
|
||||
SASL. Note also that the Cyrus SASL documentation says that it is
|
||||
pointless to enable that if you use "sasldb" for "pwcheck_method".
|
||||
|
||||
SASL is a lot of complex code. In a future version the Postfix SASL
|
||||
code is likely to be put outside the SMTP server.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
@@ -52,6 +62,12 @@ Reportedly, Microsoft Internet Explorer version 5 requires the
|
||||
non-standard SASL LOGIN authentication method. To enable this
|
||||
authentication method, specify ``./configure --enable-login''.
|
||||
|
||||
Reportedly, older Microsoft software mis-implements the AUTH
|
||||
protocol, and requires that the server replies to EHLO with
|
||||
"250-AUTH=stuff..." instead of "250-AUTH stuff...". To accomodate
|
||||
such clients, set "allow_broken_auth_clients = yes" in the main.cf
|
||||
file.
|
||||
|
||||
Building Postfix with SASL authentication support
|
||||
=================================================
|
||||
|
||||
|
@@ -1,154 +0,0 @@
|
||||
[Code contribued by Andrew McNamara ]
|
||||
|
||||
Code created by Andrew McNamara <andrew@connect.com.au> and adapted to
|
||||
snapshot 20001121 by Xavier Beaudouin.
|
||||
|
||||
Code is maintened now by Xavier Beaudouin <kiwi@oav.net>
|
||||
|
||||
[Original Message]
|
||||
I've run out of time to fiddle further at the moment, so I've decided to
|
||||
post my virtual local delivery agent. Note that this is still a work in
|
||||
progress, so don't bet your business on it.
|
||||
|
||||
I'll repeat what I said last time:
|
||||
|
||||
This code is designed for ISP's who offer virtual mail hosting. It
|
||||
looks up the location, uid and gid of user mailboxes via separate maps,
|
||||
and the mailbox location map can specify either mailbox or maildir
|
||||
delivery (controlled by trailing slash on mailbox name).
|
||||
|
||||
The agent does not support aliases or .forwards (use the virtual table
|
||||
instead), and therefore doesn't support file or program aliases. This
|
||||
choice was made to simplify and streamline the code (it allowed me to
|
||||
dispense with 70% of local's code - mostly the bits that are a security
|
||||
headache) - if you need this functionality, this agent isn't for you.
|
||||
|
||||
It also doesn't support writing to a common spool as root and then
|
||||
chowning the mailbox to the user - I felt this functionality didn't fit
|
||||
with my overall aims.
|
||||
|
||||
Some other notes:
|
||||
|
||||
- It's still called "virtual" - I had some concerns that this would
|
||||
confuse people, but I'll leave that call up to Wietse - if he wants
|
||||
to integrate it, he can specify the name.
|
||||
|
||||
- I've retained the three separate map lookups at this time. When
|
||||
postfix supports maps that return multiple values, we can consider
|
||||
changing it then.
|
||||
|
||||
- Specify "virtual:" as the target in the transport table for domains
|
||||
for which you want this agent used.
|
||||
|
||||
- The attached file is a gzipped tar that should be unpacked in the
|
||||
base postfix directory (where the INSTALL and HISTORY files live) -
|
||||
it adds a "virtual" subdirectory, and a "virtual.patch" file. The
|
||||
patch updates the top level Makefile.in to build the new agent, and
|
||||
global/mail_params.h to add the new config parameters.
|
||||
|
||||
New config options are:
|
||||
|
||||
virtual_mailbox_base
|
||||
|
||||
Specifies a path that is prepended to all mailbox paths. This is
|
||||
a safety measure to ensure an out of control map doesn't litter the
|
||||
filesystem with mailboxes (or worse). While it could be set to "/",
|
||||
this isn't recommended.
|
||||
|
||||
virtual_mailbox_maps
|
||||
|
||||
Recipients are looked up in this map to determine the path to their
|
||||
mailbox. If the returned path ends in a slash ("/"), maildir-style
|
||||
delivery is carried out, otherwise the path is assumed to specify a
|
||||
mailbox file. Note that virtual_mailbox_base is unconditionally
|
||||
prepended to this path.
|
||||
|
||||
virtual_minimum_uid
|
||||
|
||||
Specifies a minimum uid that will be accepted as a return from a
|
||||
virtual_uid_maps lookup. Returned values less than this will be
|
||||
rejected, and the message will be deferred.
|
||||
|
||||
virtual_uid_maps
|
||||
|
||||
Recipients are looked up in this map to determine the UID to be
|
||||
used when writing to the target mailbox.
|
||||
|
||||
virtual_gid_maps
|
||||
|
||||
Recipients are looked up in this map to determine the GID to be
|
||||
used when writing to the target mailbox.
|
||||
|
||||
virtual_usedotlock
|
||||
|
||||
Use dot-locking when writing to mailboxes - defaults to off.
|
||||
|
||||
[ - Exemple configuration - ]
|
||||
|
||||
In main.cf file :
|
||||
--/---
|
||||
virtual_mailbox_base = /var/mail/vhosts
|
||||
virtual_mailbox_maps = dbm:/etc/postfix/vmailbox
|
||||
virtual_minimum_uid = 100
|
||||
virtual_uid_maps = dbm:/etc/postfix/vuid
|
||||
virtual_gid_maps = dbm:/etc/postfix/vgid
|
||||
virtual_usedotlock = no
|
||||
--/---
|
||||
|
||||
In vmailbox file :
|
||||
|
||||
--/---
|
||||
testuser@fakedom.com testuser/
|
||||
--/---
|
||||
|
||||
In vuid file :
|
||||
|
||||
--/---
|
||||
testuser@fakedom.com 5000
|
||||
--/---
|
||||
|
||||
In vgid file :
|
||||
|
||||
--/---
|
||||
testuser@fakedom.com 5000
|
||||
--/---
|
||||
|
||||
Don't forget to add in master.cf the entry for the agent, that should be
|
||||
like :
|
||||
|
||||
--/---
|
||||
virtual unix - n n - - virtual
|
||||
--/---
|
||||
|
||||
NOTES :
|
||||
-------
|
||||
|
||||
1- Don't forget to add dbm:/etc/posfix/vmailbox into your
|
||||
local_recipent_maps in main.cf like :
|
||||
|
||||
--/---
|
||||
local_recipient_maps = $alias_maps dbm:/etc/posfix/vmailbox unix:passwd.byname
|
||||
--/---
|
||||
|
||||
2- If you use only the virtual localdelivery you can add the following line
|
||||
into main.cf
|
||||
|
||||
--/---
|
||||
mailbox_transport = virtual
|
||||
--/---
|
||||
|
||||
Otherwise you can use transport_maps :
|
||||
|
||||
In main.cf file :
|
||||
|
||||
--/---
|
||||
transport_maps=dbm:/etc/postfix/transport
|
||||
--/---
|
||||
|
||||
In transport file :
|
||||
|
||||
--/---
|
||||
fakedom.com virtual:
|
||||
--/---
|
||||
|
||||
|
66
postfix/conf/sample-compatibility.cf
Normal file
66
postfix/conf/sample-compatibility.cf
Normal file
@@ -0,0 +1,66 @@
|
||||
# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF
|
||||
# HERE JUST SERVES AS AN EXAMPLE.
|
||||
#
|
||||
# This file contains example settings of Postfix configuration
|
||||
# parameters that control compatibility with broken software.
|
||||
|
||||
# The ignore_mx_lookup_error parameter controls what happens when a
|
||||
# name server fails to respond to an MX lookup request. By default,
|
||||
# Postfix defers delivery and tries again after some delay. Specify
|
||||
# "ignore_mx_lookup_error = yes" to force an A record lookup instead.
|
||||
#
|
||||
ignore_mx_lookup_error = no
|
||||
|
||||
# The smtp_always_send_ehlo parameter specifies that the SMTP client
|
||||
# should always send EHLO at the start of an SMTP session.
|
||||
#
|
||||
# By default, Postfix sends EHLO only when the word "ESMTP" appears
|
||||
# in the server greeting banner (example: 220 spike.porcupine.org
|
||||
# ESMTP Postfix).
|
||||
#
|
||||
smtp_always_send_ehlo = no
|
||||
|
||||
# The smtp_never_send_ehlo parameter specifies that the SMTP client
|
||||
# should never send EHLO at the start of an SMTP session.
|
||||
#
|
||||
# By default, Postfix sends EHLO whenever the word "ESMTP" appears
|
||||
# in the server greeting banner (example: 220 spike.porcupine.org
|
||||
# ESMTP Postfix).
|
||||
#
|
||||
smtp_never_send_ehlo = no
|
||||
|
||||
# The smtp_skip_4xx_greeting parameter controls what happens when
|
||||
# an SMTP server greets us with a 4XX status code (go away, try
|
||||
# again later).
|
||||
#
|
||||
# By default, Postfix moves on the the next mail exchanger. Specify
|
||||
# "smtp_skip_4xx_greeting = no" if Postfix should defer delivery
|
||||
# immediately.
|
||||
#
|
||||
smtp_skip_4xx_greeting = yes
|
||||
|
||||
# The smtp_skip_5xx_greeting parameter controls what happens when
|
||||
# an SMTP server greets us with a 5XX status code (go away, do not
|
||||
# try again later).
|
||||
#
|
||||
# By default, Postfix moves on the the next mail exchanger. Specify
|
||||
# "smtp_skip_5xx_greeting = no" if Postfix should bounce the mail
|
||||
# immediately.
|
||||
#
|
||||
smtp_skip_5xx_greeting = yes
|
||||
|
||||
# The smtp_skip_quit_response parameter controls whether the SMTP
|
||||
# client waits for the response to the QUIT command. The default is
|
||||
# to not wait.
|
||||
#
|
||||
smtp_skip_quit_response = yes
|
||||
|
||||
# The strict_rfc821_envelopes configuration parameter controls whether
|
||||
# the Postfix SMTP server requires that MAIL FROM and RCPT TO addresses
|
||||
# are specified within <>, and that MAIL FROM and RCPT TO addresses
|
||||
# do not contain RFC822-style comments or phrases. It's great to
|
||||
# stop SPAM mailers. But it also trips up broken peecee clients.
|
||||
#
|
||||
# By default, Postfix SMTPD allows RFC822 syntax in MAIL FROM and RCPT TO.
|
||||
#
|
||||
strict_rfc821_envelopes = no
|
@@ -66,11 +66,24 @@ smtp_never_send_ehlo = no
|
||||
#smtp_bind_address=111.222.333.444
|
||||
|
||||
# The smtp_skip_4xx_greeting parameter controls what happens when
|
||||
# an SMTP server greets us with a 4XX status code. By default, Postfix
|
||||
# backs off. Specify "smtp_skip_4xx_greeting = yes" to move on the
|
||||
# the next mail exchanger.
|
||||
#
|
||||
smtp_skip_4xx_greeting = no
|
||||
# an SMTP server greets us with a 4XX status code (go away, try
|
||||
# again later).
|
||||
#
|
||||
# By default, Postfix moves on the the next mail exchanger. Specify
|
||||
# "smtp_skip_4xx_greeting = no" if Postfix should defer delivery
|
||||
# immediately.
|
||||
#
|
||||
smtp_skip_4xx_greeting = yes
|
||||
|
||||
# The smtp_skip_5xx_greeting parameter controls what happens when
|
||||
# an SMTP server greets us with a 5XX status code (go away, do not
|
||||
# try again later).
|
||||
#
|
||||
# By default, Postfix moves on the the next mail exchanger. Specify
|
||||
# "smtp_skip_5xx_greeting = no" if Postfix should bounce the mail
|
||||
# immediately.
|
||||
#
|
||||
smtp_skip_5xx_greeting = yes
|
||||
|
||||
# The smtp_skip_quit_response parameter controls whether the SMTP
|
||||
# client waits for the response to the QUIT command. The default is
|
||||
|
@@ -63,6 +63,16 @@ smtpd_recipient_limit = 1000
|
||||
#
|
||||
smtpd_timeout = 300s
|
||||
|
||||
# The strict_rfc821_envelopes configuration parameter controls whether
|
||||
# the Postfix SMTP server requires that MAIL FROM and RCPT TO addresses
|
||||
# are specified within <>, and that MAIL FROM and RCPT TO addresses
|
||||
# do not contain RFC822-style comments or phrases. It's great to
|
||||
# stop SPAM mailers. But it also trips up broken peecee clients.
|
||||
#
|
||||
# By default, Postfix SMTPD allows RFC822 syntax in MAIL FROM and RCPT TO.
|
||||
#
|
||||
strict_rfc821_envelopes = no
|
||||
|
||||
#
|
||||
# TARPIT CONTROLS
|
||||
#
|
||||
|
@@ -1,9 +1,14 @@
|
||||
#! /bin/sh
|
||||
|
||||
# LINUX2 - shell script to set up a Postfix chroot jail for Linux
|
||||
# Tested on SuSE Linux 5.3 (libc5) and 6.4 (glibc2.1)
|
||||
# Tested on SuSE Linux 5.3 (libc5) and 7.0 (glibc2.1)
|
||||
|
||||
# Copyright (c) 2000 by Matthias Andree
|
||||
# Other testers reported as working:
|
||||
#
|
||||
# 2001-01-15 Debian sid (unstable)
|
||||
# Christian Kurz <shorty@getuid.de>
|
||||
|
||||
# Copyright (c) 2000 - 2001 by Matthias Andree
|
||||
# Redistributable unter the MIT-style license that follows:
|
||||
# Abstract: "do whatever you want except hold somebody liable or change
|
||||
# the copyright information".
|
||||
@@ -26,14 +31,29 @@
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
# 2000-09-29
|
||||
# v0.1: initial release
|
||||
|
||||
# 2000-12-05
|
||||
# v0.2: copy libdb.* for libnss_db.so
|
||||
# remove /etc/localtime in case it's a broken symlink
|
||||
# restrict find to maxdepth 1 (faster)
|
||||
|
||||
# $Log: LINUX2,v $
|
||||
# Revision 1.4 2001/01/15 09:36:35 emma
|
||||
# add note it was successfully tested on Debian sid
|
||||
#
|
||||
|
||||
CP="cp -p"
|
||||
|
||||
cond_copy() {
|
||||
# find files as per pattern in $1
|
||||
# if any, copy to directory $2
|
||||
dir=`dirname "$1"`
|
||||
pat=`basename "$1"`
|
||||
lr=`find "$dir" -name "$pat"`
|
||||
lr=`find "$dir" -maxdepth 1 -name "$pat"`
|
||||
if test ! -d "$2" ; then exit 1 ; fi
|
||||
if test "x$lr" != "x" ; then cp -p $1 "$2" ; fi
|
||||
if test "x$lr" != "x" ; then $CP $1 "$2" ; fi
|
||||
}
|
||||
|
||||
set -e
|
||||
@@ -47,10 +67,18 @@ mkdir -p etc lib usr/lib/zoneinfo
|
||||
# find localtime (SuSE 5.3 does not have /etc/localtime)
|
||||
lt=/etc/localtime
|
||||
if test ! -f $lt ; then lt=/usr/lib/zoneinfo/localtime ; fi
|
||||
if test ! -f $lt ; then lt=/usr/share/zoneinfo/localtime ; fi
|
||||
if test ! -f $lt ; then echo "cannot find localtime" ; exit 1 ; fi
|
||||
cp -p -f $lt /etc/services /etc/resolv.conf /etc/nsswitch.conf etc
|
||||
cp -p -f /etc/host.conf /etc/hosts /etc/passwd etc
|
||||
rm -f etc/localtime
|
||||
|
||||
# copy localtime and some other system files into the chroot's etc
|
||||
$CP -f $lt /etc/services /etc/resolv.conf /etc/nsswitch.conf etc
|
||||
$CP -f /etc/host.conf /etc/hosts /etc/passwd etc
|
||||
ln -s -f /etc/localtime usr/lib/zoneinfo
|
||||
|
||||
cond_copy '/lib/libnss_*' lib
|
||||
cond_copy '/lib/libresolv*' lib
|
||||
# copy required libraries into the chroot
|
||||
cond_copy '/lib/libnss_*.so*' lib
|
||||
cond_copy '/lib/libresolv.so*' lib
|
||||
cond_copy '/lib/libdb.so*' lib
|
||||
|
||||
postfix reload
|
||||
|
@@ -5,7 +5,7 @@ SHELL = /bin/sh
|
||||
DAEMONS = bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
|
||||
lmtp.8.html master.8.html pickup.8.html pipe.8.html qmgr.8.html \
|
||||
showq.8.html smtp.8.html smtpd.8.html trivial-rewrite.8.html \
|
||||
nqmgr.8.html spawn.8.html flush.8.html virtual.8.html
|
||||
nqmgr.8.html spawn.8.html flush.8.html
|
||||
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
|
||||
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
|
||||
postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
|
||||
@@ -81,9 +81,6 @@ smtpd.8.html: ../src/smtpd/smtpd.c
|
||||
trivial-rewrite.8.html: ../src/trivial-rewrite/trivial-rewrite.c
|
||||
srctoman $? | nroff -man | man2html | postlink >$@
|
||||
|
||||
virtual.8.html: ../src/virtual/virtual.c
|
||||
srctoman $? | nroff -man | man2html | postlink >$@
|
||||
|
||||
postalias.1.html: ../src/postalias/postalias.c
|
||||
srctoman $? | nroff -man | man2html | postlink >$@
|
||||
|
||||
|
@@ -73,6 +73,7 @@ LMTP(8) LMTP(8)
|
||||
|
||||
<a href="http://www.faqs.org/rfcs/rfc2033.html">RFC 2033</a> (LMTP protocol)
|
||||
<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)
|
||||
|
||||
<b>DIAGNOSTICS</b>
|
||||
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
|
||||
@@ -119,12 +120,11 @@ LMTP(8) LMTP(8)
|
||||
server. Used as backup if the <b>lmtp</b> service is not
|
||||
found in <b>services</b>(4).
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>lmtp</b><i>_</i><b>cache</b><i>_</i><b>connection</b>
|
||||
Should we cache the connection to the LMTP server?
|
||||
The effectiveness of cached connections will be
|
||||
determined by the number of LMTP servers in use,
|
||||
and the concurrency limit specified for the LMTP
|
||||
<b>Authentication</b> <b>controls</b>
|
||||
<b>lmtp</b><i>_</i><b>enable</b><i>_</i><b>sasl</b><i>_</i><b>auth</b>
|
||||
Enable per-session authentication as per <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a>
|
||||
(SASL). By default, Postfix is built without SASL
|
||||
support.
|
||||
|
||||
|
||||
|
||||
@@ -137,6 +137,35 @@ LMTP(8) LMTP(8)
|
||||
LMTP(8) LMTP(8)
|
||||
|
||||
|
||||
<b>lmtp</b><i>_</i><b>sasl</b><i>_</i><b>password</b><i>_</i><b>maps</b>
|
||||
Lookup tables with per-host or domain <i>name</i>:<i>password</i>
|
||||
entries. No entry for a host means no attempt to
|
||||
authenticate.
|
||||
|
||||
<b>lmtp</b><i>_</i><b>sasl</b><i>_</i><b>security</b><i>_</i><b>options</b>
|
||||
Zero or more of the following.
|
||||
|
||||
<b>noplaintext</b>
|
||||
Disallow authentication methods that use
|
||||
plaintext passwords.
|
||||
|
||||
<b>noactive</b>
|
||||
Disallow authentication methods that are
|
||||
vulnerable to non-dictionary active attacks.
|
||||
|
||||
<b>nodictionary</b>
|
||||
Disallow authentication methods that are
|
||||
vulnerable to passive dictionary attack.
|
||||
|
||||
<b>noanonymous</b>
|
||||
Disallow anonymous logins.
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>lmtp</b><i>_</i><b>cache</b><i>_</i><b>connection</b>
|
||||
Should we cache the connection to the LMTP server?
|
||||
The effectiveness of cached connections will be
|
||||
determined by the number of LMTP servers in use,
|
||||
and the concurrency limit specified for the LMTP
|
||||
client. Cached connections are closed under any of
|
||||
the following conditions:
|
||||
|
||||
@@ -162,6 +191,18 @@ LMTP(8) LMTP(8)
|
||||
destination via this mail delivery transport.
|
||||
<i>transport</i> is the name of the service as specified
|
||||
in the <b>master.cf</b> file. The default limit is taken
|
||||
|
||||
|
||||
|
||||
3
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LMTP(8) LMTP(8)
|
||||
|
||||
|
||||
from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
|
||||
parameter.
|
||||
|
||||
@@ -192,17 +233,6 @@ LMTP(8) LMTP(8)
|
||||
value: s (seconds), m (minutes), h (hours), d (days) or w
|
||||
(weeks).
|
||||
|
||||
|
||||
|
||||
3
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LMTP(8) LMTP(8)
|
||||
|
||||
|
||||
<b>lmtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
|
||||
Timeout for opening a connection to the LMTP
|
||||
server. If no connection can be made within the
|
||||
@@ -227,6 +257,18 @@ LMTP(8) LMTP(8)
|
||||
<b>lmtp</b><i>_</i><b>data</b><i>_</i><b>xfer</b><i>_</i><b>timeout</b>
|
||||
Timeout for sending the message content.
|
||||
|
||||
|
||||
|
||||
|
||||
4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LMTP(8) LMTP(8)
|
||||
|
||||
|
||||
<b>lmtp</b><i>_</i><b>data</b><i>_</i><b>done</b><i>_</i><b>timeout</b>
|
||||
Timeout for sending the "<b>.</b>" command, and for
|
||||
receiving the server response. When no response is
|
||||
@@ -257,18 +299,6 @@ LMTP(8) LMTP(8)
|
||||
<b>AUTHOR(S)</b>
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
|
||||
|
||||
|
||||
4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LMTP(8) LMTP(8)
|
||||
|
||||
|
||||
P.O. Box 704
|
||||
Yorktown Heights, NY 10598, USA
|
||||
|
||||
@@ -296,36 +326,6 @@ LMTP(8) LMTP(8)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5
|
||||
|
||||
|
||||
|
@@ -77,6 +77,11 @@ SMTPD(8) SMTPD(8)
|
||||
For example, allow <a href="http://www.faqs.org/rfcs/rfc822.html">RFC822</a>-style address forms with
|
||||
comments, like Sendmail does.
|
||||
|
||||
<b>allow</b><i>_</i><b>broken</b><i>_</i><b>auth</b><i>_</i><b>clients</b>
|
||||
Support older Microsoft clients that mis-implement
|
||||
the AUTH protocol, and that expect an EHLO response
|
||||
of "250 AUTH=list" instead of "250 AUTH list".
|
||||
|
||||
<b>Content</b> <b>inspection</b> <b>controls</b>
|
||||
<b>content</b><i>_</i><b>filter</b>
|
||||
The name of a mail delivery transport that filters
|
||||
@@ -119,11 +124,6 @@ SMTPD(8) SMTPD(8)
|
||||
Location of Postfix support commands (default:
|
||||
<b>$program</b><i>_</i><b>directory</b>).
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
|
||||
Increment in verbose logging level when a remote
|
||||
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
parameter.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -137,6 +137,11 @@ SMTPD(8) SMTPD(8)
|
||||
SMTPD(8) SMTPD(8)
|
||||
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
|
||||
Increment in verbose logging level when a remote
|
||||
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
parameter.
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
List of domain or network patterns. When a remote
|
||||
host matches a pattern, increase the verbose log-
|
||||
@@ -186,11 +191,6 @@ SMTPD(8) SMTPD(8)
|
||||
reject responses. This can be useful for testing
|
||||
purposes.
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
|
||||
Limit the amount of memory in bytes used for the
|
||||
handling of partial input lines.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -203,6 +203,11 @@ SMTPD(8) SMTPD(8)
|
||||
SMTPD(8) SMTPD(8)
|
||||
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
|
||||
Limit the amount of memory in bytes used for the
|
||||
handling of partial input lines.
|
||||
|
||||
<b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
||||
Limit the total size in bytes of a message, includ-
|
||||
ing on-disk storage for envelope information.
|
||||
@@ -253,11 +258,6 @@ SMTPD(8) SMTPD(8)
|
||||
Restrict what recipient addresses are allowed in
|
||||
<b>RCPT</b> <b>TO</b> commands.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
|
||||
Restrict what domain names can be used in <b>ETRN</b> com-
|
||||
mands, and what clients may issue <b>ETRN</b> commands.
|
||||
|
||||
|
||||
|
||||
|
||||
4
|
||||
@@ -269,6 +269,10 @@ SMTPD(8) SMTPD(8)
|
||||
SMTPD(8) SMTPD(8)
|
||||
|
||||
|
||||
<b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
|
||||
Restrict what domain names can be used in <b>ETRN</b> com-
|
||||
mands, and what clients may issue <b>ETRN</b> commands.
|
||||
|
||||
<b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b>
|
||||
Allow untrusted clients to specify addresses with
|
||||
sender-specified routing. Enabling this opens up
|
||||
@@ -319,10 +323,6 @@ SMTPD(8) SMTPD(8)
|
||||
name mapping violates the <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
|
||||
restriction.
|
||||
|
||||
<b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
Server response when a client violates the
|
||||
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -335,6 +335,10 @@ SMTPD(8) SMTPD(8)
|
||||
SMTPD(8) SMTPD(8)
|
||||
|
||||
|
||||
<b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
Server response when a client violates the
|
||||
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
<a href="cleanup.8.html">cleanup(8)</a> message canonicalization
|
||||
<a href="master.8.html">master(8)</a> process manager
|
||||
@@ -383,10 +387,6 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,266 +0,0 @@
|
||||
<html> <head> </head> <body> <pre>
|
||||
|
||||
|
||||
|
||||
VIRTUAL(8) VIRTUAL(8)
|
||||
|
||||
|
||||
<b>NAME</b>
|
||||
virtual - Postfix virtual domain mail delivery agent
|
||||
|
||||
<b>SYNOPSIS</b>
|
||||
<b>virtual</b> [generic Postfix daemon options]
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
This daemon is designed for ISP's offering virtual mail
|
||||
hosting services. Originally based on the local delivery
|
||||
agent, this agent locates user mailboxes via map lookups
|
||||
of the full recipient address, rather than hard-coded unix
|
||||
password file searches of the local part only.
|
||||
|
||||
The <b>virtual</b> daemon processes delivery requests from the
|
||||
Postfix queue manager to deliver mail to virtual local
|
||||
recipients. Each delivery request specifies a queue file,
|
||||
a sender address, a domain or host to deliver to, and one
|
||||
or more recipients. This program expects to be run from
|
||||
the <a href="master.8.html"><b>master</b>(8)</a> process manager.
|
||||
|
||||
The <b>virtual</b> daemon updates queue files and marks recipi-
|
||||
ents as finished, or it informs the queue manager that
|
||||
delivery should be tried again at a later time. Delivery
|
||||
problem reports are sent to the <a href="bounce.8.html"><b>bounce</b>(8)</a> or <a href="defer.8.html"><b>defer</b>(8)</a> dae-
|
||||
mon as appropriate.
|
||||
|
||||
<b>MAILBOX</b> <b>DELIVERY</b>
|
||||
The <b>virtual</b> delivery agent can deliver to UNIX-style mail-
|
||||
box file or to qmail-style maildir files. The pathname and
|
||||
delivery mailbox style are controlled by the <b>virtual</b><i>_</i><b>mail-</b>
|
||||
<b>box</b><i>_</i><b>base</b> and <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>maps</b> configuration parameters
|
||||
(see below).
|
||||
|
||||
In the case of UNIX-style mailbox delivery, the <b>local</b> dae-
|
||||
mon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope header to
|
||||
each message, prepends a <b>Delivered-To:</b> header with the
|
||||
envelope recipient address, prepends a <b>Return-Path:</b> header
|
||||
with the envelope sender address, prepends a > character
|
||||
to lines beginning with "<b>From</b> ", and appends an empty
|
||||
line. The mailbox is locked for exclusive access while
|
||||
delivery is in progress. In case of problems, an attempt
|
||||
is made to truncate the mailbox to its original length.
|
||||
|
||||
In the case of <b>maildir</b> delivery, the local daemon prepends
|
||||
a <b>Delivered-To:</b> header with the envelope recipient address
|
||||
and prepends a <b>Return-Path:</b> header with the envelope
|
||||
sender address.
|
||||
|
||||
<b>DELIVERY</b> <b>RIGHTS</b>
|
||||
Deliveries are made with the user and group privileges
|
||||
that are listed in the tables specified with the <b>vir-</b>
|
||||
<b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> and <b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b>, respectively.
|
||||
|
||||
The <b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b> parameter specifies a lower bound
|
||||
|
||||
|
||||
|
||||
1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VIRTUAL(8) VIRTUAL(8)
|
||||
|
||||
|
||||
on user ID values that may be specified in <b>vir-</b>
|
||||
<b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>. Mail will not be delivered when a too low
|
||||
UID value is found.
|
||||
|
||||
<b>STANDARDS</b>
|
||||
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
|
||||
|
||||
<b>DIAGNOSTICS</b>
|
||||
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
|
||||
rupted message files are marked so that the queue manager
|
||||
can move them to the <b>corrupt</b> queue afterwards.
|
||||
|
||||
Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
|
||||
the postmaster is notified of bounces and of other trou-
|
||||
ble.
|
||||
|
||||
<b>CONFIGURATION</b> <b>PARAMETERS</b>
|
||||
The following <b>main.cf</b> parameters are especially relevant
|
||||
to this program. See the Postfix <b>main.cf</b> file for syntax
|
||||
details and for default values. Use the <b>postfix</b> <b>reload</b>
|
||||
command after a configuration change.
|
||||
|
||||
<b>Mailbox</b> <b>delivery</b>
|
||||
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>base</b>
|
||||
Specifies a path that is prepended to all mailbox
|
||||
or maildir paths. This is a safety measure to
|
||||
ensure that an out of control map in <b>virtual</b><i>_</i><b>mail-</b>
|
||||
<b>box</b><i>_</i><b>maps</b> doesn't litter the filesystem with mail-
|
||||
boxes. While it could be set to "/", this setting
|
||||
isn't recommended.
|
||||
|
||||
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>maps</b>
|
||||
Recipients are looked up in this map to determine
|
||||
the path to their mailbox or maildir. If the
|
||||
returned path ends in a slash ("/"), maildir-style
|
||||
delivery is carried out, otherwise the path is
|
||||
assumed to specify a mailbox file.
|
||||
|
||||
Note that <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>base</b> is unconditionally
|
||||
prepended to this path.
|
||||
|
||||
<b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b>
|
||||
Specifies a minimum uid that will be accepted as a
|
||||
return from a <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup. Returned
|
||||
values less than this will be rejected, and the
|
||||
message will be deferred.
|
||||
|
||||
<b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
|
||||
Recipients are looked up in this map to determine
|
||||
the UID to be used when writing to the target mail-
|
||||
box.
|
||||
|
||||
<b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b>
|
||||
Recipients are looked up in this map to determine
|
||||
|
||||
|
||||
|
||||
2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VIRTUAL(8) VIRTUAL(8)
|
||||
|
||||
|
||||
the GID to be used when writing to the target mail-
|
||||
box.
|
||||
|
||||
<b>Locking</b> <b>controls</b>
|
||||
<b>mailbox</b><i>_</i><b>delivery</b><i>_</i><b>lock</b>
|
||||
How to lock UNIX-style mailboxes: one or more of
|
||||
<b>flock</b>, <b>fcntl</b> or <b>dotlock</b>.
|
||||
|
||||
Use the command <b>postconf</b> <b>-m</b> to find out what lock-
|
||||
ing methods are available on your system.
|
||||
|
||||
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
|
||||
Limit the number of attempts to acquire an exclu-
|
||||
sive lock on a mailbox file.
|
||||
|
||||
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
|
||||
Time (default: seconds) between successive attempts
|
||||
to acquire an exclusive lock on a mailbox file.
|
||||
|
||||
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
|
||||
Limit the time after which a stale lockfile is
|
||||
removed.
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>virtual</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
|
||||
Limit the number of parallel deliveries to the same
|
||||
domain. The default limit is taken from the
|
||||
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
|
||||
|
||||
<b>virtual</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
||||
Limit the number of recipients per message deliv-
|
||||
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>HISTORY</b>
|
||||
This agent was originally based on the local delivery
|
||||
agent. Modifications mainly consisted of removing code
|
||||
that wasn't applicable or wasn't safe in this context
|
||||
(aliases, .forwards, program aliases).
|
||||
|
||||
The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
|
||||
Daniel Bernstein.
|
||||
|
||||
The <i>maildir</i> structure appears in the <b>qmail</b> system by
|
||||
Daniel Bernstein.
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
<a href="bounce.8.html">bounce(8)</a> non-delivery status reports
|
||||
syslogd(8) system logging
|
||||
<a href="qmgr.8.html">qmgr(8)</a> queue manager
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
|
||||
|
||||
3
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VIRTUAL(8) VIRTUAL(8)
|
||||
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
P.O. Box 704
|
||||
Yorktown Heights, NY 10598, USA
|
||||
|
||||
Andrew McNamara
|
||||
andrewm@connect.com.au
|
||||
connect.com.au Pty. Ltd.
|
||||
Level 3, 213 Miller St
|
||||
North Sydney 2060, NSW, Australia
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4
|
||||
|
||||
|
||||
</pre> </body> </html>
|
@@ -5,7 +5,7 @@ SHELL = /bin/sh
|
||||
DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \
|
||||
man8/lmtp.8 man8/master.8 man8/pickup.8 man8/pipe.8 man8/qmgr.8 \
|
||||
man8/showq.8 man8/smtp.8 man8/smtpd.8 man8/trivial-rewrite.8 \
|
||||
man8/nqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8
|
||||
man8/nqmgr.8 man8/spawn.8 man8/flush.8
|
||||
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
|
||||
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
|
||||
man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
|
||||
@@ -80,9 +80,6 @@ man8/smtpd.8: ../src/smtpd/smtpd.c
|
||||
man8/trivial-rewrite.8: ../src/trivial-rewrite/trivial-rewrite.c
|
||||
../mantools/srctoman $? >$@
|
||||
|
||||
man8/virtual.8: ../src/virtual/virtual.c
|
||||
../mantools/srctoman $? >$@
|
||||
|
||||
man1/postalias.1: ../src/postalias/postalias.c
|
||||
../mantools/srctoman $? >$@
|
||||
|
||||
|
@@ -59,6 +59,7 @@ RFC 1651 (SMTP service extensions)
|
||||
RFC 1870 (Message Size Declaration)
|
||||
RFC 2033 (LMTP protocol)
|
||||
RFC 2197 (Pipelining)
|
||||
RFC 2554 (AUTH command)
|
||||
.SH DIAGNOSTICS
|
||||
.ad
|
||||
.fi
|
||||
@@ -101,6 +102,27 @@ Do not wait for the server response after sending QUIT.
|
||||
.IP \fBlmtp_tcp_port\fR
|
||||
The TCP port to be used when connecting to a LMTP server. Used as
|
||||
backup if the \fBlmtp\fR service is not found in \fBservices\fR(4).
|
||||
.SH "Authentication controls"
|
||||
.IP \fBlmtp_enable_sasl_auth\fR
|
||||
Enable per-session authentication as per RFC 2554 (SASL).
|
||||
By default, Postfix is built without SASL support.
|
||||
.IP \fBlmtp_sasl_password_maps\fR
|
||||
Lookup tables with per-host or domain \fIname\fR:\fIpassword\fR entries.
|
||||
No entry for a host means no attempt to authenticate.
|
||||
.IP \fBlmtp_sasl_security_options\fR
|
||||
Zero or more of the following.
|
||||
.RS
|
||||
.IP \fBnoplaintext\fR
|
||||
Disallow authentication methods that use plaintext passwords.
|
||||
.IP \fBnoactive\fR
|
||||
Disallow authentication methods that are vulnerable to non-dictionary
|
||||
active attacks.
|
||||
.IP \fBnodictionary\fR
|
||||
Disallow authentication methods that are vulnerable to passive
|
||||
dictionary attack.
|
||||
.IP \fBnoanonymous\fR
|
||||
Disallow anonymous logins.
|
||||
.RE
|
||||
.SH "Resource controls"
|
||||
.ad
|
||||
.fi
|
||||
|
@@ -71,6 +71,10 @@ a configuration change.
|
||||
.IP \fBstrict_rfc821_envelopes\fR
|
||||
Disallow non-RFC 821 style addresses in envelopes. For example,
|
||||
allow RFC822-style address forms with comments, like Sendmail does.
|
||||
.IP \fBallow_broken_auth_clients\fR
|
||||
Support older Microsoft clients that mis-implement the AUTH
|
||||
protocol, and that expect an EHLO response of "250 AUTH=list"
|
||||
instead of "250 AUTH list".
|
||||
.SH "Content inspection controls"
|
||||
.IP \fBcontent_filter\fR
|
||||
The name of a mail delivery transport that filters mail and that
|
||||
|
@@ -1,183 +0,0 @@
|
||||
.TH VIRTUAL 8
|
||||
.ad
|
||||
.fi
|
||||
.SH NAME
|
||||
virtual
|
||||
\-
|
||||
Postfix virtual domain mail delivery agent
|
||||
.SH SYNOPSIS
|
||||
.na
|
||||
.nf
|
||||
\fBvirtual\fR [generic Postfix daemon options]
|
||||
.SH DESCRIPTION
|
||||
.ad
|
||||
.fi
|
||||
This daemon is designed for ISP's offering virtual mail hosting
|
||||
services. Originally based on the local delivery agent, this agent
|
||||
locates user mailboxes via map lookups of the full recipient
|
||||
address, rather than hard-coded unix password file searches of
|
||||
the local part only.
|
||||
|
||||
The \fBvirtual\fR daemon processes delivery requests from the
|
||||
Postfix queue manager to deliver mail to virtual local recipients.
|
||||
Each delivery request specifies a queue file, a sender address,
|
||||
a domain or host to deliver to, and one or more recipients.
|
||||
This program expects to be run from the \fBmaster\fR(8) process
|
||||
manager.
|
||||
|
||||
The \fBvirtual\fR daemon updates queue files and marks recipients
|
||||
as finished, or it informs the queue manager that delivery should
|
||||
be tried again at a later time. Delivery problem reports are sent
|
||||
to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
|
||||
.SH MAILBOX DELIVERY
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The \fBvirtual\fR delivery agent can deliver to UNIX-style mailbox
|
||||
file or to qmail-style maildir files. The pathname and delivery
|
||||
mailbox style are controlled by the \fBvirtual_mailbox_base\fR
|
||||
and \fBvirtual_mailbox_maps\fR configuration parameters (see below).
|
||||
|
||||
In the case of UNIX-style mailbox delivery,
|
||||
the \fBlocal\fR daemon prepends a "\fBFrom \fIsender time_stamp\fR"
|
||||
envelope header to each message, prepends a \fBDelivered-To:\fR header
|
||||
with the envelope recipient address, prepends a \fBReturn-Path:\fR
|
||||
header with the envelope sender address, prepends a \fB>\fR character
|
||||
to lines beginning with "\fBFrom \fR", and appends an empty line.
|
||||
The mailbox is locked for exclusive access while delivery is in
|
||||
progress. In case of problems, an attempt is made to truncate the
|
||||
mailbox to its original length.
|
||||
|
||||
In the case of \fBmaildir\fR delivery, the local daemon prepends
|
||||
a \fBDelivered-To:\fR header with the envelope recipient address
|
||||
and prepends a \fBReturn-Path:\fR header with the envelope sender
|
||||
address.
|
||||
.SH DELIVERY RIGHTS
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
Deliveries are made with the user and group privileges that are
|
||||
listed in the tables specified with the \fBvirtual_uid_maps\fR
|
||||
and \fBvirtual_gid_maps\fR, respectively.
|
||||
|
||||
The \fBvirtual_minimum_uid\fR parameter specifies a lower bound on
|
||||
user ID values that may be specified in \fBvirtual_uid_maps\fR. Mail
|
||||
will not be delivered when a too low UID value is found.
|
||||
.SH STANDARDS
|
||||
.na
|
||||
.nf
|
||||
RFC 822 (ARPA Internet Text Messages)
|
||||
.SH DIAGNOSTICS
|
||||
.ad
|
||||
.fi
|
||||
Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
Corrupted message files are marked so that the queue
|
||||
manager can move them to the \fBcorrupt\fR queue afterwards.
|
||||
|
||||
Depending on the setting of the \fBnotify_classes\fR parameter,
|
||||
the postmaster is notified of bounces and of other trouble.
|
||||
.SH CONFIGURATION PARAMETERS
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The following \fBmain.cf\fR parameters are especially relevant to
|
||||
this program. See the Postfix \fBmain.cf\fR file for syntax details
|
||||
and for default values. Use the \fBpostfix reload\fR command after
|
||||
a configuration change.
|
||||
.SH Mailbox delivery
|
||||
.ad
|
||||
.fi
|
||||
.IP \fBvirtual_mailbox_base\fR
|
||||
Specifies a path that is prepended to all mailbox or maildir paths.
|
||||
This is a safety measure to ensure that an out of control map in
|
||||
\fBvirtual_mailbox_maps\fR doesn't litter the filesystem with mailboxes.
|
||||
While it could be set to "/", this setting isn't recommended.
|
||||
.IP \fBvirtual_mailbox_maps\fR
|
||||
Recipients are looked up in this map to determine the path to
|
||||
their mailbox or maildir. If the returned path ends in a slash
|
||||
("/"), maildir-style delivery is carried out, otherwise the
|
||||
path is assumed to specify a mailbox file.
|
||||
|
||||
Note that \fBvirtual_mailbox_base\fR is unconditionally prepended
|
||||
to this path.
|
||||
.IP \fBvirtual_minimum_uid\fR
|
||||
Specifies a minimum uid that will be accepted as a return from
|
||||
a \fBvirtual_uid_maps\fR lookup. Returned values less than this
|
||||
will be rejected, and the message will be deferred.
|
||||
.IP \fBvirtual_uid_maps\fR
|
||||
Recipients are looked up in this map to determine the UID to be
|
||||
used when writing to the target mailbox.
|
||||
.IP \fBvirtual_gid_maps\fR
|
||||
Recipients are looked up in this map to determine the GID to be
|
||||
used when writing to the target mailbox.
|
||||
.SH "Locking controls"
|
||||
.ad
|
||||
.fi
|
||||
.IP \fBmailbox_delivery_lock\fR
|
||||
How to lock UNIX-style mailboxes: one or more of \fBflock\fR,
|
||||
\fBfcntl\fR or \fBdotlock\fR.
|
||||
|
||||
Use the command \fBpostconf -m\fR to find out what locking methods
|
||||
are available on your system.
|
||||
.IP \fBdeliver_lock_attempts\fR
|
||||
Limit the number of attempts to acquire an exclusive lock
|
||||
on a mailbox file.
|
||||
.IP \fBdeliver_lock_delay\fR
|
||||
Time (default: seconds) between successive attempts to acquire
|
||||
an exclusive lock on a mailbox file.
|
||||
.IP \fBstale_lock_time\fR
|
||||
Limit the time after which a stale lockfile is removed.
|
||||
.SH "Resource controls"
|
||||
.ad
|
||||
.fi
|
||||
.IP \fBvirtual_destination_concurrency_limit\fR
|
||||
Limit the number of parallel deliveries to the same domain.
|
||||
The default limit is taken from the
|
||||
\fBdefault_destination_concurrency_limit\fR parameter.
|
||||
.IP \fBvirtual_destination_recipient_limit\fR
|
||||
Limit the number of recipients per message delivery.
|
||||
The default limit is taken from the
|
||||
\fBdefault_destination_recipient_limit\fR parameter.
|
||||
.SH HISTORY
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
This agent was originally based on the local delivery
|
||||
agent. Modifications mainly consisted of removing code that wasn't
|
||||
applicable or wasn't safe in this context (aliases, .forwards,
|
||||
program aliases).
|
||||
|
||||
The \fBDelivered-To:\fR header appears in the \fBqmail\fR system
|
||||
by Daniel Bernstein.
|
||||
|
||||
The \fImaildir\fR structure appears in the \fBqmail\fR system
|
||||
by Daniel Bernstein.
|
||||
.SH SEE ALSO
|
||||
.na
|
||||
.nf
|
||||
bounce(8) non-delivery status reports
|
||||
syslogd(8) system logging
|
||||
qmgr(8) queue manager
|
||||
.SH LICENSE
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The Secure Mailer license must be distributed with this software.
|
||||
.SH AUTHOR(S)
|
||||
.na
|
||||
.nf
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
P.O. Box 704
|
||||
Yorktown Heights, NY 10598, USA
|
||||
|
||||
Andrew McNamara
|
||||
andrewm@connect.com.au
|
||||
connect.com.au Pty. Ltd.
|
||||
Level 3, 213 Miller St
|
||||
North Sydney 2060, NSW, Australia
|
1
postfix/src/base64/.indent.pro
vendored
1
postfix/src/base64/.indent.pro
vendored
@@ -1 +0,0 @@
|
||||
../../.indent.pro
|
@@ -1,79 +0,0 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = base64encode.c base64decode.c
|
||||
OBJS = base64encode.o base64decode.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
INC_DIR = ../../include
|
||||
PROG = base64encode base64decode
|
||||
LIBS = ../../lib/libglobal.a ../../lib/libutil.a
|
||||
|
||||
.c.o:; $(CC) $(CFLAGS) -c $*.c
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
Makefile: Makefile.in
|
||||
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
|
||||
|
||||
base64decode: base64decode.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ base64decode.o $(LIBS) $(SYSLIBS)
|
||||
|
||||
base64encode: base64encode.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ base64encode.o $(LIBS) $(SYSLIBS)
|
||||
|
||||
test: $(TESTPROG)
|
||||
|
||||
update: ../../bin/base64encode ../../bin/base64decode
|
||||
|
||||
../../bin/base64encode: base64encode
|
||||
cp $? $@
|
||||
|
||||
../../bin/base64decode: base64decode
|
||||
cp $? $@
|
||||
|
||||
printfck: $(OBJS) $(PROG)
|
||||
rm -rf printfck
|
||||
mkdir printfck
|
||||
sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
|
||||
set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
|
||||
cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
|
||||
|
||||
lint:
|
||||
lint $(DEFS) $(SRCS) $(LINTFIX)
|
||||
|
||||
clean:
|
||||
rm -f *.o *core $(PROG) $(TESTPROG) junk
|
||||
rm -rf printfck
|
||||
|
||||
tidy: clean
|
||||
|
||||
depend: $(MAKES)
|
||||
(sed '1,/^# do not edit/!d' Makefile.in; \
|
||||
set -e; for i in [a-z][a-z0-9]*.c; do \
|
||||
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
|
||||
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
|
||||
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
|
||||
@$(EXPORT) make -f Makefile.in Makefile 1>&2
|
||||
|
||||
# do not edit below this line - it is generated by 'make depend'
|
||||
base64decode.o: base64decode.c
|
||||
base64decode.o: ../../include/sys_defs.h
|
||||
base64decode.o: ../../include/vstring.h
|
||||
base64decode.o: ../../include/vbuf.h
|
||||
base64decode.o: ../../include/vstream.h
|
||||
base64decode.o: ../../include/vstring_vstream.h
|
||||
base64decode.o: ../../include/msg.h
|
||||
base64decode.o: ../../include/msg_vstream.h
|
||||
base64encode.o: base64encode.c
|
||||
base64encode.o: ../../include/sys_defs.h
|
||||
base64encode.o: ../../include/vstring.h
|
||||
base64encode.o: ../../include/vbuf.h
|
||||
base64encode.o: ../../include/vstream.h
|
||||
base64encode.o: ../../include/vstring_vstream.h
|
||||
base64encode.o: ../../include/msg.h
|
||||
base64encode.o: ../../include/msg_vstream.h
|
@@ -1,63 +0,0 @@
|
||||
/* base64decode - transform base 64 data to printable form */
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* SASL library. */
|
||||
|
||||
#include <sasl.h>
|
||||
#include <saslutil.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <vstring.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring_vstream.h>
|
||||
#include <msg.h>
|
||||
#include <msg_vstream.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
#define UCHAR(x) ((unsigned char *) (x))
|
||||
|
||||
static VSTRING *escape(VSTRING *escaped, char *input, int len)
|
||||
{
|
||||
char *cp;
|
||||
unsigned ch;
|
||||
|
||||
VSTRING_RESET(escaped);
|
||||
for (cp = input; cp < input + len; cp++) {
|
||||
ch = *UCHAR(cp);
|
||||
if (ISASCII(ch) && ISPRINT(ch))
|
||||
VSTRING_ADDCH(escaped, ch);
|
||||
else
|
||||
vstring_sprintf_append(escaped, "\\%03o", ch);
|
||||
}
|
||||
VSTRING_TERMINATE(escaped);
|
||||
return (escaped);
|
||||
}
|
||||
|
||||
int main(int unused_argc, char **argv)
|
||||
{
|
||||
VSTRING *input = vstring_alloc(100);
|
||||
VSTRING *escaped = vstring_alloc(100);
|
||||
VSTRING *result = vstring_alloc(100);
|
||||
int len;
|
||||
|
||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||
|
||||
while (vstring_get_nonl(input, VSTREAM_IN) != VSTREAM_EOF) {
|
||||
VSTRING_SPACE(result, LEN(input));
|
||||
if (sasl_decode64(STR(input), LEN(input),
|
||||
STR(result), &len) != SASL_OK)
|
||||
msg_fatal("malformed input");
|
||||
vstream_printf("%s\n", STR(escape(escaped, STR(result), len)));
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
}
|
||||
return (0);
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
/* base64encode - transform printable form to base 64 data */
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* SASL library. */
|
||||
|
||||
#include <sasl.h>
|
||||
#include <saslutil.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <vstring.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring_vstream.h>
|
||||
#include <msg.h>
|
||||
#include <msg_vstream.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
#define UCHAR(x) ((unsigned char *) (x))
|
||||
|
||||
static VSTRING *unescape(VSTRING *unescaped, VSTRING *input)
|
||||
{
|
||||
char *cp = STR(input);
|
||||
int ch;
|
||||
int oval;
|
||||
int i;
|
||||
|
||||
VSTRING_RESET(unescaped);
|
||||
while ((ch = *UCHAR(cp++)) != 0) {
|
||||
switch (ch) {
|
||||
case '\\':
|
||||
for (oval = 0, i = 0; i < 3 && (ch = *UCHAR(cp)) != 0; i++) {
|
||||
if (!ISDIGIT(ch) || ch == '8' || ch == '9')
|
||||
break;
|
||||
oval = (oval << 3) | (ch - '0');
|
||||
cp++;
|
||||
}
|
||||
VSTRING_ADDCH(unescaped, oval);
|
||||
break;
|
||||
default:
|
||||
VSTRING_ADDCH(unescaped, ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
VSTRING_TERMINATE(unescaped);
|
||||
return (unescaped);
|
||||
}
|
||||
|
||||
int main(int unused_argc, char **argv)
|
||||
{
|
||||
VSTRING *input = vstring_alloc(100);
|
||||
VSTRING *unescaped = vstring_alloc(100);
|
||||
VSTRING *result = vstring_alloc(100);
|
||||
int result_len;
|
||||
int len;
|
||||
|
||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||
|
||||
while (vstring_get_nonl(input, VSTREAM_IN) != VSTREAM_EOF) {
|
||||
unescape(unescaped, input);
|
||||
result_len = ((LEN(unescaped) + 2) / 3) * 4 + 1;
|
||||
VSTRING_SPACE(result, result_len);
|
||||
if (sasl_encode64(STR(unescaped), LEN(unescaped), STR(result),
|
||||
result_len, &len) != SASL_OK)
|
||||
msg_panic("sasl_encode64 botch");
|
||||
vstream_printf("%.*s\n", len, STR(result));
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
}
|
||||
return (0);
|
||||
}
|
@@ -339,10 +339,10 @@ int bounce_boilerplate(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
|
||||
"####################################################################");
|
||||
post_mail_fputs(bounce, "");
|
||||
post_mail_fprintf(bounce,
|
||||
"Your message could not be delivered for %.1g hours.",
|
||||
"Your message could not be delivered for %.1f hours.",
|
||||
var_delay_warn_time / 3600.0);
|
||||
post_mail_fprintf(bounce,
|
||||
"It will be retried until it is %.1g days old.",
|
||||
"It will be retried until it is %.1f days old.",
|
||||
var_max_queue_time / 86400.0);
|
||||
}
|
||||
|
||||
|
@@ -428,13 +428,6 @@ header_opts.o: header_opts.h
|
||||
is_header.o: is_header.c
|
||||
is_header.o: ../../include/sys_defs.h
|
||||
is_header.o: is_header.h
|
||||
local_transport.o: local_transport.c
|
||||
local_transport.o: ../../include/sys_defs.h
|
||||
local_transport.o: ../../include/msg.h
|
||||
local_transport.o: ../../include/mymalloc.h
|
||||
local_transport.o: string_list.h
|
||||
local_transport.o: mail_params.h
|
||||
local_transport.o: local_transport.h
|
||||
mail_addr.o: mail_addr.c
|
||||
mail_addr.o: ../../include/sys_defs.h
|
||||
mail_addr.o: ../../include/stringops.h
|
||||
|
@@ -237,6 +237,14 @@ extern char *var_rcpt_witheld;
|
||||
#define DEF_STRICT_RFC821_ENV 0
|
||||
extern bool var_strict_rfc821_env;
|
||||
|
||||
/*
|
||||
* Standards violation: send "250 AUTH=list" in order to accomodate broken
|
||||
* Microsoft clients.
|
||||
*/
|
||||
#define VAR_BROKEN_AUTH_CLNTS "allow_broken_auth_clients"
|
||||
#define DEF_BROKEN_AUTH_CLNTS 0
|
||||
extern bool var_broken_auth_clients;
|
||||
|
||||
/*
|
||||
* Standards violation: disable VRFY.
|
||||
*/
|
||||
@@ -712,7 +720,7 @@ extern int var_smtpd_err_sleep;
|
||||
extern int var_smtpd_junk_cmd_limit;
|
||||
|
||||
/*
|
||||
* SASL authentication support, server side.
|
||||
* SASL authentication support, SMTP server side.
|
||||
*/
|
||||
#define VAR_SMTPD_SASL_ENABLE "smtpd_sasl_auth_enable"
|
||||
#define DEF_SMTPD_SASL_ENABLE 0
|
||||
@@ -727,7 +735,7 @@ extern char *var_smtpd_sasl_opts;
|
||||
extern char *var_smtpd_sasl_realm;
|
||||
|
||||
/*
|
||||
* SASL authentication support, client side.
|
||||
* SASL authentication support, SMTP client side.
|
||||
*/
|
||||
#define VAR_SMTP_SASL_ENABLE "smtp_sasl_auth_enable"
|
||||
#define DEF_SMTP_SASL_ENABLE 0
|
||||
@@ -741,6 +749,24 @@ extern char *var_smtp_sasl_passwd;
|
||||
#define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous"
|
||||
extern char *var_smtp_sasl_opts;
|
||||
|
||||
/*
|
||||
* SASL authentication support, LMTP client side.
|
||||
*/
|
||||
#define VAR_LMTP_SASL_ENABLE "lmtp_sasl_auth_enable"
|
||||
#define DEF_LMTP_SASL_ENABLE 0
|
||||
extern bool var_lmtp_sasl_enable;
|
||||
|
||||
#define VAR_LMTP_SASL_PASSWD "lmtp_sasl_password_maps"
|
||||
#define DEF_LMTP_SASL_PASSWD ""
|
||||
extern char *var_lmtp_sasl_passwd;
|
||||
|
||||
#define VAR_LMTP_SASL_OPTS "lmtp_sasl_security_options"
|
||||
#define DEF_LMTP_SASL_OPTS "noplaintext, noanonymous"
|
||||
extern char *var_lmtp_sasl_opts;
|
||||
|
||||
/*
|
||||
* SASL-based relay etc. control.
|
||||
*/
|
||||
#define PERMIT_SASL_AUTH "permit_sasl_authenticated"
|
||||
|
||||
/*
|
||||
@@ -862,7 +888,7 @@ extern int var_fork_delay;
|
||||
* When locking a mailbox, how often to try and how long to wait.
|
||||
*/
|
||||
#define VAR_FLOCK_TRIES "deliver_lock_attempts"
|
||||
#define DEF_FLOCK_TRIES 5
|
||||
#define DEF_FLOCK_TRIES 10
|
||||
extern int var_flock_tries;
|
||||
|
||||
#define VAR_FLOCK_DELAY "deliver_lock_delay"
|
||||
@@ -1110,18 +1136,23 @@ extern char *var_export_environ;
|
||||
#define VAR_VIRT_MAILBOX_MAPS "virtual_mailbox_maps"
|
||||
#define DEF_VIRT_MAILBOX_MAPS ""
|
||||
extern char *var_mailbox_maps;
|
||||
|
||||
#define VAR_VIRT_UID_MAPS "virtual_uid_maps"
|
||||
#define DEF_VIRT_UID_MAPS ""
|
||||
extern char *var_uid_maps;
|
||||
|
||||
#define VAR_VIRT_GID_MAPS "virtual_gid_maps"
|
||||
#define DEF_VIRT_GID_MAPS ""
|
||||
extern char *var_gid_maps;
|
||||
|
||||
#define VAR_VIRT_USEDOTLOCK "virtual_usedotlock"
|
||||
#define DEF_VIRT_USEDOTLOCK 0
|
||||
extern bool var_virt_usedotlock;
|
||||
|
||||
#define VAR_VIRT_MINUID "virtual_minimum_uid"
|
||||
#define DEF_VIRT_MINUID 100
|
||||
extern int var_virt_minimum_uid;
|
||||
extern int var_virt_minimum_uid;
|
||||
|
||||
#define VAR_VIRT_MAILBOX_BASE "virtual_mailbox_base"
|
||||
#define DEF_VIRT_MAILBOX_BASE ""
|
||||
extern char *var_virt_mailbox_base;
|
||||
|
@@ -415,7 +415,8 @@ VSTREAM *mail_queue_open(const char *queue_name, const char *queue_id,
|
||||
* missing subdirectory.
|
||||
*/
|
||||
if ((fp = vstream_fopen(path, flags, mode)) == 0)
|
||||
if ((flags & O_CREAT) == O_CREAT && mail_queue_mkdirs(path) == 0)
|
||||
fp = vstream_fopen(path, flags, mode);
|
||||
if (errno == ENOENT)
|
||||
if ((flags & O_CREAT) == O_CREAT && mail_queue_mkdirs(path) == 0)
|
||||
fp = vstream_fopen(path, flags, mode);
|
||||
return (fp);
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20010105"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20010122"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
@@ -1,8 +1,10 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = lmtp.c lmtp_connect.c lmtp_proto.c lmtp_chat.c lmtp_session.c \
|
||||
lmtp_addr.c lmtp_trouble.c lmtp_state.c
|
||||
lmtp_addr.c lmtp_trouble.c lmtp_state.c lmtp_sasl_glue.c \
|
||||
lmtp_sasl_proto.c
|
||||
OBJS = lmtp.o lmtp_connect.o lmtp_proto.o lmtp_chat.o lmtp_session.o \
|
||||
lmtp_addr.o lmtp_trouble.o lmtp_state.o
|
||||
lmtp_addr.o lmtp_trouble.o lmtp_state.o lmtp_sasl_glue.o \
|
||||
lmtp_sasl_proto.o
|
||||
HDRS = lmtp.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
@@ -79,6 +81,7 @@ lmtp.o: ../../include/debug_peer.h
|
||||
lmtp.o: ../../include/mail_error.h
|
||||
lmtp.o: ../../include/mail_server.h
|
||||
lmtp.o: lmtp.h
|
||||
lmtp.o: lmtp_sasl.h
|
||||
lmtp_addr.o: lmtp_addr.c
|
||||
lmtp_addr.o: ../../include/sys_defs.h
|
||||
lmtp_addr.o: ../../include/msg.h
|
||||
@@ -113,6 +116,8 @@ lmtp_chat.o: ../../include/mail_params.h
|
||||
lmtp_chat.o: ../../include/mail_addr.h
|
||||
lmtp_chat.o: ../../include/post_mail.h
|
||||
lmtp_chat.o: ../../include/cleanup_user.h
|
||||
lmtp_chat.o: ../../include/mail_error.h
|
||||
lmtp_chat.o: ../../include/name_mask.h
|
||||
lmtp_chat.o: lmtp.h
|
||||
lmtp_connect.o: lmtp_connect.c
|
||||
lmtp_connect.o: ../../include/sys_defs.h
|
||||
@@ -155,9 +160,42 @@ lmtp_proto.o: ../../include/record.h
|
||||
lmtp_proto.o: ../../include/rec_type.h
|
||||
lmtp_proto.o: ../../include/off_cvt.h
|
||||
lmtp_proto.o: ../../include/mark_corrupt.h
|
||||
lmtp_proto.o: ../../include/quote_821_local.h
|
||||
lmtp_proto.o: lmtp.h
|
||||
lmtp_proto.o: ../../include/argv.h
|
||||
lmtp_proto.o: ../../include/quote_821_local.h
|
||||
lmtp_proto.o: lmtp_sasl.h
|
||||
lmtp_sasl_glue.o: lmtp_sasl_glue.c
|
||||
lmtp_sasl_glue.o: ../../include/sys_defs.h
|
||||
lmtp_sasl_glue.o: ../../include/msg.h
|
||||
lmtp_sasl_glue.o: ../../include/mymalloc.h
|
||||
lmtp_sasl_glue.o: ../../include/stringops.h
|
||||
lmtp_sasl_glue.o: ../../include/vstring.h
|
||||
lmtp_sasl_glue.o: ../../include/vbuf.h
|
||||
lmtp_sasl_glue.o: ../../include/split_at.h
|
||||
lmtp_sasl_glue.o: ../../include/name_mask.h
|
||||
lmtp_sasl_glue.o: ../../include/mail_params.h
|
||||
lmtp_sasl_glue.o: ../../include/string_list.h
|
||||
lmtp_sasl_glue.o: ../../include/maps.h
|
||||
lmtp_sasl_glue.o: ../../include/dict.h
|
||||
lmtp_sasl_glue.o: ../../include/vstream.h
|
||||
lmtp_sasl_glue.o: ../../include/argv.h
|
||||
lmtp_sasl_glue.o: lmtp.h
|
||||
lmtp_sasl_glue.o: ../../include/deliver_request.h
|
||||
lmtp_sasl_glue.o: ../../include/recipient_list.h
|
||||
lmtp_sasl_glue.o: lmtp_sasl.h
|
||||
lmtp_sasl_proto.o: lmtp_sasl_proto.c
|
||||
lmtp_sasl_proto.o: ../../include/sys_defs.h
|
||||
lmtp_sasl_proto.o: ../../include/msg.h
|
||||
lmtp_sasl_proto.o: ../../include/mymalloc.h
|
||||
lmtp_sasl_proto.o: ../../include/mail_params.h
|
||||
lmtp_sasl_proto.o: lmtp.h
|
||||
lmtp_sasl_proto.o: ../../include/vstream.h
|
||||
lmtp_sasl_proto.o: ../../include/vbuf.h
|
||||
lmtp_sasl_proto.o: ../../include/vstring.h
|
||||
lmtp_sasl_proto.o: ../../include/argv.h
|
||||
lmtp_sasl_proto.o: ../../include/deliver_request.h
|
||||
lmtp_sasl_proto.o: ../../include/recipient_list.h
|
||||
lmtp_sasl_proto.o: lmtp_sasl.h
|
||||
lmtp_session.o: lmtp_session.c
|
||||
lmtp_session.o: ../../include/sys_defs.h
|
||||
lmtp_session.o: ../../include/mymalloc.h
|
||||
@@ -176,12 +214,12 @@ lmtp_state.o: ../../include/mymalloc.h
|
||||
lmtp_state.o: ../../include/vstring.h
|
||||
lmtp_state.o: ../../include/vbuf.h
|
||||
lmtp_state.o: ../../include/vstream.h
|
||||
lmtp_state.o: ../../include/config.h
|
||||
lmtp_state.o: ../../include/mail_conf.h
|
||||
lmtp_state.o: lmtp.h
|
||||
lmtp_state.o: ../../include/argv.h
|
||||
lmtp_state.o: ../../include/deliver_request.h
|
||||
lmtp_state.o: ../../include/recipient_list.h
|
||||
lmtp_state.o: lmtp_sasl.h
|
||||
lmtp_trouble.o: lmtp_trouble.c
|
||||
lmtp_trouble.o: ../../include/sys_defs.h
|
||||
lmtp_trouble.o: ../../include/msg.h
|
||||
|
@@ -49,6 +49,7 @@
|
||||
/* RFC 1870 (Message Size Declaration)
|
||||
/* RFC 2033 (LMTP protocol)
|
||||
/* RFC 2197 (Pipelining)
|
||||
/* RFC 2554 (AUTH command)
|
||||
/* DIAGNOSTICS
|
||||
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
/* Corrupted message files are marked so that the queue manager can
|
||||
@@ -85,6 +86,27 @@
|
||||
/* .IP \fBlmtp_tcp_port\fR
|
||||
/* The TCP port to be used when connecting to a LMTP server. Used as
|
||||
/* backup if the \fBlmtp\fR service is not found in \fBservices\fR(4).
|
||||
/* .SH "Authentication controls"
|
||||
/* .IP \fBlmtp_enable_sasl_auth\fR
|
||||
/* Enable per-session authentication as per RFC 2554 (SASL).
|
||||
/* By default, Postfix is built without SASL support.
|
||||
/* .IP \fBlmtp_sasl_password_maps\fR
|
||||
/* Lookup tables with per-host or domain \fIname\fR:\fIpassword\fR entries.
|
||||
/* No entry for a host means no attempt to authenticate.
|
||||
/* .IP \fBlmtp_sasl_security_options\fR
|
||||
/* Zero or more of the following.
|
||||
/* .RS
|
||||
/* .IP \fBnoplaintext\fR
|
||||
/* Disallow authentication methods that use plaintext passwords.
|
||||
/* .IP \fBnoactive\fR
|
||||
/* Disallow authentication methods that are vulnerable to non-dictionary
|
||||
/* active attacks.
|
||||
/* .IP \fBnodictionary\fR
|
||||
/* Disallow authentication methods that are vulnerable to passive
|
||||
/* dictionary attack.
|
||||
/* .IP \fBnoanonymous\fR
|
||||
/* Disallow anonymous logins.
|
||||
/* .RE
|
||||
/* .SH "Resource controls"
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -231,6 +253,7 @@
|
||||
/* Application-specific. */
|
||||
|
||||
#include "lmtp.h"
|
||||
#include "lmtp_sasl.h"
|
||||
|
||||
/*
|
||||
* Tunable parameters. These have compiled-in defaults that can be overruled
|
||||
@@ -252,6 +275,9 @@ int var_lmtp_cache_conn;
|
||||
int var_lmtp_skip_quit_resp;
|
||||
char *var_notify_classes;
|
||||
char *var_error_rcpt;
|
||||
char *var_lmtp_sasl_opts;
|
||||
char *var_lmtp_sasl_passwd;
|
||||
bool var_lmtp_sasl_enable;
|
||||
|
||||
/*
|
||||
* Global variables.
|
||||
@@ -432,6 +458,10 @@ static void post_init(char *unused_name, char **unused_argv)
|
||||
static void pre_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
debug_peer_init();
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_lmtp_sasl_enable)
|
||||
lmtp_sasl_initialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* cleanup - close any open connections, etc. */
|
||||
@@ -446,6 +476,10 @@ static void cleanup(void)
|
||||
msg_info("cleanup: just closed down session");
|
||||
}
|
||||
lmtp_state_free(state);
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_lmtp_sasl_enable)
|
||||
sasl_done();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* pre_accept - see if tables have changed */
|
||||
@@ -467,6 +501,8 @@ int main(int argc, char **argv)
|
||||
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
|
||||
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
||||
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
|
||||
VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_lmtp_sasl_passwd, 0, 0,
|
||||
VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_lmtp_sasl_opts, 0, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_INT_TABLE int_table[] = {
|
||||
|
@@ -8,6 +8,14 @@
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* SASL library.
|
||||
*/
|
||||
#ifdef USE_SASL_AUTH
|
||||
#include <sasl.h>
|
||||
#include <saslutil.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
@@ -35,6 +43,15 @@ typedef struct LMTP_STATE {
|
||||
int features; /* server features */
|
||||
ARGV *history; /* transaction log */
|
||||
int error_mask; /* error classes */
|
||||
#ifdef USE_SASL_AUTH
|
||||
char *sasl_mechanism_list; /* server mechanism list */
|
||||
char *sasl_username; /* client username */
|
||||
char *sasl_passwd; /* client password */
|
||||
sasl_conn_t *sasl_conn; /* SASL internal state */
|
||||
VSTRING *sasl_encoded; /* encoding buffer */
|
||||
VSTRING *sasl_decoded; /* decoding buffer */
|
||||
sasl_callback_t *sasl_callbacks; /* stateful callbacks */
|
||||
#endif
|
||||
int sndbufsize; /* total window size */
|
||||
int sndbuffree; /* remaining window */
|
||||
int reuse; /* connection being reused */
|
||||
@@ -44,6 +61,7 @@ typedef struct LMTP_STATE {
|
||||
#define LMTP_FEATURE_8BITMIME (1<<1)
|
||||
#define LMTP_FEATURE_PIPELINING (1<<2)
|
||||
#define LMTP_FEATURE_SIZE (1<<3)
|
||||
#define SMTP_FEATURE_AUTH (1<<5)
|
||||
|
||||
/*
|
||||
* lmtp.c
|
||||
|
@@ -104,6 +104,7 @@
|
||||
#include <mail_params.h>
|
||||
#include <mail_addr.h>
|
||||
#include <post_mail.h>
|
||||
#include <mail_error.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -172,7 +173,6 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state)
|
||||
{
|
||||
LMTP_SESSION *session = state->session;
|
||||
static LMTP_RESP rdata;
|
||||
int more;
|
||||
char *cp;
|
||||
int last_char;
|
||||
|
||||
@@ -190,17 +190,12 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state)
|
||||
VSTRING_RESET(rdata.buf);
|
||||
for (;;) {
|
||||
last_char = smtp_get(state->buffer, session->stream, var_line_limit);
|
||||
cp = printable(STR(state->buffer), '?');
|
||||
printable(STR(state->buffer), '?');
|
||||
if (last_char != '\n')
|
||||
msg_warn("%s: response longer than %d: %.30s...",
|
||||
session->namaddr, var_line_limit, cp);
|
||||
session->namaddr, var_line_limit, STR(state->buffer));
|
||||
if (msg_verbose)
|
||||
msg_info("< %s: %s", session->namaddr, cp);
|
||||
while (ISDIGIT(*cp))
|
||||
cp++;
|
||||
rdata.code = (cp - STR(state->buffer) == 3 ?
|
||||
atoi(STR(state->buffer)) : 0);
|
||||
more = (*cp == '-');
|
||||
msg_info("< %s: %s", session->namaddr, STR(state->buffer));
|
||||
|
||||
/*
|
||||
* Defend against a denial of service attack by limiting the amount
|
||||
@@ -212,13 +207,23 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state)
|
||||
vstring_strcat(rdata.buf, STR(state->buffer));
|
||||
lmtp_chat_append(state, "In: ", STR(state->buffer));
|
||||
}
|
||||
if (VSTRING_LEN(state->buffer) == 0) /* XXX remote brain damage */
|
||||
continue;
|
||||
if (!ISDIGIT(STR(state->buffer)[0])) /* XXX remote brain damage */
|
||||
continue;
|
||||
if (more == 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Parse into code and text. Ignore unrecognized garbage. This means
|
||||
* that any character except space (or end of line) will have the
|
||||
* same effect as the '-' line continuation character.
|
||||
*/
|
||||
for (cp = STR(state->buffer); *cp && ISDIGIT(*cp); cp++)
|
||||
/* void */ ;
|
||||
if (cp - STR(state->buffer) == 3) {
|
||||
if (*cp == '-')
|
||||
continue;
|
||||
if (*cp == ' ' || *cp == 0)
|
||||
break;
|
||||
}
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
}
|
||||
rdata.code = atoi(STR(state->buffer));
|
||||
VSTRING_TERMINATE(rdata.buf);
|
||||
rdata.str = STR(rdata.buf);
|
||||
return (&rdata);
|
||||
|
@@ -116,11 +116,12 @@
|
||||
#include <rec_type.h>
|
||||
#include <off_cvt.h>
|
||||
#include <mark_corrupt.h>
|
||||
#include <quote_821_local.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "lmtp.h"
|
||||
#include "quote_821_local.h"
|
||||
#include "lmtp_sasl.h"
|
||||
|
||||
/*
|
||||
* Sender and receiver state. A session does not necessarily go through a
|
||||
@@ -193,7 +194,7 @@ int lmtp_lhlo(LMTP_STATE *state)
|
||||
*/
|
||||
if (((resp = lmtp_chat_resp(state))->code / 100) != 2)
|
||||
return (lmtp_site_fail(state, resp->code,
|
||||
"%s refused to talk to me: %s",
|
||||
"host %s refused to talk to me: %s",
|
||||
session->namaddr, translit(resp->str, "\n", " ")));
|
||||
|
||||
/*
|
||||
@@ -202,7 +203,7 @@ int lmtp_lhlo(LMTP_STATE *state)
|
||||
lmtp_chat_cmd(state, "LHLO %s", var_myhostname);
|
||||
if ((resp = lmtp_chat_resp(state))->code / 100 != 2)
|
||||
return (lmtp_site_fail(state, resp->code,
|
||||
"%s refused to talk to me: %s",
|
||||
"host %s refused to talk to me: %s",
|
||||
session->namaddr,
|
||||
translit(resp->str, "\n", " ")));
|
||||
|
||||
@@ -223,11 +224,20 @@ int lmtp_lhlo(LMTP_STATE *state)
|
||||
state->features |= LMTP_FEATURE_PIPELINING;
|
||||
else if (strcasecmp(word, "SIZE") == 0)
|
||||
state->features |= LMTP_FEATURE_SIZE;
|
||||
#ifdef USE_SASL_AUTH
|
||||
else if (var_lmtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
|
||||
lmtp_sasl_helo_auth(state, words);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("server features: 0x%x", state->features);
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_lmtp_sasl_enable && (state->features & SMTP_FEATURE_AUTH))
|
||||
return (lmtp_sasl_helo_login(state));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use LMTP command pipelining if the server said it supported it.
|
||||
* Since we use blocking I/O, RFC 2197 says that we should inspect the
|
||||
@@ -463,7 +473,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
case LMTP_STATE_MAIL:
|
||||
if (resp->code / 100 != 2) {
|
||||
lmtp_mesg_fail(state, resp->code,
|
||||
"%s said: %s", session->namaddr,
|
||||
"host %s said: %s", session->namaddr,
|
||||
translit(resp->str, "\n", " "));
|
||||
mail_from_rejected = 1;
|
||||
}
|
||||
@@ -487,7 +497,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
survivors[nrcpt++] = recv_rcpt;
|
||||
} else {
|
||||
lmtp_rcpt_fail(state, resp->code, rcpt,
|
||||
"%s said: %s", session->namaddr,
|
||||
"host %s said: %s", session->namaddr,
|
||||
translit(resp->str, "\n", " "));
|
||||
rcpt->offset = 0; /* in case deferred */
|
||||
}
|
||||
@@ -505,7 +515,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
if (resp->code / 100 != 3) {
|
||||
if (nrcpt > 0)
|
||||
lmtp_mesg_fail(state, resp->code,
|
||||
"%s said: %s", session->namaddr,
|
||||
"host %s said: %s", session->namaddr,
|
||||
translit(resp->str, "\n", " "));
|
||||
nrcpt = -1;
|
||||
}
|
||||
@@ -535,7 +545,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
}
|
||||
} else {
|
||||
lmtp_rcpt_fail(state, resp->code, rcpt,
|
||||
"%s said: %s", session->namaddr,
|
||||
"host %s said: %s", session->namaddr,
|
||||
translit(resp->str, "\n", " "));
|
||||
rcpt->offset = 0; /* in case deferred */
|
||||
}
|
||||
|
39
postfix/src/lmtp/lmtp_sasl.h
Normal file
39
postfix/src/lmtp/lmtp_sasl.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* lmtp_sasl 3h
|
||||
/* SUMMARY
|
||||
/* Postfix SASL interface for LMTP client
|
||||
/* SYNOPSIS
|
||||
/* #include "lmtp_sasl.h"
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* SASL protocol functions
|
||||
*/
|
||||
extern void lmtp_sasl_initialize(void);
|
||||
extern void lmtp_sasl_connect(LMTP_STATE *);
|
||||
extern int lmtp_sasl_passwd_lookup(LMTP_STATE *);
|
||||
extern void lmtp_sasl_start(LMTP_STATE *);
|
||||
extern int lmtp_sasl_authenticate(LMTP_STATE *, VSTRING *);
|
||||
extern void lmtp_sasl_cleanup(LMTP_STATE *);
|
||||
|
||||
extern void lmtp_sasl_helo_auth(LMTP_STATE *, const char *);
|
||||
extern int lmtp_sasl_helo_login(LMTP_STATE *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Initial implementation by:
|
||||
/* Till Franke
|
||||
/* SuSE Rhein/Main AG
|
||||
/* 65760 Eschborn, Germany
|
||||
/*
|
||||
/* Adopted by:
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
512
postfix/src/lmtp/lmtp_sasl_glue.c
Normal file
512
postfix/src/lmtp/lmtp_sasl_glue.c
Normal file
@@ -0,0 +1,512 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* lmtp_sasl 3
|
||||
/* SUMMARY
|
||||
/* Postfix SASL interface for LMTP client
|
||||
/* SYNOPSIS
|
||||
/* #include lmtp_sasl.h
|
||||
/*
|
||||
/* void lmtp_sasl_initialize()
|
||||
/*
|
||||
/* void lmtp_sasl_connect(state)
|
||||
/* LMTP_STATE *state;
|
||||
/*
|
||||
/* void lmtp_sasl_start(state)
|
||||
/* LMTP_STATE *state;
|
||||
/*
|
||||
/* int lmtp_sasl_passwd_lookup(state)
|
||||
/* LMTP_STATE *state;
|
||||
/*
|
||||
/* int lmtp_sasl_authenticate(state, why)
|
||||
/* LMTP_STATE *state;
|
||||
/* VSTRING *why;
|
||||
/*
|
||||
/* void lmtp_sasl_cleanup(state)
|
||||
/* LMTP_STATE *state;
|
||||
/* DESCRIPTION
|
||||
/* lmtp_sasl_initialize() initializes the SASL library. This
|
||||
/* routine must be called once at process startup, before any
|
||||
/* chroot operations.
|
||||
/*
|
||||
/* lmtp_sasl_connect() performs per-session initialization. This
|
||||
/* routine must be called once at the start of each connection.
|
||||
/*
|
||||
/* lmtp_sasl_start() performs per-session initialization. This
|
||||
/* routine must be called once per session before doing any SASL
|
||||
/* authentication.
|
||||
/*
|
||||
/* lmtp_sasl_passwd_lookup() looks up the username/password
|
||||
/* for the current SMTP server. The result is zero in case
|
||||
/* of failure.
|
||||
/*
|
||||
/* lmtp_sasl_authenticate() implements the SASL authentication
|
||||
/* dialog. The result is < 0 in case of protocol failure, zero in
|
||||
/* case of unsuccessful authentication, > 0 in case of success.
|
||||
/* The why argument is updated with a reason for failure.
|
||||
/* This routine must be called only when lmtp_sasl_passwd_lookup()
|
||||
/* suceeds.
|
||||
/*
|
||||
/* lmtp_sasl_cleanup() cleans up. It must be called at the
|
||||
/* end of every SMTP session that uses SASL authentication.
|
||||
/* This routine is a noop for non-SASL sessions.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
/* Session context.
|
||||
/* .IP mech_list
|
||||
/* String of SASL mechanisms (separated by blanks)
|
||||
/* DIAGNOSTICS
|
||||
/* All errors are fatal.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Original author:
|
||||
/* Till Franke
|
||||
/* SuSE Rhein/Main AG
|
||||
/* 65760 Eschborn, Germany
|
||||
/*
|
||||
/* Adopted by:
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/*
|
||||
* System library.
|
||||
*/
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef STRCASECMP_IN_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility library
|
||||
*/
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <stringops.h>
|
||||
#include <split_at.h>
|
||||
#include <name_mask.h>
|
||||
|
||||
/*
|
||||
* Global library
|
||||
*/
|
||||
#include <mail_params.h>
|
||||
#include <string_list.h>
|
||||
#include <maps.h>
|
||||
|
||||
/*
|
||||
* Application-specific
|
||||
*/
|
||||
#include "lmtp.h"
|
||||
#include "lmtp_sasl.h"
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
|
||||
/*
|
||||
* Authentication security options.
|
||||
*/
|
||||
static NAME_MASK lmtp_sasl_sec_mask[] = {
|
||||
"noplaintext", SASL_SEC_NOPLAINTEXT,
|
||||
"noactive", SASL_SEC_NOACTIVE,
|
||||
"nodictionary", SASL_SEC_NODICTIONARY,
|
||||
"noanonymous", SASL_SEC_NOANONYMOUS,
|
||||
0,
|
||||
};
|
||||
|
||||
static int lmtp_sasl_sec_opts;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/*
|
||||
* Per-host login/password information.
|
||||
*/
|
||||
static MAPS *lmtp_sasl_passwd_map;
|
||||
|
||||
/* lmtp_sasl_log - logging call-back routine */
|
||||
|
||||
static int lmtp_sasl_log(void *unused_context, int priority,
|
||||
const char *message)
|
||||
{
|
||||
switch (priority) {
|
||||
case SASL_LOG_ERR:
|
||||
case SASL_LOG_WARNING:
|
||||
msg_warn("%s", message);
|
||||
break;
|
||||
case SASL_LOG_INFO:
|
||||
if (msg_verbose)
|
||||
msg_info("%s", message);
|
||||
break;
|
||||
}
|
||||
return (SASL_OK);
|
||||
}
|
||||
|
||||
/* lmtp_sasl_get_user - username lookup call-back routine */
|
||||
|
||||
static int lmtp_sasl_get_user(void *context, int unused_id, const char **result,
|
||||
unsigned *len)
|
||||
{
|
||||
char *myname = "lmtp_sasl_get_user";
|
||||
LMTP_STATE *state = (LMTP_STATE *) context;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s", myname, state->sasl_username);
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (state->sasl_passwd == 0)
|
||||
msg_panic("%s: no username looked up", myname);
|
||||
|
||||
*result = state->sasl_username;
|
||||
if (len)
|
||||
*len = strlen(state->sasl_username);
|
||||
return (SASL_OK);
|
||||
}
|
||||
|
||||
/* lmtp_sasl_get_passwd - password lookup call-back routine */
|
||||
|
||||
static int lmtp_sasl_get_passwd(sasl_conn_t *conn, void *context,
|
||||
int id, sasl_secret_t **psecret)
|
||||
{
|
||||
char *myname = "lmtp_sasl_get_passwd";
|
||||
LMTP_STATE *state = (LMTP_STATE *) context;
|
||||
int len;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s", myname, state->sasl_passwd);
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (!conn || !psecret || id != SASL_CB_PASS)
|
||||
return (SASL_BADPARAM);
|
||||
if (state->sasl_passwd == 0)
|
||||
msg_panic("%s: no password looked up", myname);
|
||||
|
||||
/*
|
||||
* Convert the password into a counted string.
|
||||
*/
|
||||
len = strlen(state->sasl_passwd);
|
||||
if ((*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len)) == 0)
|
||||
return (SASL_NOMEM);
|
||||
(*psecret)->len = len;
|
||||
memcpy((*psecret)->data, state->sasl_passwd, len + 1);
|
||||
|
||||
return (SASL_OK);
|
||||
}
|
||||
|
||||
/* lmtp_sasl_passwd_lookup - password lookup routine */
|
||||
|
||||
int lmtp_sasl_passwd_lookup(LMTP_STATE *state)
|
||||
{
|
||||
char *myname = "lmtp_sasl_passwd_lookup";
|
||||
const char *value;
|
||||
char *passwd;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (lmtp_sasl_passwd_map == 0)
|
||||
msg_panic("%s: passwd map not initialized", myname);
|
||||
|
||||
/*
|
||||
* Look up the per-server password information. Try the hostname first,
|
||||
* then try the destination.
|
||||
*/
|
||||
if ((value = maps_find(lmtp_sasl_passwd_map, state->session->host, 0)) != 0
|
||||
|| (value = maps_find(lmtp_sasl_passwd_map, state->request->nexthop, 0)) != 0) {
|
||||
state->sasl_username = mystrdup(value);
|
||||
passwd = split_at(state->sasl_username, ':');
|
||||
state->sasl_passwd = mystrdup(passwd ? passwd : "");
|
||||
if (msg_verbose)
|
||||
msg_info("%s: host `%s' user `%s' pass `%s'",
|
||||
myname, state->session->host,
|
||||
state->sasl_username, state->sasl_passwd);
|
||||
return (1);
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: host `%s' no auth info found",
|
||||
myname, state->session->host);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* lmtp_sasl_initialize - per-process initialization (pre jail) */
|
||||
|
||||
void lmtp_sasl_initialize(void)
|
||||
{
|
||||
|
||||
/*
|
||||
* Global callbacks. These have no per-session context.
|
||||
*/
|
||||
static sasl_callback_t callbacks[] = {
|
||||
{SASL_CB_LOG, &lmtp_sasl_log, 0},
|
||||
{SASL_CB_LIST_END, 0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (lmtp_sasl_passwd_map)
|
||||
msg_panic("lmtp_sasl_initialize: repeated call");
|
||||
if (*var_lmtp_sasl_passwd == 0)
|
||||
msg_fatal("specify a password table via the `%s' configuration parameter",
|
||||
VAR_LMTP_SASL_PASSWD);
|
||||
|
||||
/*
|
||||
* Open the per-host password table and initialize the SASL library. Use
|
||||
* shared locks for reading, just in case someone updates the table.
|
||||
*/
|
||||
lmtp_sasl_passwd_map = maps_create("lmtp_sasl_passwd",
|
||||
var_lmtp_sasl_passwd, DICT_FLAG_LOCK);
|
||||
if (sasl_client_init(callbacks) != SASL_OK)
|
||||
msg_fatal("SASL library initialization");
|
||||
|
||||
/*
|
||||
* Configuration parameters.
|
||||
*/
|
||||
lmtp_sasl_sec_opts = name_mask(VAR_LMTP_SASL_OPTS, lmtp_sasl_sec_mask,
|
||||
var_lmtp_sasl_opts);
|
||||
}
|
||||
|
||||
/* lmtp_sasl_connect - per-session client initialization */
|
||||
|
||||
void lmtp_sasl_connect(LMTP_STATE *state)
|
||||
{
|
||||
state->sasl_mechanism_list = 0;
|
||||
state->sasl_username = 0;
|
||||
state->sasl_passwd = 0;
|
||||
state->sasl_conn = 0;
|
||||
state->sasl_encoded = 0;
|
||||
state->sasl_decoded = 0;
|
||||
state->sasl_callbacks = 0;
|
||||
}
|
||||
|
||||
/* lmtp_sasl_start - per-session SASL initialization */
|
||||
|
||||
void lmtp_sasl_start(LMTP_STATE *state)
|
||||
{
|
||||
static sasl_callback_t callbacks[] = {
|
||||
{SASL_CB_USER, &lmtp_sasl_get_user, 0},
|
||||
{SASL_CB_AUTHNAME, &lmtp_sasl_get_user, 0},
|
||||
{SASL_CB_PASS, &lmtp_sasl_get_passwd, 0},
|
||||
{SASL_CB_LIST_END, 0, 0}
|
||||
};
|
||||
sasl_callback_t *cp;
|
||||
sasl_security_properties_t sec_props;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("starting new SASL client");
|
||||
|
||||
/*
|
||||
* Per-session initialization. Provide each session with its own callback
|
||||
* context.
|
||||
*/
|
||||
#define NULL_SECFLAGS 0
|
||||
|
||||
state->sasl_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks));
|
||||
memcpy((char *) state->sasl_callbacks, callbacks, sizeof(callbacks));
|
||||
for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++)
|
||||
cp->context = (void *) state;
|
||||
if (sasl_client_new("smtp", state->session->host,
|
||||
state->sasl_callbacks, NULL_SECFLAGS,
|
||||
(sasl_conn_t **) &state->sasl_conn) != SASL_OK)
|
||||
msg_fatal("per-session SASL client initialization");
|
||||
|
||||
/*
|
||||
* Per-session security properties. XXX This routine is not sufficiently
|
||||
* documented. What is the purpose of all this?
|
||||
*/
|
||||
memset(&sec_props, 0L, sizeof(sec_props));
|
||||
sec_props.min_ssf = 0;
|
||||
sec_props.max_ssf = 1; /* don't allow real SASL
|
||||
* security layer */
|
||||
sec_props.security_flags = lmtp_sasl_sec_opts;
|
||||
sec_props.maxbufsize = 0;
|
||||
sec_props.property_names = 0;
|
||||
sec_props.property_values = 0;
|
||||
if (sasl_setprop(state->sasl_conn, SASL_SEC_PROPS,
|
||||
&sec_props) != SASL_OK)
|
||||
msg_fatal("set per-session SASL security properties");
|
||||
|
||||
/*
|
||||
* We use long-lived conversion buffers rather than local variables in
|
||||
* order to avoid memory leaks in case of read/write timeout or I/O
|
||||
* error.
|
||||
*/
|
||||
state->sasl_encoded = vstring_alloc(10);
|
||||
state->sasl_decoded = vstring_alloc(10);
|
||||
}
|
||||
|
||||
/* lmtp_sasl_authenticate - run authentication protocol */
|
||||
|
||||
int lmtp_sasl_authenticate(LMTP_STATE *state, VSTRING *why)
|
||||
{
|
||||
char *myname = "lmtp_sasl_authenticate";
|
||||
unsigned enc_length;
|
||||
unsigned enc_length_out;
|
||||
char *clientout;
|
||||
unsigned clientoutlen;
|
||||
unsigned serverinlen;
|
||||
LMTP_RESP *resp;
|
||||
const char *mechanism;
|
||||
int result;
|
||||
char *line;
|
||||
|
||||
#define NO_SASL_SECRET 0
|
||||
#define NO_SASL_INTERACTION 0
|
||||
#define NO_SASL_LANGLIST ((const char *) 0)
|
||||
#define NO_SASL_OUTLANG ((const char **) 0)
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s: SASL mechanisms %s",
|
||||
myname, state->session->namaddr, state->sasl_mechanism_list);
|
||||
|
||||
/*
|
||||
* Start the client side authentication protocol.
|
||||
*/
|
||||
result = sasl_client_start((sasl_conn_t *) state->sasl_conn,
|
||||
state->sasl_mechanism_list,
|
||||
NO_SASL_SECRET, NO_SASL_INTERACTION,
|
||||
&clientout, &clientoutlen, &mechanism);
|
||||
if (result != SASL_OK && result != SASL_CONTINUE) {
|
||||
vstring_sprintf(why, "cannot SASL authenticate to server %s: %s",
|
||||
state->session->namaddr,
|
||||
sasl_errstring(result, NO_SASL_LANGLIST,
|
||||
NO_SASL_OUTLANG));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the AUTH command and the optional initial client response.
|
||||
* sasl_encode64() produces four bytes for each complete or incomplete
|
||||
* triple of input bytes. Allocate an extra byte for string termination.
|
||||
*/
|
||||
#define ENCODE64_LENGTH(n) ((((n) + 2) / 3) * 4)
|
||||
|
||||
if (clientoutlen > 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s: uncoded initial reply: %.*s",
|
||||
myname, state->session->namaddr,
|
||||
(int) clientoutlen, clientout);
|
||||
enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
|
||||
VSTRING_SPACE(state->sasl_encoded, enc_length);
|
||||
if (sasl_encode64(clientout, clientoutlen,
|
||||
STR(state->sasl_encoded), enc_length,
|
||||
&enc_length_out) != SASL_OK)
|
||||
msg_panic("%s: sasl_encode64 botch", myname);
|
||||
free(clientout);
|
||||
lmtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded));
|
||||
} else {
|
||||
lmtp_chat_cmd(state, "AUTH %s", mechanism);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step through the authentication protocol until the server tells us
|
||||
* that we are done.
|
||||
*/
|
||||
while ((resp = lmtp_chat_resp(state))->code / 100 == 3) {
|
||||
|
||||
/*
|
||||
* Process a server challenge.
|
||||
*/
|
||||
line = resp->str;
|
||||
(void) mystrtok(&line, "- \t\n"); /* skip over result code */
|
||||
serverinlen = strlen(line);
|
||||
VSTRING_SPACE(state->sasl_decoded, serverinlen);
|
||||
if (sasl_decode64(line, serverinlen,
|
||||
STR(state->sasl_decoded), &enc_length) != SASL_OK) {
|
||||
vstring_sprintf(why, "malformed SASL challenge from server %s",
|
||||
state->session->namaddr);
|
||||
return (-1);
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s: decoded challenge: %.*s",
|
||||
myname, state->session->namaddr,
|
||||
(int) enc_length, STR(state->sasl_decoded));
|
||||
result = sasl_client_step((sasl_conn_t *) state->sasl_conn,
|
||||
STR(state->sasl_decoded), enc_length,
|
||||
NO_SASL_INTERACTION, &clientout, &clientoutlen);
|
||||
if (result != SASL_OK && result != SASL_CONTINUE)
|
||||
msg_warn("SASL authentication failed to server %s: %s",
|
||||
state->session->namaddr,
|
||||
sasl_errstring(result, NO_SASL_LANGLIST,
|
||||
NO_SASL_OUTLANG));
|
||||
|
||||
/*
|
||||
* Send a client response.
|
||||
*/
|
||||
if (clientoutlen > 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s: uncoded client response %.*s",
|
||||
myname, state->session->namaddr,
|
||||
(int) clientoutlen, clientout);
|
||||
enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
|
||||
VSTRING_SPACE(state->sasl_encoded, enc_length);
|
||||
if (sasl_encode64(clientout, clientoutlen,
|
||||
STR(state->sasl_encoded), enc_length,
|
||||
&enc_length_out) != SASL_OK)
|
||||
msg_panic("%s: sasl_encode64 botch", myname);
|
||||
free(clientout);
|
||||
} else {
|
||||
vstring_strcat(state->sasl_encoded, "");
|
||||
}
|
||||
lmtp_chat_cmd(state, "%s", STR(state->sasl_encoded));
|
||||
}
|
||||
|
||||
/*
|
||||
* We completed the authentication protocol.
|
||||
*/
|
||||
if (resp->code / 100 != 2) {
|
||||
vstring_sprintf(why, "SASL authentication failed; server %s said: %s",
|
||||
state->session->namaddr, resp->str);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* lmtp_sasl_cleanup - per-session cleanup */
|
||||
|
||||
void lmtp_sasl_cleanup(LMTP_STATE *state)
|
||||
{
|
||||
if (state->sasl_username) {
|
||||
myfree(state->sasl_username);
|
||||
state->sasl_username = 0;
|
||||
}
|
||||
if (state->sasl_passwd) {
|
||||
myfree(state->sasl_passwd);
|
||||
state->sasl_passwd = 0;
|
||||
}
|
||||
if (state->sasl_mechanism_list) {
|
||||
myfree(state->sasl_mechanism_list); /* allocated in lmtp_helo */
|
||||
state->sasl_mechanism_list = 0;
|
||||
}
|
||||
if (state->sasl_conn) {
|
||||
if (msg_verbose)
|
||||
msg_info("disposing SASL state information");
|
||||
sasl_dispose(&state->sasl_conn);
|
||||
}
|
||||
if (state->sasl_callbacks) {
|
||||
myfree((char *) state->sasl_callbacks);
|
||||
state->sasl_callbacks = 0;
|
||||
}
|
||||
if (state->sasl_encoded) {
|
||||
vstring_free(state->sasl_encoded);
|
||||
state->sasl_encoded = 0;
|
||||
}
|
||||
if (state->sasl_decoded) {
|
||||
vstring_free(state->sasl_decoded);
|
||||
state->sasl_decoded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
120
postfix/src/lmtp/lmtp_sasl_proto.c
Normal file
120
postfix/src/lmtp/lmtp_sasl_proto.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* lmtp_sasl_proto 3
|
||||
/* SUMMARY
|
||||
/* Postfix SASL interface for LMTP client
|
||||
/* SYNOPSIS
|
||||
/* #include lmtp_sasl.h
|
||||
/*
|
||||
/* void lmtp_sasl_helo_auth(state, words)
|
||||
/* LMTP_STATE *state;
|
||||
/* const char *words;
|
||||
/*
|
||||
/* int lmtp_sasl_helo_login(state)
|
||||
/* LMTP_STATE *state;
|
||||
/* DESCRIPTION
|
||||
/* This module contains random chunks of code that implement
|
||||
/* the SMTP protocol interface for SASL negotiation. The goal
|
||||
/* is to reduce clutter in the main LMTP client source code.
|
||||
/*
|
||||
/* lmtp_sasl_helo_auth() processes the AUTH option in the
|
||||
/* SMTP server's EHLO response.
|
||||
/*
|
||||
/* lmtp_sasl_helo_login() authenticates the LMTP client to the
|
||||
/* SMTP server, using the authentication mechanism information
|
||||
/* given by the server. The result is a Postfix delivery status
|
||||
/* code in case of trouble.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
/* Session context.
|
||||
/* .IP words
|
||||
/* List of SASL authentication mechanisms (separated by blanks)
|
||||
/* DIAGNOSTICS
|
||||
/* All errors are fatal.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Original author:
|
||||
/* Till Franke
|
||||
/* SuSE Rhein/Main AG
|
||||
/* 65760 Eschborn, Germany
|
||||
/*
|
||||
/* Adopted by:
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_params.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "lmtp.h"
|
||||
#include "lmtp_sasl.h"
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
|
||||
/* lmtp_sasl_helo_auth - handle AUTH option in EHLO reply */
|
||||
|
||||
void lmtp_sasl_helo_auth(LMTP_STATE *state, const char *words)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX If the server offers a null list of authentication mechanisms,
|
||||
* then pretend that the server doesn't support SASL authentication.
|
||||
*/
|
||||
if (state->sasl_mechanism_list) {
|
||||
myfree(state->sasl_mechanism_list);
|
||||
msg_warn("%s offered AUTH option multiple times",
|
||||
state->session->namaddr);
|
||||
state->sasl_mechanism_list = 0;
|
||||
state->features &= ~SMTP_FEATURE_AUTH;
|
||||
}
|
||||
if (strlen(words) > 0) {
|
||||
state->sasl_mechanism_list = mystrdup(words);
|
||||
state->features |= SMTP_FEATURE_AUTH;
|
||||
} else {
|
||||
msg_warn("%s offered null AUTH mechanism list",
|
||||
state->session->namaddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* lmtp_sasl_helo_login - perform SASL login */
|
||||
|
||||
int lmtp_sasl_helo_login(LMTP_STATE *state)
|
||||
{
|
||||
VSTRING *why = vstring_alloc(10);
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Skip authentication when no authentication info exists for this
|
||||
* server, so that we talk to each other like strangers. Otherwise, if
|
||||
* authentication information exists, assume that authentication is
|
||||
* required, and assume that an authentication error is recoverable.
|
||||
*/
|
||||
if (lmtp_sasl_passwd_lookup(state) != 0) {
|
||||
lmtp_sasl_start(state);
|
||||
if (lmtp_sasl_authenticate(state, why) <= 0)
|
||||
ret = lmtp_site_fail(state, 450, "Authentication failed: %s",
|
||||
vstring_str(why));
|
||||
}
|
||||
vstring_free(why);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif
|
@@ -53,11 +53,12 @@
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <config.h>
|
||||
#include <mail_conf.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "lmtp.h"
|
||||
#include "lmtp_sasl.h"
|
||||
|
||||
/* lmtp_state_alloc - initialize */
|
||||
|
||||
@@ -75,6 +76,9 @@ LMTP_STATE *lmtp_state_alloc(void)
|
||||
state->features = 0;
|
||||
state->history = 0;
|
||||
state->error_mask = 0;
|
||||
#ifdef USE_SASL_AUTH
|
||||
lmtp_sasl_connect(state);
|
||||
#endif
|
||||
state->sndbufsize = 0;
|
||||
state->sndbuffree = 0;
|
||||
state->reuse = 0;
|
||||
@@ -88,5 +92,8 @@ void lmtp_state_free(LMTP_STATE *state)
|
||||
vstring_free(state->buffer);
|
||||
vstring_free(state->scratch);
|
||||
vstring_free(state->scratch2);
|
||||
#ifdef USE_SASL_AUTH
|
||||
lmtp_sasl_cleanup(state);
|
||||
#endif
|
||||
myfree((char *) state);
|
||||
}
|
||||
|
@@ -93,6 +93,7 @@ postconf.o: time_vars.h
|
||||
postconf.o: bool_vars.h
|
||||
postconf.o: int_vars.h
|
||||
postconf.o: str_vars.h
|
||||
postconf.o: raw_vars.h
|
||||
postconf.o: local_vars.h
|
||||
postconf.o: smtp_vars.h
|
||||
postconf.o: time_table.h
|
||||
@@ -101,3 +102,4 @@ postconf.o: int_table.h
|
||||
postconf.o: str_table.h
|
||||
postconf.o: local_table.h
|
||||
postconf.o: smtp_table.h
|
||||
postconf.o: raw_table.h
|
||||
|
@@ -420,7 +420,7 @@ static void set_parameters(void)
|
||||
* bool_table, int_table, str_table, and raw_table. Look up each
|
||||
* parameter name in the configuration parameter dictionary. If the
|
||||
* parameter is not set, take the default value, or take the value from
|
||||
* in main.c, without doing $name expansions. This includes converting
|
||||
* main.cf, without doing $name expansions. This includes converting
|
||||
* default values from numeric/boolean internal forms to external string
|
||||
* form.
|
||||
*
|
||||
@@ -790,9 +790,6 @@ int main(int argc, char **argv)
|
||||
case 'd':
|
||||
mode |= SHOW_DEFS;
|
||||
break;
|
||||
case 'E':
|
||||
mode |= SHOW_EVAL;
|
||||
break;
|
||||
case 'e':
|
||||
mode |= EDIT_MAIN;
|
||||
break;
|
||||
|
@@ -162,9 +162,9 @@ smtp_proto.o: ../../include/record.h
|
||||
smtp_proto.o: ../../include/rec_type.h
|
||||
smtp_proto.o: ../../include/off_cvt.h
|
||||
smtp_proto.o: ../../include/mark_corrupt.h
|
||||
smtp_proto.o: ../../include/quote_821_local.h
|
||||
smtp_proto.o: smtp.h
|
||||
smtp_proto.o: ../../include/argv.h
|
||||
smtp_proto.o: ../../include/quote_821_local.h
|
||||
smtp_proto.o: smtp_sasl.h
|
||||
smtp_sasl_glue.o: smtp_sasl_glue.c
|
||||
smtp_sasl_glue.o: ../../include/sys_defs.h
|
||||
|
@@ -85,7 +85,7 @@ extern void smtp_session_free(SMTP_SESSION *);
|
||||
*/
|
||||
extern SMTP_SESSION *smtp_connect(char *, VSTRING *);
|
||||
extern SMTP_SESSION *smtp_connect_host(char *, unsigned, VSTRING *);
|
||||
extern SMTP_SESSION *smtp_connect_domain(char *, unsigned, VSTRING *);
|
||||
extern SMTP_SESSION *smtp_connect_domain(char *, unsigned, VSTRING *, int *);
|
||||
|
||||
/*
|
||||
* smtp_proto.c
|
||||
|
@@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* #include "smtp_addr.h"
|
||||
/*
|
||||
/* DNS_RR *smtp_domain_addr(name, why)
|
||||
/* DNS_RR *smtp_domain_addr(name, why, found_myself)
|
||||
/* char *name;
|
||||
/* VSTRING *why;
|
||||
/* int *found_myself;
|
||||
/*
|
||||
/* DNS_RR *smtp_host_addr(name, why)
|
||||
/* char *name;
|
||||
@@ -279,11 +280,11 @@ static int smtp_compare_mx(DNS_RR *a, DNS_RR *b)
|
||||
|
||||
/* smtp_domain_addr - mail exchanger address lookup */
|
||||
|
||||
DNS_RR *smtp_domain_addr(char *name, VSTRING *why)
|
||||
DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
|
||||
{
|
||||
DNS_RR *mx_names;
|
||||
DNS_RR *addr_list = 0;
|
||||
DNS_RR *self;
|
||||
DNS_RR *self = 0;
|
||||
unsigned best_pref;
|
||||
unsigned best_found;
|
||||
|
||||
@@ -363,6 +364,7 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why)
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
*found_myself = (self != 0);
|
||||
return (addr_list);
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,7 @@
|
||||
* Internal interfaces.
|
||||
*/
|
||||
extern DNS_RR *smtp_host_addr(char *, VSTRING *);
|
||||
extern DNS_RR *smtp_domain_addr(char *, VSTRING *);
|
||||
extern DNS_RR *smtp_domain_addr(char *, VSTRING *, int *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@@ -292,7 +292,8 @@ SMTP_SESSION *smtp_connect_host(char *host, unsigned port, VSTRING *why)
|
||||
|
||||
/* smtp_connect_domain - connect to smtp server for domain */
|
||||
|
||||
SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why)
|
||||
SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why,
|
||||
int *found_myself)
|
||||
{
|
||||
SMTP_SESSION *session = 0;
|
||||
DNS_RR *addr_list;
|
||||
@@ -306,7 +307,7 @@ SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why)
|
||||
* the primary MX host is reachable but does not want to receive our
|
||||
* mail, there is no point in trying the backup hosts.
|
||||
*/
|
||||
addr_list = smtp_domain_addr(name, why);
|
||||
addr_list = smtp_domain_addr(name, why, found_myself);
|
||||
for (addr = addr_list; addr; addr = addr->next) {
|
||||
if ((session = smtp_connect_addr(addr, port, why)) != 0) {
|
||||
session->best = (addr->pref == addr_list->pref);
|
||||
@@ -393,6 +394,7 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
|
||||
char *save;
|
||||
char *dest;
|
||||
char *cp;
|
||||
int found_myself;
|
||||
|
||||
/*
|
||||
* First try to deliver to the indicated destination, then try to deliver
|
||||
@@ -417,7 +419,7 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
|
||||
if (var_disable_dns || *dest == '[') {
|
||||
session = smtp_connect_host(host, port, why);
|
||||
} else {
|
||||
session = smtp_connect_domain(host, port, why);
|
||||
session = smtp_connect_domain(host, port, why, &found_myself);
|
||||
}
|
||||
myfree(dest_buf);
|
||||
|
||||
@@ -426,7 +428,7 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
|
||||
* is the best MX relay for the destination. Agreed, an errno of OK
|
||||
* after failure is a weird way to reporting progress.
|
||||
*/
|
||||
if (session != 0 || smtp_errno == SMTP_OK)
|
||||
if (session != 0 || smtp_errno == SMTP_OK || found_myself)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -98,11 +98,11 @@
|
||||
#include <rec_type.h>
|
||||
#include <off_cvt.h>
|
||||
#include <mark_corrupt.h>
|
||||
#include <quote_821_local.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "smtp.h"
|
||||
#include "quote_821_local.h"
|
||||
#include "smtp_sasl.h"
|
||||
|
||||
/*
|
||||
@@ -226,6 +226,8 @@ int smtp_helo(SMTP_STATE *state)
|
||||
#ifdef USE_SASL_AUTH
|
||||
else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
|
||||
smtp_sasl_helo_auth(state, words);
|
||||
else if (var_smtp_sasl_enable && strncasecmp(word, "AUTH=", 5) == 0)
|
||||
smtp_sasl_helo_auth(state, word + 5);
|
||||
#endif
|
||||
else if (strcasecmp(word, var_myhostname) == 0) {
|
||||
msg_warn("host %s replied to HELO/EHLO with my own hostname %s",
|
||||
|
@@ -133,7 +133,7 @@ static void smtp_check_code(SMTP_STATE *state, int code)
|
||||
* anti-UCE systems, by people who aren't aware of RFC details.
|
||||
*/
|
||||
if ((!SMTP_SOFT(code) && !SMTP_HARD(code))
|
||||
|| code == 555 /* RFC 1869, section 6.1. */
|
||||
|| code == 555 /* RFC 1869, section 6.1. */
|
||||
|| (code >= 500 && code < 510))
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
}
|
||||
|
@@ -57,6 +57,10 @@
|
||||
/* .IP \fBstrict_rfc821_envelopes\fR
|
||||
/* Disallow non-RFC 821 style addresses in envelopes. For example,
|
||||
/* allow RFC822-style address forms with comments, like Sendmail does.
|
||||
/* .IP \fBallow_broken_auth_clients\fR
|
||||
/* Support older Microsoft clients that mis-implement the AUTH
|
||||
/* protocol, and that expect an EHLO response of "250 AUTH=list"
|
||||
/* instead of "250 AUTH list".
|
||||
/* .SH "Content inspection controls"
|
||||
/* .IP \fBcontent_filter\fR
|
||||
/* The name of a mail delivery transport that filters mail and that
|
||||
@@ -343,6 +347,7 @@ bool var_smtpd_sasl_enable;
|
||||
char *var_smtpd_sasl_opts;
|
||||
char *var_smtpd_sasl_realm;
|
||||
char *var_filter_xport;
|
||||
bool var_broken_auth_clients;
|
||||
|
||||
/*
|
||||
* Global state, for stand-alone mode queue file cleanup. When this is
|
||||
@@ -439,8 +444,11 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "250-SIZE");
|
||||
smtpd_chat_reply(state, "250-ETRN");
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_smtpd_sasl_enable)
|
||||
if (var_smtpd_sasl_enable) {
|
||||
smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list);
|
||||
if (var_broken_auth_clients)
|
||||
smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
|
||||
}
|
||||
#endif
|
||||
smtpd_chat_reply(state, "250 8BITMIME");
|
||||
return (0);
|
||||
@@ -949,7 +957,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
state->error_mask |= MAIL_ERROR_BOUNCE;
|
||||
smtpd_chat_reply(state, "554 Error: too many hops");
|
||||
} else if ((state->err & CLEANUP_STAT_CONT) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_BOUNCE;
|
||||
state->error_mask |= MAIL_ERROR_POLICY;
|
||||
smtpd_chat_reply(state, "552 Error: content rejected");
|
||||
} else if ((state->err & CLEANUP_STAT_WRITE) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_RESOURCE;
|
||||
@@ -1447,6 +1455,7 @@ int main(int argc, char **argv)
|
||||
VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd,
|
||||
VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route,
|
||||
VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable,
|
||||
VAR_BROKEN_AUTH_CLNTS, DEF_BROKEN_AUTH_CLNTS, &var_broken_auth_clients,
|
||||
0,
|
||||
};
|
||||
static CONFIG_STR_TABLE str_table[] = {
|
||||
|
@@ -329,12 +329,19 @@ static void disconnect(SINK_STATE *state)
|
||||
static void connect_event(int unused_event, char *context)
|
||||
{
|
||||
int sock = CAST_CHAR_PTR_TO_INT(context);
|
||||
struct sockaddr sa;
|
||||
SOCKADDR_SIZE len = sizeof(sa);
|
||||
SINK_STATE *state;
|
||||
int fd;
|
||||
|
||||
if ((fd = accept(sock, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0)) >= 0) {
|
||||
if ((fd = accept(sock, &sa, &len)) >= 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("connect");
|
||||
msg_info("connect (%s)", sa.sa_family == AF_LOCAL ? "AF_LOCAL" :
|
||||
#ifdef AF_INET6
|
||||
sa.sa_family == AF_INET6 ? "AF_INET6" :
|
||||
#endif
|
||||
sa.sa_family == AF_INET ? "AF_INET" :
|
||||
"unknown protocol family");
|
||||
non_blocking(fd, NON_BLOCKING);
|
||||
state = (SINK_STATE *) mymalloc(sizeof(*state));
|
||||
state->stream = vstream_fdopen(fd, O_RDWR);
|
||||
|
@@ -136,10 +136,11 @@ static const char *var_myhostname;
|
||||
static int session_count;
|
||||
static int message_count = 1;
|
||||
static struct sockaddr_in sin;
|
||||
|
||||
#undef sun
|
||||
static struct sockaddr_un sun;
|
||||
static struct sockaddr *sa;
|
||||
static int sa_len;
|
||||
static int sa_length;
|
||||
static int recipients = 1;
|
||||
static char *defaddr;
|
||||
static char *recipient;
|
||||
@@ -398,7 +399,7 @@ static void start_connect(SESSION *session)
|
||||
session->stream = vstream_fdopen(fd, O_RDWR);
|
||||
event_enable_write(fd, connect_done, (char *) session);
|
||||
smtp_timeout_setup(session->stream, var_timeout);
|
||||
if (connect(fd, sa, sa_len) < 0 && errno != EINPROGRESS)
|
||||
if (connect(fd, sa, sa_length) < 0 && errno != EINPROGRESS)
|
||||
fail_connect(session);
|
||||
}
|
||||
|
||||
@@ -842,7 +843,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
memcpy(sun.sun_path, path, path_len);
|
||||
sa = (struct sockaddr *) & sun;
|
||||
sa_len = sizeof(sun);
|
||||
sa_length = sizeof(sun);
|
||||
} else {
|
||||
if (strncmp(argv[optind], "inet:", 5) == 0)
|
||||
argv[optind] += 5;
|
||||
@@ -853,7 +854,7 @@ int main(int argc, char **argv)
|
||||
sin.sin_addr.s_addr = find_inet_addr(host);
|
||||
sin.sin_port = find_inet_port(port, "tcp");
|
||||
sa = (struct sockaddr *) & sin;
|
||||
sa_len = sizeof(sin);
|
||||
sa_length = sizeof(sin);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -383,18 +383,6 @@ dict_db.o: argv.h
|
||||
dict_db.o: dict_db.h
|
||||
dict_dbm.o: dict_dbm.c
|
||||
dict_dbm.o: sys_defs.h
|
||||
dict_dbm.o: msg.h
|
||||
dict_dbm.o: mymalloc.h
|
||||
dict_dbm.o: htable.h
|
||||
dict_dbm.o: iostuff.h
|
||||
dict_dbm.o: vstring.h
|
||||
dict_dbm.o: vbuf.h
|
||||
dict_dbm.o: myflock.h
|
||||
dict_dbm.o: stringops.h
|
||||
dict_dbm.o: dict.h
|
||||
dict_dbm.o: vstream.h
|
||||
dict_dbm.o: argv.h
|
||||
dict_dbm.o: dict_dbm.h
|
||||
dict_env.o: dict_env.c
|
||||
dict_env.o: sys_defs.h
|
||||
dict_env.o: mymalloc.h
|
||||
@@ -418,14 +406,6 @@ dict_ldap.o: dict_ldap.c
|
||||
dict_ldap.o: sys_defs.h
|
||||
dict_mysql.o: dict_mysql.c
|
||||
dict_mysql.o: sys_defs.h
|
||||
dict_mysql.o: dict.h
|
||||
dict_mysql.o: vstream.h
|
||||
dict_mysql.o: vbuf.h
|
||||
dict_mysql.o: argv.h
|
||||
dict_mysql.o: msg.h
|
||||
dict_mysql.o: mymalloc.h
|
||||
dict_mysql.o: dict_mysql.h
|
||||
dict_mysql.o: vstring.h
|
||||
dict_ni.o: dict_ni.c
|
||||
dict_ni.o: sys_defs.h
|
||||
dict_nis.o: dict_nis.c
|
||||
|
@@ -81,8 +81,18 @@ int make_dirs(const char *path, int perms)
|
||||
} else {
|
||||
if (errno != ENOENT)
|
||||
break;
|
||||
if ((ret = mkdir(saved_path, perms)) < 0 && errno != EEXIST)
|
||||
break;
|
||||
if ((ret = mkdir(saved_path, perms)) < 0) {
|
||||
if (errno != EEXIST)
|
||||
break;
|
||||
/* Race condition? */
|
||||
if ((ret = stat(saved_path, &st)) < 0)
|
||||
break;
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (saved_ch != 0)
|
||||
*cp = saved_ch;
|
||||
|
1
postfix/src/virtual/.indent.pro
vendored
1
postfix/src/virtual/.indent.pro
vendored
@@ -1 +0,0 @@
|
||||
../../.indent.pro
|
@@ -1,441 +0,0 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = virtual.c mailbox.c recipient.c deliver_attr.c maildir.c unknown.c
|
||||
OBJS = virtual.o mailbox.o recipient.o deliver_attr.o maildir.o unknown.o
|
||||
HDRS = virtual.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -I..
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
PROG = virtual
|
||||
TESTPROG=
|
||||
INC_DIR = ../../include
|
||||
LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a $(AUXLIBS)
|
||||
|
||||
.c.o:; $(CC) $(CFLAGS) -c $*.c
|
||||
|
||||
$(PROG): $(OBJS) $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
|
||||
|
||||
Makefile: Makefile.in
|
||||
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs; cat $?) >$@
|
||||
|
||||
test: $(TESTPROG)
|
||||
|
||||
update: ../../libexec/$(PROG)
|
||||
|
||||
../../libexec/$(PROG): $(PROG)
|
||||
cp $(PROG) ../../libexec
|
||||
|
||||
printfck: $(OBJS) $(PROG)
|
||||
rm -rf printfck
|
||||
mkdir printfck
|
||||
cp *.h printfck
|
||||
sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
|
||||
set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
|
||||
cd printfck; make "INC_DIR=../../include" `cd ..; ls *.o`
|
||||
|
||||
lint:
|
||||
lint $(DEFS) $(SRCS) $(LINTFIX)
|
||||
|
||||
clean:
|
||||
rm -f *.o *core $(PROG) $(TESTPROG) junk
|
||||
rm -rf printfck
|
||||
|
||||
tidy: clean
|
||||
|
||||
depend: $(MAKES)
|
||||
(sed '1,/^# do not edit/!d' Makefile.in; \
|
||||
set -e; for i in [a-z][a-z0-9]*.c; do \
|
||||
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
|
||||
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
|
||||
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
|
||||
@make -f Makefile.in Makefile
|
||||
deliver_attr.o: deliver_attr.c
|
||||
deliver_attr.o: ../../include/sys_defs.h
|
||||
deliver_attr.o: ../../include/msg.h
|
||||
deliver_attr.o: ../../include/vstream.h
|
||||
deliver_attr.o: ../../include/vbuf.h
|
||||
deliver_attr.o: virtual.h
|
||||
deliver_attr.o: ../../include/htable.h
|
||||
deliver_attr.o: ../../include/vstring.h
|
||||
deliver_attr.o: ../../include/been_here.h
|
||||
deliver_attr.o: ../../include/tok822.h
|
||||
deliver_attr.o: ../../include/resolve_clnt.h
|
||||
deliver_attr.o: ../../include/deliver_request.h
|
||||
deliver_attr.o: ../../include/recipient_list.h
|
||||
deliver_attr.o: ../../include/maps.h
|
||||
deliver_attr.o: ../../include/dict.h
|
||||
deliver_attr.o: ../../include/argv.h
|
||||
mailbox.o: mailbox.c
|
||||
mailbox.o: ../../include/sys_defs.h
|
||||
mailbox.o: ../../include/msg.h
|
||||
mailbox.o: ../../include/htable.h
|
||||
mailbox.o: ../../include/vstring.h
|
||||
mailbox.o: ../../include/vbuf.h
|
||||
mailbox.o: ../../include/vstream.h
|
||||
mailbox.o: ../../include/mymalloc.h
|
||||
mailbox.o: ../../include/stringops.h
|
||||
mailbox.o: ../../include/set_eugid.h
|
||||
mailbox.o: ../../include/mail_copy.h
|
||||
mailbox.o: ../../include/safe_open.h
|
||||
mailbox.o: ../../include/deliver_flock.h
|
||||
mailbox.o: ../../include/dot_lockfile.h
|
||||
mailbox.o: ../../include/defer.h
|
||||
mailbox.o: ../../include/bounce.h
|
||||
mailbox.o: ../../include/sent.h
|
||||
mailbox.o: ../../include/mypwd.h
|
||||
mailbox.o: ../../include/mail_params.h
|
||||
mailbox.o: ../../include/deliver_pass.h
|
||||
mailbox.o: ../../include/deliver_request.h
|
||||
mailbox.o: ../../include/recipient_list.h
|
||||
mailbox.o: ../../include/mail_proto.h
|
||||
mailbox.o: ../../include/iostuff.h
|
||||
mailbox.o: virtual.h
|
||||
mailbox.o: ../../include/been_here.h
|
||||
mailbox.o: ../../include/tok822.h
|
||||
mailbox.o: ../../include/resolve_clnt.h
|
||||
mailbox.o: ../../include/maps.h
|
||||
mailbox.o: ../../include/dict.h
|
||||
mailbox.o: ../../include/argv.h
|
||||
maildir.o: maildir.c
|
||||
maildir.o: ../../include/sys_defs.h
|
||||
maildir.o: ../../include/msg.h
|
||||
maildir.o: ../../include/mymalloc.h
|
||||
maildir.o: ../../include/stringops.h
|
||||
maildir.o: ../../include/vstring.h
|
||||
maildir.o: ../../include/vbuf.h
|
||||
maildir.o: ../../include/vstream.h
|
||||
maildir.o: ../../include/make_dirs.h
|
||||
maildir.o: ../../include/set_eugid.h
|
||||
maildir.o: ../../include/get_hostname.h
|
||||
maildir.o: ../../include/mail_copy.h
|
||||
maildir.o: ../../include/bounce.h
|
||||
maildir.o: ../../include/sent.h
|
||||
maildir.o: ../../include/mail_params.h
|
||||
maildir.o: virtual.h
|
||||
maildir.o: ../../include/htable.h
|
||||
maildir.o: ../../include/been_here.h
|
||||
maildir.o: ../../include/tok822.h
|
||||
maildir.o: ../../include/resolve_clnt.h
|
||||
maildir.o: ../../include/deliver_request.h
|
||||
maildir.o: ../../include/recipient_list.h
|
||||
maildir.o: ../../include/maps.h
|
||||
maildir.o: ../../include/dict.h
|
||||
maildir.o: ../../include/argv.h
|
||||
recipient.o: recipient.c
|
||||
recipient.o: ../../include/sys_defs.h
|
||||
recipient.o: ../../include/msg.h
|
||||
recipient.o: ../../include/mymalloc.h
|
||||
recipient.o: ../../include/htable.h
|
||||
recipient.o: ../../include/split_at.h
|
||||
recipient.o: ../../include/stringops.h
|
||||
recipient.o: ../../include/vstring.h
|
||||
recipient.o: ../../include/vbuf.h
|
||||
recipient.o: ../../include/dict.h
|
||||
recipient.o: ../../include/vstream.h
|
||||
recipient.o: ../../include/argv.h
|
||||
recipient.o: ../../include/bounce.h
|
||||
recipient.o: ../../include/mail_params.h
|
||||
recipient.o: ../../include/split_addr.h
|
||||
recipient.o: ../../include/ext_prop.h
|
||||
recipient.o: virtual.h
|
||||
recipient.o: ../../include/been_here.h
|
||||
recipient.o: ../../include/tok822.h
|
||||
recipient.o: ../../include/resolve_clnt.h
|
||||
recipient.o: ../../include/deliver_request.h
|
||||
recipient.o: ../../include/recipient_list.h
|
||||
recipient.o: ../../include/maps.h
|
||||
unknown.o: unknown.c
|
||||
unknown.o: ../../include/sys_defs.h
|
||||
unknown.o: ../../include/msg.h
|
||||
unknown.o: ../../include/stringops.h
|
||||
unknown.o: ../../include/vstring.h
|
||||
unknown.o: ../../include/vbuf.h
|
||||
unknown.o: ../../include/mymalloc.h
|
||||
unknown.o: ../../include/mail_params.h
|
||||
unknown.o: ../../include/mail_proto.h
|
||||
unknown.o: ../../include/vstream.h
|
||||
unknown.o: ../../include/iostuff.h
|
||||
unknown.o: ../../include/bounce.h
|
||||
unknown.o: virtual.h
|
||||
unknown.o: ../../include/htable.h
|
||||
unknown.o: ../../include/been_here.h
|
||||
unknown.o: ../../include/tok822.h
|
||||
unknown.o: ../../include/resolve_clnt.h
|
||||
unknown.o: ../../include/deliver_request.h
|
||||
unknown.o: ../../include/recipient_list.h
|
||||
unknown.o: ../../include/maps.h
|
||||
unknown.o: ../../include/dict.h
|
||||
unknown.o: ../../include/argv.h
|
||||
virtual.o: virtual.c
|
||||
virtual.o: ../../include/sys_defs.h
|
||||
virtual.o: ../../include/msg.h
|
||||
virtual.o: ../../include/mymalloc.h
|
||||
virtual.o: ../../include/htable.h
|
||||
virtual.o: ../../include/vstring.h
|
||||
virtual.o: ../../include/vbuf.h
|
||||
virtual.o: ../../include/vstream.h
|
||||
virtual.o: ../../include/iostuff.h
|
||||
virtual.o: ../../include/name_mask.h
|
||||
virtual.o: ../../include/set_eugid.h
|
||||
virtual.o: ../../include/dict.h
|
||||
virtual.o: ../../include/argv.h
|
||||
virtual.o: ../../include/mail_queue.h
|
||||
virtual.o: ../../include/recipient_list.h
|
||||
virtual.o: ../../include/deliver_request.h
|
||||
virtual.o: ../../include/deliver_completed.h
|
||||
virtual.o: ../../include/mail_params.h
|
||||
virtual.o: ../../include/mail_addr.h
|
||||
virtual.o: ../../include/mail_conf.h
|
||||
virtual.o: ../../include/ext_prop.h
|
||||
virtual.o: ../../include/mail_server.h
|
||||
virtual.o: virtual.h
|
||||
virtual.o: ../../include/been_here.h
|
||||
virtual.o: ../../include/tok822.h
|
||||
virtual.o: ../../include/resolve_clnt.h
|
||||
virtual.o: ../../include/maps.h
|
||||
deliver_attr.o: deliver_attr.c
|
||||
deliver_attr.o: ../../include/sys_defs.h
|
||||
deliver_attr.o: ../../include/msg.h
|
||||
deliver_attr.o: ../../include/vstream.h
|
||||
deliver_attr.o: ../../include/vbuf.h
|
||||
deliver_attr.o: virtual.h
|
||||
deliver_attr.o: ../../include/vstring.h
|
||||
deliver_attr.o: ../../include/deliver_request.h
|
||||
deliver_attr.o: ../../include/recipient_list.h
|
||||
deliver_attr.o: ../../include/maps.h
|
||||
deliver_attr.o: ../../include/dict.h
|
||||
deliver_attr.o: ../../include/argv.h
|
||||
deliver_attr.o: ../../include/mbox_conf.h
|
||||
mailbox.o: mailbox.c
|
||||
mailbox.o: ../../include/sys_defs.h
|
||||
mailbox.o: ../../include/msg.h
|
||||
mailbox.o: ../../include/vstring.h
|
||||
mailbox.o: ../../include/vbuf.h
|
||||
mailbox.o: ../../include/vstream.h
|
||||
mailbox.o: ../../include/mymalloc.h
|
||||
mailbox.o: ../../include/stringops.h
|
||||
mailbox.o: ../../include/set_eugid.h
|
||||
mailbox.o: ../../include/mail_copy.h
|
||||
mailbox.o: ../../include/mbox_open.h
|
||||
mailbox.o: ../../include/safe_open.h
|
||||
mailbox.o: ../../include/defer.h
|
||||
mailbox.o: ../../include/bounce.h
|
||||
mailbox.o: ../../include/sent.h
|
||||
mailbox.o: ../../include/mypwd.h
|
||||
mailbox.o: ../../include/mail_params.h
|
||||
mailbox.o: virtual.h
|
||||
mailbox.o: ../../include/deliver_request.h
|
||||
mailbox.o: ../../include/recipient_list.h
|
||||
mailbox.o: ../../include/maps.h
|
||||
mailbox.o: ../../include/dict.h
|
||||
mailbox.o: ../../include/argv.h
|
||||
mailbox.o: ../../include/mbox_conf.h
|
||||
maildir.o: maildir.c
|
||||
maildir.o: ../../include/sys_defs.h
|
||||
maildir.o: ../../include/msg.h
|
||||
maildir.o: ../../include/mymalloc.h
|
||||
maildir.o: ../../include/stringops.h
|
||||
maildir.o: ../../include/vstring.h
|
||||
maildir.o: ../../include/vbuf.h
|
||||
maildir.o: ../../include/vstream.h
|
||||
maildir.o: ../../include/make_dirs.h
|
||||
maildir.o: ../../include/set_eugid.h
|
||||
maildir.o: ../../include/get_hostname.h
|
||||
maildir.o: ../../include/sane_fsops.h
|
||||
maildir.o: ../../include/mail_copy.h
|
||||
maildir.o: ../../include/bounce.h
|
||||
maildir.o: ../../include/sent.h
|
||||
maildir.o: ../../include/mail_params.h
|
||||
maildir.o: virtual.h
|
||||
maildir.o: ../../include/deliver_request.h
|
||||
maildir.o: ../../include/recipient_list.h
|
||||
maildir.o: ../../include/maps.h
|
||||
maildir.o: ../../include/dict.h
|
||||
maildir.o: ../../include/argv.h
|
||||
maildir.o: ../../include/mbox_conf.h
|
||||
recipient.o: recipient.c
|
||||
recipient.o: ../../include/sys_defs.h
|
||||
recipient.o: ../../include/msg.h
|
||||
recipient.o: ../../include/mymalloc.h
|
||||
recipient.o: ../../include/htable.h
|
||||
recipient.o: ../../include/split_at.h
|
||||
recipient.o: ../../include/stringops.h
|
||||
recipient.o: ../../include/vstring.h
|
||||
recipient.o: ../../include/vbuf.h
|
||||
recipient.o: ../../include/dict.h
|
||||
recipient.o: ../../include/vstream.h
|
||||
recipient.o: ../../include/argv.h
|
||||
recipient.o: ../../include/bounce.h
|
||||
recipient.o: ../../include/mail_params.h
|
||||
recipient.o: ../../include/split_addr.h
|
||||
recipient.o: ../../include/ext_prop.h
|
||||
recipient.o: virtual.h
|
||||
recipient.o: ../../include/deliver_request.h
|
||||
recipient.o: ../../include/recipient_list.h
|
||||
recipient.o: ../../include/maps.h
|
||||
recipient.o: ../../include/mbox_conf.h
|
||||
unknown.o: unknown.c
|
||||
unknown.o: ../../include/sys_defs.h
|
||||
unknown.o: ../../include/msg.h
|
||||
unknown.o: ../../include/stringops.h
|
||||
unknown.o: ../../include/vstring.h
|
||||
unknown.o: ../../include/vbuf.h
|
||||
unknown.o: ../../include/mymalloc.h
|
||||
unknown.o: ../../include/mail_params.h
|
||||
unknown.o: ../../include/mail_proto.h
|
||||
unknown.o: ../../include/vstream.h
|
||||
unknown.o: ../../include/iostuff.h
|
||||
unknown.o: ../../include/bounce.h
|
||||
unknown.o: virtual.h
|
||||
unknown.o: ../../include/deliver_request.h
|
||||
unknown.o: ../../include/recipient_list.h
|
||||
unknown.o: ../../include/maps.h
|
||||
unknown.o: ../../include/dict.h
|
||||
unknown.o: ../../include/argv.h
|
||||
unknown.o: ../../include/mbox_conf.h
|
||||
virtual.o: virtual.c
|
||||
virtual.o: ../../include/sys_defs.h
|
||||
virtual.o: ../../include/msg.h
|
||||
virtual.o: ../../include/mymalloc.h
|
||||
virtual.o: ../../include/htable.h
|
||||
virtual.o: ../../include/vstring.h
|
||||
virtual.o: ../../include/vbuf.h
|
||||
virtual.o: ../../include/vstream.h
|
||||
virtual.o: ../../include/iostuff.h
|
||||
virtual.o: ../../include/name_mask.h
|
||||
virtual.o: ../../include/set_eugid.h
|
||||
virtual.o: ../../include/dict.h
|
||||
virtual.o: ../../include/argv.h
|
||||
virtual.o: ../../include/mail_queue.h
|
||||
virtual.o: ../../include/recipient_list.h
|
||||
virtual.o: ../../include/deliver_request.h
|
||||
virtual.o: ../../include/deliver_completed.h
|
||||
virtual.o: ../../include/mail_params.h
|
||||
virtual.o: ../../include/mail_addr.h
|
||||
virtual.o: ../../include/mail_conf.h
|
||||
virtual.o: ../../include/mail_server.h
|
||||
virtual.o: virtual.h
|
||||
virtual.o: ../../include/maps.h
|
||||
virtual.o: ../../include/mbox_conf.h
|
||||
deliver_attr.o: deliver_attr.c
|
||||
deliver_attr.o: ../../include/sys_defs.h
|
||||
deliver_attr.o: ../../include/msg.h
|
||||
deliver_attr.o: ../../include/vstream.h
|
||||
deliver_attr.o: ../../include/vbuf.h
|
||||
deliver_attr.o: virtual.h
|
||||
deliver_attr.o: ../../include/vstring.h
|
||||
deliver_attr.o: ../../include/deliver_request.h
|
||||
deliver_attr.o: ../../include/recipient_list.h
|
||||
deliver_attr.o: ../../include/maps.h
|
||||
deliver_attr.o: ../../include/dict.h
|
||||
deliver_attr.o: ../../include/argv.h
|
||||
deliver_attr.o: ../../include/mbox_conf.h
|
||||
mailbox.o: mailbox.c
|
||||
mailbox.o: ../../include/sys_defs.h
|
||||
mailbox.o: ../../include/msg.h
|
||||
mailbox.o: ../../include/vstring.h
|
||||
mailbox.o: ../../include/vbuf.h
|
||||
mailbox.o: ../../include/vstream.h
|
||||
mailbox.o: ../../include/mymalloc.h
|
||||
mailbox.o: ../../include/stringops.h
|
||||
mailbox.o: ../../include/set_eugid.h
|
||||
mailbox.o: ../../include/mail_copy.h
|
||||
mailbox.o: ../../include/mbox_open.h
|
||||
mailbox.o: ../../include/safe_open.h
|
||||
mailbox.o: ../../include/defer.h
|
||||
mailbox.o: ../../include/bounce.h
|
||||
mailbox.o: ../../include/sent.h
|
||||
mailbox.o: ../../include/mypwd.h
|
||||
mailbox.o: ../../include/mail_params.h
|
||||
mailbox.o: virtual.h
|
||||
mailbox.o: ../../include/deliver_request.h
|
||||
mailbox.o: ../../include/recipient_list.h
|
||||
mailbox.o: ../../include/maps.h
|
||||
mailbox.o: ../../include/dict.h
|
||||
mailbox.o: ../../include/argv.h
|
||||
mailbox.o: ../../include/mbox_conf.h
|
||||
maildir.o: maildir.c
|
||||
maildir.o: ../../include/sys_defs.h
|
||||
maildir.o: ../../include/msg.h
|
||||
maildir.o: ../../include/mymalloc.h
|
||||
maildir.o: ../../include/stringops.h
|
||||
maildir.o: ../../include/vstring.h
|
||||
maildir.o: ../../include/vbuf.h
|
||||
maildir.o: ../../include/vstream.h
|
||||
maildir.o: ../../include/make_dirs.h
|
||||
maildir.o: ../../include/set_eugid.h
|
||||
maildir.o: ../../include/get_hostname.h
|
||||
maildir.o: ../../include/sane_fsops.h
|
||||
maildir.o: ../../include/mail_copy.h
|
||||
maildir.o: ../../include/bounce.h
|
||||
maildir.o: ../../include/sent.h
|
||||
maildir.o: ../../include/mail_params.h
|
||||
maildir.o: virtual.h
|
||||
maildir.o: ../../include/deliver_request.h
|
||||
maildir.o: ../../include/recipient_list.h
|
||||
maildir.o: ../../include/maps.h
|
||||
maildir.o: ../../include/dict.h
|
||||
maildir.o: ../../include/argv.h
|
||||
maildir.o: ../../include/mbox_conf.h
|
||||
recipient.o: recipient.c
|
||||
recipient.o: ../../include/sys_defs.h
|
||||
recipient.o: ../../include/msg.h
|
||||
recipient.o: ../../include/mymalloc.h
|
||||
recipient.o: ../../include/stringops.h
|
||||
recipient.o: ../../include/vstring.h
|
||||
recipient.o: ../../include/vbuf.h
|
||||
recipient.o: ../../include/bounce.h
|
||||
recipient.o: virtual.h
|
||||
recipient.o: ../../include/vstream.h
|
||||
recipient.o: ../../include/deliver_request.h
|
||||
recipient.o: ../../include/recipient_list.h
|
||||
recipient.o: ../../include/maps.h
|
||||
recipient.o: ../../include/dict.h
|
||||
recipient.o: ../../include/argv.h
|
||||
recipient.o: ../../include/mbox_conf.h
|
||||
unknown.o: unknown.c
|
||||
unknown.o: ../../include/sys_defs.h
|
||||
unknown.o: ../../include/msg.h
|
||||
unknown.o: ../../include/stringops.h
|
||||
unknown.o: ../../include/vstring.h
|
||||
unknown.o: ../../include/vbuf.h
|
||||
unknown.o: ../../include/mymalloc.h
|
||||
unknown.o: ../../include/mail_params.h
|
||||
unknown.o: ../../include/mail_proto.h
|
||||
unknown.o: ../../include/vstream.h
|
||||
unknown.o: ../../include/iostuff.h
|
||||
unknown.o: ../../include/bounce.h
|
||||
unknown.o: virtual.h
|
||||
unknown.o: ../../include/deliver_request.h
|
||||
unknown.o: ../../include/recipient_list.h
|
||||
unknown.o: ../../include/maps.h
|
||||
unknown.o: ../../include/dict.h
|
||||
unknown.o: ../../include/argv.h
|
||||
unknown.o: ../../include/mbox_conf.h
|
||||
virtual.o: virtual.c
|
||||
virtual.o: ../../include/sys_defs.h
|
||||
virtual.o: ../../include/msg.h
|
||||
virtual.o: ../../include/mymalloc.h
|
||||
virtual.o: ../../include/htable.h
|
||||
virtual.o: ../../include/vstring.h
|
||||
virtual.o: ../../include/vbuf.h
|
||||
virtual.o: ../../include/vstream.h
|
||||
virtual.o: ../../include/iostuff.h
|
||||
virtual.o: ../../include/name_mask.h
|
||||
virtual.o: ../../include/set_eugid.h
|
||||
virtual.o: ../../include/dict.h
|
||||
virtual.o: ../../include/argv.h
|
||||
virtual.o: ../../include/mail_queue.h
|
||||
virtual.o: ../../include/recipient_list.h
|
||||
virtual.o: ../../include/deliver_request.h
|
||||
virtual.o: ../../include/deliver_completed.h
|
||||
virtual.o: ../../include/mail_params.h
|
||||
virtual.o: ../../include/mail_addr.h
|
||||
virtual.o: ../../include/mail_conf.h
|
||||
virtual.o: ../../include/mail_server.h
|
||||
virtual.o: virtual.h
|
||||
virtual.o: ../../include/maps.h
|
||||
virtual.o: ../../include/mbox_conf.h
|
@@ -1,74 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* deliver_attr 3
|
||||
/* SUMMARY
|
||||
/* initialize message delivery attributes
|
||||
/* SYNOPSIS
|
||||
/* #include "virtual.h"
|
||||
/*
|
||||
/* void deliver_attr_init(attrp)
|
||||
/* DELIVER_ATTR *attrp;
|
||||
/*
|
||||
/* void deliver_attr_dump(attrp)
|
||||
/* DELIVER_ATTR *attrp;
|
||||
/* DESCRIPTION
|
||||
/* deliver_attr_init() initializes a structure with message delivery
|
||||
/* attributes to a known initial state (all zeros).
|
||||
/*
|
||||
/* deliver_attr_dump() logs the contents of the given attribute list.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <vstream.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "virtual.h"
|
||||
|
||||
/* deliver_attr_init - set message delivery attributes to all-zero state */
|
||||
|
||||
void deliver_attr_init(DELIVER_ATTR *attrp)
|
||||
{
|
||||
attrp->level = 0;
|
||||
attrp->fp = 0;
|
||||
attrp->queue_name = 0;
|
||||
attrp->queue_id = 0;
|
||||
attrp->offset = 0;
|
||||
attrp->sender = 0;
|
||||
attrp->recipient = 0;
|
||||
attrp->user = 0;
|
||||
attrp->delivered = 0;
|
||||
attrp->relay = 0;
|
||||
}
|
||||
|
||||
/* deliver_attr_dump - log message delivery attributes */
|
||||
|
||||
void deliver_attr_dump(DELIVER_ATTR *attrp)
|
||||
{
|
||||
msg_info("level: %d", attrp->level);
|
||||
msg_info("path: %s", VSTREAM_PATH(attrp->fp));
|
||||
msg_info("fp: 0x%lx", (long) attrp->fp);
|
||||
msg_info("queue_name: %s", attrp->queue_name ? attrp->queue_name : "null");
|
||||
msg_info("queue_id: %s", attrp->queue_id ? attrp->queue_id : "null");
|
||||
msg_info("offset: %ld", attrp->offset);
|
||||
msg_info("sender: %s", attrp->sender ? attrp->sender : "null");
|
||||
msg_info("recipient: %s", attrp->recipient ? attrp->recipient : "null");
|
||||
msg_info("user: %s", attrp->user ? attrp->user : "null");
|
||||
msg_info("delivered: %s", attrp->delivered ? attrp->delivered : "null");
|
||||
msg_info("relay: %s", attrp->relay ? attrp->relay : "null");
|
||||
}
|
@@ -1,232 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* mailbox 3
|
||||
/* SUMMARY
|
||||
/* mailbox delivery
|
||||
/* SYNOPSIS
|
||||
/* #include "virtual.h"
|
||||
/*
|
||||
/* int deliver_mailbox(state, usr_attr, statusp)
|
||||
/* LOCAL_STATE state;
|
||||
/* USER_ATTR usr_attr;
|
||||
/* int *statusp;
|
||||
/* DESCRIPTION
|
||||
/* deliver_mailbox() delivers to UNIX-style mailbox or to maildir.
|
||||
/*
|
||||
/* A zero result means that the named user was not found.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
/* The attributes that specify the message, recipient and more.
|
||||
/* .IP usr_attr
|
||||
/* Attributes describing user rights and mailbox location.
|
||||
/* .IP statusp
|
||||
/* Delivery status: see below.
|
||||
/* DIAGNOSTICS
|
||||
/* The message delivery status is non-zero when delivery should be tried
|
||||
/* again.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <vstring.h>
|
||||
#include <vstream.h>
|
||||
#include <mymalloc.h>
|
||||
#include <stringops.h>
|
||||
#include <set_eugid.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_copy.h>
|
||||
#include <mbox_open.h>
|
||||
#include <defer.h>
|
||||
#include <sent.h>
|
||||
#include <mail_params.h>
|
||||
|
||||
#ifndef EDQUOT
|
||||
#define EDQUOT EFBIG
|
||||
#endif
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "virtual.h"
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
/* deliver_mailbox_file - deliver to recipient mailbox */
|
||||
|
||||
static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
|
||||
{
|
||||
char *myname = "deliver_mailbox_file";
|
||||
VSTRING *why;
|
||||
MBOX *mp;
|
||||
int status;
|
||||
int copy_flags;
|
||||
long end;
|
||||
struct stat st;
|
||||
|
||||
/*
|
||||
* Make verbose logging easier to understand.
|
||||
*/
|
||||
state.level++;
|
||||
if (msg_verbose)
|
||||
MSG_LOG_STATE(myname, state);
|
||||
|
||||
/*
|
||||
* Initialize. Assume the operation will fail. Set the delivered
|
||||
* attribute to reflect the final recipient.
|
||||
*/
|
||||
if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
|
||||
msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp));
|
||||
state.msg_attr.delivered = state.msg_attr.recipient;
|
||||
status = -1;
|
||||
why = vstring_alloc(100);
|
||||
|
||||
/*
|
||||
* Lock the mailbox and open/create the mailbox file.
|
||||
*
|
||||
* Write the file as the recipient, so that file quota work.
|
||||
*/
|
||||
copy_flags = MAIL_COPY_MBOX;
|
||||
|
||||
set_eugid(usr_attr.uid, usr_attr.gid);
|
||||
mp = mbox_open(usr_attr.mailbox, O_APPEND | O_WRONLY | O_CREAT,
|
||||
S_IRUSR | S_IWUSR, &st, -1, -1,
|
||||
virtual_mbox_lock_mask, why);
|
||||
if (mp != 0) {
|
||||
if (S_ISREG(st.st_mode) == 0) {
|
||||
vstream_fclose(mp->fp);
|
||||
vstring_sprintf(why, "destination is not a regular file");
|
||||
errno = 0;
|
||||
} else {
|
||||
end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END);
|
||||
status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
|
||||
copy_flags, "\n", why);
|
||||
}
|
||||
mbox_release(mp);
|
||||
}
|
||||
set_eugid(var_owner_uid, var_owner_gid);
|
||||
|
||||
/*
|
||||
* As the mail system, bounce, defer delivery, or report success.
|
||||
*/
|
||||
if (status != 0)
|
||||
status = (errno == EDQUOT ? bounce_append : defer_append)
|
||||
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"cannot access mailbox for %s. %s",
|
||||
usr_attr.mailbox, state.msg_attr.recipient, vstring_str(why));
|
||||
else
|
||||
sent(SENT_ATTR(state.msg_attr), "mailbox");
|
||||
|
||||
vstring_free(why);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* deliver_mailbox - deliver to recipient mailbox */
|
||||
|
||||
int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
|
||||
{
|
||||
char *myname = "deliver_mailbox";
|
||||
const char *result;
|
||||
long n;
|
||||
|
||||
/*
|
||||
* Make verbose logging easier to understand.
|
||||
*/
|
||||
state.level++;
|
||||
if (msg_verbose)
|
||||
MSG_LOG_STATE(myname, state);
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (*var_virt_mailbox_base != '/')
|
||||
msg_fatal("do not specify relative pathname: %s = %s",
|
||||
VAR_VIRT_MAILBOX_BASE, var_virt_mailbox_base);
|
||||
|
||||
/*
|
||||
* Look up the mailbox location and rights of the recipient user.
|
||||
*/
|
||||
result = maps_find(virtual_mailbox_maps, state.msg_attr.user, 0);
|
||||
if (result == 0) {
|
||||
if (dict_errno == 0)
|
||||
return (NO);
|
||||
|
||||
*statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"%s: lookup %s: %m",
|
||||
virtual_mailbox_maps->title, state.msg_attr.user);
|
||||
return (YES);
|
||||
}
|
||||
usr_attr.mailbox = concatenate(var_virt_mailbox_base, "/", result, (char *) 0);
|
||||
|
||||
if ((result = maps_find(virtual_uid_maps, state.msg_attr.user, 0)) == 0) {
|
||||
myfree(usr_attr.mailbox);
|
||||
*statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"recipient %s: uid not found in %s",
|
||||
state.msg_attr.user, virtual_uid_maps->title);
|
||||
return (YES);
|
||||
}
|
||||
if ((n = atol(result)) < var_virt_minimum_uid) {
|
||||
myfree(usr_attr.mailbox);
|
||||
*statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"recipient %s: bad uid %s in %s",
|
||||
state.msg_attr.user, result, virtual_uid_maps->title);
|
||||
return (YES);
|
||||
}
|
||||
usr_attr.uid = (uid_t) n;
|
||||
|
||||
if ((result = maps_find(virtual_gid_maps, state.msg_attr.user, 0)) == 0) {
|
||||
myfree(usr_attr.mailbox);
|
||||
*statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"recipient %s: gid not found in %s",
|
||||
state.msg_attr.user, virtual_gid_maps->title);
|
||||
return (YES);
|
||||
}
|
||||
if ((n = atol(result)) <= 0) {
|
||||
myfree(usr_attr.mailbox);
|
||||
*statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"recipient %s: bad gid %s in %s",
|
||||
state.msg_attr.user, result, virtual_gid_maps->title);
|
||||
return (YES);
|
||||
}
|
||||
usr_attr.gid = (gid_t) n;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s[%d]: set user_attr: %s, uid = %d, gid = %d",
|
||||
myname, state.level,
|
||||
usr_attr.mailbox, usr_attr.uid, usr_attr.gid);
|
||||
|
||||
/*
|
||||
* Deliver to mailbox or to external command.
|
||||
*/
|
||||
#define LAST_CHAR(s) (s[strlen(s) - 1])
|
||||
|
||||
if (LAST_CHAR(usr_attr.mailbox) == '/')
|
||||
*statusp = deliver_maildir(state, usr_attr);
|
||||
else
|
||||
*statusp = deliver_mailbox_file(state, usr_attr);
|
||||
|
||||
/*
|
||||
* Cleanup.
|
||||
*/
|
||||
myfree(usr_attr.mailbox);
|
||||
return (YES);
|
||||
}
|
@@ -1,159 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* maildir 3
|
||||
/* SUMMARY
|
||||
/* delivery to maildir
|
||||
/* SYNOPSIS
|
||||
/* #include "virtual.h"
|
||||
/*
|
||||
/* int deliver_maildir(state, usr_attr)
|
||||
/* LOCAL_STATE state;
|
||||
/* USER_ATTR usr_attr;
|
||||
/* DESCRIPTION
|
||||
/* deliver_maildir() delivers a message to a qmail-style maildir.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
/* The attributes that specify the message, recipient and more.
|
||||
/* .IP usr_attr
|
||||
/* Attributes describing user rights and environment information.
|
||||
/* DIAGNOSTICS
|
||||
/* deliver_maildir() always succeeds or it bounces the message.
|
||||
/* SEE ALSO
|
||||
/* bounce(3)
|
||||
/* 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 <errno.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <stringops.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring.h>
|
||||
#include <make_dirs.h>
|
||||
#include <set_eugid.h>
|
||||
#include <get_hostname.h>
|
||||
#include <sane_fsops.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_copy.h>
|
||||
#include <bounce.h>
|
||||
#include <sent.h>
|
||||
#include <mail_params.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "virtual.h"
|
||||
|
||||
/* deliver_maildir - delivery to maildir-style mailbox */
|
||||
|
||||
int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr)
|
||||
{
|
||||
char *myname = "deliver_maildir";
|
||||
char *newdir;
|
||||
char *tmpdir;
|
||||
char *curdir;
|
||||
char *tmpfile;
|
||||
char *newfile;
|
||||
VSTRING *why;
|
||||
VSTRING *buf;
|
||||
VSTREAM *dst;
|
||||
int status;
|
||||
int copy_flags;
|
||||
static int count;
|
||||
|
||||
/*
|
||||
* Make verbose logging easier to understand.
|
||||
*/
|
||||
state.level++;
|
||||
if (msg_verbose)
|
||||
MSG_LOG_STATE(myname, state);
|
||||
|
||||
/*
|
||||
* Initialize. Assume the operation will fail. Set the delivered
|
||||
* attribute to reflect the final recipient.
|
||||
*/
|
||||
if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
|
||||
msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp));
|
||||
state.msg_attr.delivered = state.msg_attr.recipient;
|
||||
status = -1;
|
||||
buf = vstring_alloc(100);
|
||||
why = vstring_alloc(100);
|
||||
|
||||
copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH | MAIL_COPY_DELIVERED;
|
||||
|
||||
newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0);
|
||||
tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0);
|
||||
curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0);
|
||||
|
||||
/*
|
||||
* Create and write the file as the recipient, so that file quota work.
|
||||
* Create any missing directories on the fly. The file name is chosen
|
||||
* according to ftp://koobera.math.uic.edu/www/proto/maildir.html:
|
||||
*
|
||||
* "A unique name has three pieces, separated by dots. On the left is the
|
||||
* result of time(). On the right is the result of gethostname(). In the
|
||||
* middle is something that doesn't repeat within one second on a single
|
||||
* host. I fork a new process for each delivery, so I just use the
|
||||
* process ID. If you're delivering several messages from one process,
|
||||
* use starttime.pid_count.host, where starttime is the time that your
|
||||
* process started, and count is the number of messages you've
|
||||
* delivered."
|
||||
*/
|
||||
#define STR vstring_str
|
||||
|
||||
set_eugid(usr_attr.uid, usr_attr.gid);
|
||||
vstring_sprintf(buf, "%ld.%d_%d.%s", (long) var_starttime,
|
||||
var_pid, count++, get_hostname());
|
||||
tmpfile = concatenate(tmpdir, STR(buf), (char *) 0);
|
||||
newfile = concatenate(newdir, STR(buf), (char *) 0);
|
||||
if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0
|
||||
&& (errno != ENOENT
|
||||
|| make_dirs(tmpdir, 0700) < 0
|
||||
|| (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) {
|
||||
vstring_sprintf(why, "create %s: %m", tmpfile);
|
||||
} else {
|
||||
if (mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why) == 0) {
|
||||
if (sane_link(tmpfile, newfile) < 0
|
||||
&& (errno != ENOENT
|
||||
|| (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0
|
||||
|| sane_link(tmpfile, newfile) < 0)) {
|
||||
vstring_sprintf(why, "link to %s: %m", newfile);
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
if (unlink(tmpfile) < 0)
|
||||
msg_warn("remove %s: %m", tmpfile);
|
||||
}
|
||||
set_eugid(var_owner_uid, var_owner_gid);
|
||||
|
||||
if (status)
|
||||
bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"maildir delivery failed: %s", vstring_str(why));
|
||||
else
|
||||
sent(SENT_ATTR(state.msg_attr), "maildir");
|
||||
vstring_free(buf);
|
||||
vstring_free(why);
|
||||
myfree(newdir);
|
||||
myfree(tmpdir);
|
||||
myfree(curdir);
|
||||
myfree(tmpfile);
|
||||
myfree(newfile);
|
||||
return (0);
|
||||
}
|
@@ -1,93 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* recipient 3
|
||||
/* SUMMARY
|
||||
/* deliver to one local recipient
|
||||
/* SYNOPSIS
|
||||
/* #include "virtual.h"
|
||||
/*
|
||||
/* int deliver_recipient(state, usr_attr)
|
||||
/* LOCAL_STATE state;
|
||||
/* USER_ATTR *usr_attr;
|
||||
/* DESCRIPTION
|
||||
/* deliver_recipient() delivers a message to a local recipient.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
/* The attributes that specify the message, sender, and more.
|
||||
/* .IP usr_attr
|
||||
/* Attributes describing user rights and mailbox location.
|
||||
/* DIAGNOSTICS
|
||||
/* deliver_recipient() returns non-zero when delivery should be
|
||||
/* tried again.
|
||||
/* SEE ALSO
|
||||
/* mailbox(3) delivery to UNIX-style mailbox
|
||||
/* maildir(3) delivery to qmail-style maildir
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <stringops.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <bounce.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "virtual.h"
|
||||
|
||||
/* deliver_recipient - deliver one local recipient */
|
||||
|
||||
int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
|
||||
{
|
||||
char *myname = "deliver_recipient";
|
||||
int rcpt_stat;
|
||||
|
||||
/*
|
||||
* Make verbose logging easier to understand.
|
||||
*/
|
||||
state.level++;
|
||||
if (msg_verbose)
|
||||
MSG_LOG_STATE(myname, state);
|
||||
|
||||
/*
|
||||
* Set up the recipient-specific attributes. The recipient's lookup
|
||||
* handle is the full address.
|
||||
*/
|
||||
if (state.msg_attr.delivered == 0)
|
||||
state.msg_attr.delivered = state.msg_attr.recipient;
|
||||
state.msg_attr.user = mystrdup(state.msg_attr.recipient);
|
||||
lowercase(state.msg_attr.user);
|
||||
|
||||
/*
|
||||
* Deliver
|
||||
*/
|
||||
if (msg_verbose)
|
||||
deliver_attr_dump(&state.msg_attr);
|
||||
|
||||
if (deliver_mailbox(state, usr_attr, &rcpt_stat) == 0)
|
||||
rcpt_stat = deliver_unknown(state);
|
||||
|
||||
/*
|
||||
* Cleanup.
|
||||
*/
|
||||
myfree(state.msg_attr.user);
|
||||
|
||||
return (rcpt_stat);
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* unknown 3
|
||||
/* SUMMARY
|
||||
/* delivery of unknown recipients
|
||||
/* SYNOPSIS
|
||||
/* #include "virtual.h"
|
||||
/*
|
||||
/* int deliver_unknown(state)
|
||||
/* LOCAL_STATE state;
|
||||
/* DESCRIPTION
|
||||
/* deliver_unknown() delivers a message for unknown recipients.
|
||||
/* .PP
|
||||
/* Arguments:
|
||||
/* .IP state
|
||||
/* Message delivery attributes (sender, recipient etc.).
|
||||
/* .IP usr_attr
|
||||
/* Attributes describing user rights and mailbox location.
|
||||
/* DIAGNOSTICS
|
||||
/* The result status is non-zero when delivery should be tried again.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <bounce.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "virtual.h"
|
||||
|
||||
/* deliver_unknown - delivery for unknown recipients */
|
||||
|
||||
int deliver_unknown(LOCAL_STATE state)
|
||||
{
|
||||
char *myname = "deliver_unknown";
|
||||
|
||||
/*
|
||||
* Make verbose logging easier to understand.
|
||||
*/
|
||||
state.level++;
|
||||
if (msg_verbose)
|
||||
MSG_LOG_STATE(myname, state);
|
||||
|
||||
return (bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"unknown user: \"%s\"", state.msg_attr.user));
|
||||
|
||||
}
|
@@ -1,392 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* virtual 8
|
||||
/* SUMMARY
|
||||
/* Postfix virtual domain mail delivery agent
|
||||
/* SYNOPSIS
|
||||
/* \fBvirtual\fR [generic Postfix daemon options]
|
||||
/* DESCRIPTION
|
||||
/* The \fBvirtual\fR delivery agent is designed for virtual mail
|
||||
/* hosting services. Originally based on the Postfix local delivery
|
||||
/* agent, this agent looks up recipients with map lookups of their
|
||||
/* full recipient address, instead of using hard-coded unix password
|
||||
/* file lookups of the address local part only.
|
||||
/*
|
||||
/* This delivery agent only delivers mail. Other features such as
|
||||
/* mail forwarding, out-of-office notifications, etc., must be
|
||||
/* configured via virtual maps or via similar lookup mechanisms.
|
||||
/* MAILBOX LOCATION
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The mailbox location is controlled by the \fBvirtual_mailbox_base\fR
|
||||
/* and \fBvirtual_mailbox_maps\fR configuration parameters (see below).
|
||||
/* The pathname is constructed as follows:
|
||||
/*
|
||||
/* .ti +2
|
||||
/* \fB$virtual_mailbox_base/$virtual_mailbox_maps(\fIrecipient\fB)\fR
|
||||
/*
|
||||
/* where \fIrecipient\fR is the full recipient address.
|
||||
/* UNIX MAILBOX FORMAT
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* When the mailbox location does not end in \fB/\fR, the message
|
||||
/* is delivered in UNIX mailbox format. This format stores multiple
|
||||
/* messages in one textfile.
|
||||
/*
|
||||
/* The \fBvirtual\fR delivery agent prepends a "\fBFrom \fIsender
|
||||
/* time_stamp\fR" envelope header to each message, prepends a
|
||||
/* \fBDelivered-To:\fR message header with the envelope recipient
|
||||
/* address, prepends a \fBReturn-Path:\fR message header with the
|
||||
/* envelope sender address, prepends a \fB>\fR character to lines
|
||||
/* beginning with "\fBFrom \fR", and appends an empty line.
|
||||
/*
|
||||
/* The mailbox is locked for exclusive access while delivery is in
|
||||
/* progress. In case of problems, an attempt is made to truncate the
|
||||
/* mailbox to its original length.
|
||||
/* QMAIL MAILDIR FORMAT
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* When the mailbox location ends in \fB/\fR, the message is delivered
|
||||
/* in qmail \fBmaildir\fR format. This format stores one message per file.
|
||||
/*
|
||||
/* The \fBvirtual\fR delivery agent daemon prepends a \fBDelivered-To:\fR
|
||||
/* message header with the envelope recipient address and prepends a
|
||||
/* \fBReturn-Path:\fR message header with the envelope sender address.
|
||||
/*
|
||||
/* By definition, \fBmaildir\fR format does not require file locking
|
||||
/* during mail delivery or retrieval.
|
||||
/* MAILBOX OWNERSHIP
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* Mailbox ownership is controlled by the \fBvirtual_owner_maps\fR
|
||||
/* lookup tables. These tables can perform the following mappings:
|
||||
/* .IP "recipient username"
|
||||
/* The mailbox is owned by the specified UNIX user.
|
||||
/* .IP "recipient uid:gid"
|
||||
/* The mailbox is owned by the specified numerical user and group ID.
|
||||
/* BACKWARDS COMPATIBILITY
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* For backwards compatibility, mailbox ownership can also be specified
|
||||
/* through separate \fBvirtual_uid_maps\fR and \fBvirtual_gid_maps\fR
|
||||
/* tables.
|
||||
/* SAFETY
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The \fBvirtual_minimum_uid\fR parameter imposes a lower bound on
|
||||
/* numerical user ID values that may be specified in any
|
||||
/* \fBvirtual_owner_maps\fR or \fBvirtual_uid_maps\fR.
|
||||
/* STANDARDS
|
||||
/* RFC 822 (ARPA Internet Text Messages)
|
||||
/* DIAGNOSTICS
|
||||
/* Mail bounces when the recipient has no mailbox or when the
|
||||
/* recipient is over disk quota. In all other cases, mail for
|
||||
/* an existing recipient is deferred and a warning is logged.
|
||||
/*
|
||||
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
/* Corrupted message files are marked so that the queue
|
||||
/* manager can move them to the \fBcorrupt\fR queue afterwards.
|
||||
/*
|
||||
/* Depending on the setting of the \fBnotify_classes\fR parameter,
|
||||
/* the postmaster is notified of bounces and of other trouble.
|
||||
/* BUGS
|
||||
/* This delivery agent silently ignores address extensions.
|
||||
/* CONFIGURATION PARAMETERS
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The following \fBmain.cf\fR parameters are especially relevant to
|
||||
/* this program. See the Postfix \fBmain.cf\fR file for syntax details
|
||||
/* and for default values. Use the \fBpostfix reload\fR command after
|
||||
/* a configuration change.
|
||||
/* .SH Mailbox delivery
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .IP \fBvirtual_mailbox_base\fR
|
||||
/* Specifies a path that is prepended to all mailbox or maildir paths.
|
||||
/* This is a safety measure to ensure that an out of control map in
|
||||
/* \fBvirtual_mailbox_maps\fR doesn't litter the filesystem with mailboxes.
|
||||
/* While it could be set to "/", this setting isn't recommended.
|
||||
/* .IP \fBvirtual_mailbox_maps\fR
|
||||
/* Recipients are looked up in these maps to determine the path to
|
||||
/* their mailbox or maildir. If the returned path ends in a slash
|
||||
/* ("/"), maildir-style delivery is carried out, otherwise the
|
||||
/* path is assumed to specify a mailbox file.
|
||||
/*
|
||||
/* Note that \fBvirtual_mailbox_base\fR is unconditionally prepended
|
||||
/* to this path.
|
||||
/* .IP \fBvirtual_minimum_uid\fR
|
||||
/* Specifies a minimum uid that will be accepted as a return from
|
||||
/* a \fBvirtual_owner_maps\fR or \fBvirtual_uid_maps\fR lookup.
|
||||
/* Returned values less than this will be rejected, and the message
|
||||
/* will be deferred.
|
||||
/* .IP \fBvirtual_owner_maps\fR
|
||||
/* Recipients are looked up in these maps to determine the UNIX user
|
||||
/* name of the mailbox owner, or the numerical user and group ID
|
||||
/* in numerical \fIuid:gid\fR format.
|
||||
/* .IP \fBvirtual_uid_maps\fR
|
||||
/* Recipients are looked up in these maps to determine the user ID to be
|
||||
/* used when writing to the target mailbox.
|
||||
/* .sp
|
||||
/* This feature exists for backwards compatibility; it will go away.
|
||||
/* .IP \fBvirtual_gid_maps\fR
|
||||
/* Recipients are looked up in these maps to determine the group ID to be
|
||||
/* used when writing to the target mailbox.
|
||||
/* .sp
|
||||
/* This feature exists for backwards compatibility; it will go away.
|
||||
/* .SH "Locking controls"
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .IP \fBmailbox_delivery_lock\fR
|
||||
/* How to lock UNIX-style mailboxes: one or more of \fBflock\fR,
|
||||
/* \fBfcntl\fR or \fBdotlock\fR.
|
||||
/*
|
||||
/* Use the command \fBpostconf -m\fR to find out what locking methods
|
||||
/* are available on your system.
|
||||
/* .IP \fBdeliver_lock_attempts\fR
|
||||
/* Limit the number of attempts to acquire an exclusive lock
|
||||
/* on a UNIX-style mailbox file.
|
||||
/* .IP \fBdeliver_lock_delay\fR
|
||||
/* Time (default: seconds) between successive attempts to acquire
|
||||
/* an exclusive lock on a UNIX-style mailbox file.
|
||||
/* .IP \fBstale_lock_time\fR
|
||||
/* Limit the time after which a stale lockfile is removed (applicable
|
||||
/* to UNIX-style mailboxes only).
|
||||
/* .SH "Resource controls"
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .IP \fBvirtual_destination_concurrency_limit\fR
|
||||
/* Limit the number of parallel deliveries to the same domain.
|
||||
/* The default limit is taken from the
|
||||
/* \fBdefault_destination_concurrency_limit\fR parameter.
|
||||
/* .IP \fBvirtual_destination_recipient_limit\fR
|
||||
/* Limit the number of recipients per message delivery.
|
||||
/* The default limit is taken from the
|
||||
/* \fBdefault_destination_recipient_limit\fR parameter.
|
||||
/* HISTORY
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* This agent was originally based on the Postfix local delivery
|
||||
/* agent. Modifications mainly consisted of removing code that either
|
||||
/* was not applicable or that was not safe in this context: aliases,
|
||||
/* ~user/.forward files, delivery to "|command" or to /file/name.
|
||||
/*
|
||||
/* The \fBDelivered-To:\fR header appears in the \fBqmail\fR system
|
||||
/* by Daniel Bernstein.
|
||||
/*
|
||||
/* The \fImaildir\fR structure appears in the \fBqmail\fR system
|
||||
/* by Daniel Bernstein.
|
||||
/* SEE ALSO
|
||||
/* bounce(8) non-delivery status reports
|
||||
/* syslogd(8) system logging
|
||||
/* qmgr(8) queue manager
|
||||
/* 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
|
||||
/*
|
||||
/* Andrew McNamara
|
||||
/* andrewm@connect.com.au
|
||||
/* connect.com.au Pty. Ltd.
|
||||
/* Level 3, 213 Miller St
|
||||
/* North Sydney 2060, NSW, Australia
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <vstring.h>
|
||||
#include <vstream.h>
|
||||
#include <iostuff.h>
|
||||
#include <set_eugid.h>
|
||||
#include <dict.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_queue.h>
|
||||
#include <recipient_list.h>
|
||||
#include <deliver_request.h>
|
||||
#include <deliver_completed.h>
|
||||
#include <mail_params.h>
|
||||
#include <mail_conf.h>
|
||||
#include <mail_params.h>
|
||||
|
||||
/* Single server skeleton. */
|
||||
|
||||
#include <mail_server.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "virtual.h"
|
||||
|
||||
/*
|
||||
* Tunable parameters.
|
||||
*/
|
||||
char *var_mailbox_maps;
|
||||
char *var_uid_maps;
|
||||
char *var_gid_maps;
|
||||
int var_virt_minimum_uid;
|
||||
char *var_virt_mailbox_base;
|
||||
char *var_mailbox_lock;
|
||||
|
||||
/*
|
||||
* Mappings.
|
||||
*/
|
||||
MAPS *virtual_mailbox_maps;
|
||||
MAPS *virtual_uid_maps;
|
||||
MAPS *virtual_gid_maps;
|
||||
|
||||
/*
|
||||
* Bit masks.
|
||||
*/
|
||||
int virtual_mbox_lock_mask;
|
||||
|
||||
/* local_deliver - deliver message with extreme prejudice */
|
||||
|
||||
static int local_deliver(DELIVER_REQUEST *rqst, char *service)
|
||||
{
|
||||
char *myname = "local_deliver";
|
||||
RECIPIENT *rcpt_end = rqst->rcpt_list.info + rqst->rcpt_list.len;
|
||||
RECIPIENT *rcpt;
|
||||
int rcpt_stat;
|
||||
int msg_stat;
|
||||
LOCAL_STATE state;
|
||||
USER_ATTR usr_attr;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("local_deliver: %s from %s", rqst->queue_id, rqst->sender);
|
||||
|
||||
/*
|
||||
* Initialize the delivery attributes that are not recipient specific.
|
||||
* While messages are being delivered and while aliases or forward files
|
||||
* are being expanded, this attribute list is being changed constantly.
|
||||
* For this reason, the list is passed on by value (except when it is
|
||||
* being initialized :-), so that there is no need to undo attribute
|
||||
* changes made by lower-level routines. The alias/include/forward
|
||||
* expansion attribute list is part of a tree with self and parent
|
||||
* references (see the EXPAND_ATTR definitions). The user-specific
|
||||
* attributes are security sensitive, and are therefore kept separate.
|
||||
* All this results in a noticeable level of clumsiness, but passing
|
||||
* things around by value gives good protection against accidental change
|
||||
* by subroutines.
|
||||
*/
|
||||
state.level = 0;
|
||||
deliver_attr_init(&state.msg_attr);
|
||||
state.msg_attr.queue_name = rqst->queue_name;
|
||||
state.msg_attr.queue_id = rqst->queue_id;
|
||||
state.msg_attr.fp = rqst->fp;
|
||||
state.msg_attr.offset = rqst->data_offset;
|
||||
state.msg_attr.sender = rqst->sender;
|
||||
state.msg_attr.relay = service;
|
||||
state.msg_attr.arrival_time = rqst->arrival_time;
|
||||
RESET_USER_ATTR(usr_attr, state.level);
|
||||
state.request = rqst;
|
||||
|
||||
/*
|
||||
* Iterate over each recipient named in the delivery request. When the
|
||||
* mail delivery status for a given recipient is definite (i.e. bounced
|
||||
* or delivered), update the message queue file and cross off the
|
||||
* recipient. Update the per-message delivery status.
|
||||
*/
|
||||
for (msg_stat = 0, rcpt = rqst->rcpt_list.info; rcpt < rcpt_end; rcpt++) {
|
||||
state.msg_attr.recipient = rcpt->address;
|
||||
rcpt_stat = deliver_recipient(state, usr_attr);
|
||||
if (rcpt_stat == 0)
|
||||
deliver_completed(state.msg_attr.fp, rcpt->offset);
|
||||
msg_stat |= rcpt_stat;
|
||||
}
|
||||
|
||||
return (msg_stat);
|
||||
}
|
||||
|
||||
/* local_service - perform service for client */
|
||||
|
||||
static void local_service(VSTREAM *stream, char *service, char **argv)
|
||||
{
|
||||
DELIVER_REQUEST *request;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Sanity check. This service takes no command-line arguments.
|
||||
*/
|
||||
if (argv[0])
|
||||
msg_fatal("unexpected command-line argument: %s", argv[0]);
|
||||
|
||||
/*
|
||||
* This routine runs whenever a client connects to the UNIX-domain socket
|
||||
* that is dedicated to local mail delivery service. What we see below is
|
||||
* a little protocol to (1) tell the client that we are ready, (2) read a
|
||||
* delivery request from the client, and (3) report the completion status
|
||||
* of that request.
|
||||
*/
|
||||
if ((request = deliver_request_read(stream)) != 0) {
|
||||
status = local_deliver(request, service);
|
||||
deliver_request_done(stream, request, status);
|
||||
}
|
||||
}
|
||||
|
||||
/* pre_accept - see if tables have changed */
|
||||
|
||||
static void pre_accept(char *unused_name, char **unused_argv)
|
||||
{
|
||||
if (dict_changed()) {
|
||||
msg_info("table has changed -- exiting");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* post_init - post-jail initialization */
|
||||
|
||||
static void post_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
|
||||
/*
|
||||
* Drop privileges most of the time.
|
||||
*/
|
||||
set_eugid(var_owner_uid, var_owner_gid);
|
||||
|
||||
virtual_mailbox_maps =
|
||||
maps_create(VAR_VIRT_MAILBOX_MAPS, var_mailbox_maps,
|
||||
DICT_FLAG_LOCK);
|
||||
|
||||
virtual_uid_maps =
|
||||
maps_create(VAR_VIRT_UID_MAPS, var_uid_maps, DICT_FLAG_LOCK);
|
||||
|
||||
virtual_gid_maps =
|
||||
maps_create(VAR_VIRT_UID_MAPS, var_gid_maps, DICT_FLAG_LOCK);
|
||||
|
||||
virtual_mbox_lock_mask = mbox_lock_mask(var_mailbox_lock);
|
||||
}
|
||||
|
||||
/* main - pass control to the single-threaded skeleton */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static CONFIG_INT_TABLE int_table[] = {
|
||||
VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_STR_TABLE str_table[] = {
|
||||
VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_mailbox_maps, 0, 0,
|
||||
VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_uid_maps, 0, 0,
|
||||
VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_gid_maps, 0, 0,
|
||||
VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 0, 0,
|
||||
VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, &var_mailbox_lock, 1, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
single_server_main(argc, argv, local_service,
|
||||
MAIL_SERVER_INT_TABLE, int_table,
|
||||
MAIL_SERVER_STR_TABLE, str_table,
|
||||
MAIL_SERVER_POST_INIT, post_init,
|
||||
MAIL_SERVER_PRE_ACCEPT, pre_accept,
|
||||
0);
|
||||
}
|
@@ -1,134 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* virtual 3h
|
||||
/* SUMMARY
|
||||
/* virtual mail delivery
|
||||
/* SYNOPSIS
|
||||
/* #include "virtual.h"
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* System library.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <vstream.h>
|
||||
#include <vstring.h>
|
||||
|
||||
/*
|
||||
* Global library.
|
||||
*/
|
||||
#include <deliver_request.h>
|
||||
#include <maps.h>
|
||||
#include <mbox_conf.h>
|
||||
|
||||
/*
|
||||
* Mappings.
|
||||
*/
|
||||
extern MAPS *virtual_mailbox_maps;
|
||||
extern MAPS *virtual_uid_maps;
|
||||
extern MAPS *virtual_gid_maps;
|
||||
|
||||
/*
|
||||
* User attributes: these control the privileges for delivery to external
|
||||
* commands, external files, or mailboxes, and the initial environment of
|
||||
* external commands.
|
||||
*/
|
||||
typedef struct USER_ATTR {
|
||||
uid_t uid; /* file/command access */
|
||||
gid_t gid; /* file/command access */
|
||||
char *mailbox; /* mailbox file or directory */
|
||||
} USER_ATTR;
|
||||
|
||||
/*
|
||||
* Critical macros. Not for obscurity, but to ensure consistency.
|
||||
*/
|
||||
#define RESET_USER_ATTR(usr_attr, level) { \
|
||||
usr_attr.uid = 0; usr_attr.gid = 0; usr_attr.mailbox = 0; \
|
||||
if (msg_verbose) \
|
||||
msg_info("%s[%d]: reset user_attr", myname, level); \
|
||||
}
|
||||
|
||||
/*
|
||||
* The delivery attributes are inherited from files, from aliases, and from
|
||||
* whatnot. Some of the information is changed on the fly. DELIVER_ATTR
|
||||
* structres are therefore passed by value, so there is no need to undo
|
||||
* changes.
|
||||
*/
|
||||
typedef struct DELIVER_ATTR {
|
||||
int level; /* recursion level */
|
||||
VSTREAM *fp; /* open queue file */
|
||||
char *queue_name; /* mail queue id */
|
||||
char *queue_id; /* mail queue id */
|
||||
long offset; /* data offset */
|
||||
char *sender; /* taken from envelope */
|
||||
char *recipient; /* taken from resolver */
|
||||
char *user; /* recipient lookup handle */
|
||||
char *delivered; /* for loop detection */
|
||||
char *relay; /* relay host */
|
||||
long arrival_time; /* arrival time */
|
||||
} DELIVER_ATTR;
|
||||
|
||||
extern void deliver_attr_init(DELIVER_ATTR *);
|
||||
extern void deliver_attr_dump(DELIVER_ATTR *);
|
||||
|
||||
#define FEATURE_NODELIVERED (1<<0) /* no delivered-to */
|
||||
|
||||
/*
|
||||
* Rather than schlepping around dozens of arguments, here is one that has
|
||||
* all. Well, almost. The user attributes are just a bit too sensitive, so
|
||||
* they are passed around separately.
|
||||
*/
|
||||
typedef struct LOCAL_STATE {
|
||||
int level; /* nesting level, for logging */
|
||||
DELIVER_ATTR msg_attr; /* message attributes */
|
||||
DELIVER_REQUEST *request; /* as from queue manager */
|
||||
} LOCAL_STATE;
|
||||
|
||||
/*
|
||||
* Bundle up some often-user attributes.
|
||||
*/
|
||||
#define BOUNCE_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \
|
||||
attr.arrival_time
|
||||
#define SENT_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \
|
||||
attr.arrival_time
|
||||
#define COPY_ATTR(attr) attr.sender, attr.delivered, attr.fp
|
||||
|
||||
#define MSG_LOG_STATE(m, p) \
|
||||
msg_info("%s[%d]: recip %s deliver %s", m, \
|
||||
p.level, \
|
||||
p.msg_attr.recipient ? p.msg_attr.recipient : "", \
|
||||
p.msg_attr.delivered ? p.msg_attr.delivered : "")
|
||||
|
||||
/*
|
||||
* "inner" nodes of the delivery graph.
|
||||
*/
|
||||
extern int deliver_recipient(LOCAL_STATE, USER_ATTR);
|
||||
|
||||
/*
|
||||
* "leaf" nodes of the delivery graph.
|
||||
*/
|
||||
extern int deliver_mailbox(LOCAL_STATE, USER_ATTR, int *);
|
||||
extern int deliver_file(LOCAL_STATE, USER_ATTR, char *);
|
||||
extern int deliver_maildir(LOCAL_STATE, USER_ATTR);
|
||||
extern int deliver_unknown(LOCAL_STATE);
|
||||
|
||||
/*
|
||||
* Mailbox lock protocol.
|
||||
*/
|
||||
extern int virtual_mbox_lock_mask;
|
||||
|
||||
/* 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
|
||||
/*--*/
|
Reference in New Issue
Block a user