not part of release 1.1.2
This commit is contained in:
parent
1f31e11b0f
commit
5cf194aa6d
|
@ -1,68 +0,0 @@
|
||||||
Purpose of this document
|
|
||||||
========================
|
|
||||||
|
|
||||||
This document describes how to build Postfix with third-party
|
|
||||||
Berkeley DB from www.sleepycat.com, or how to choose a specific
|
|
||||||
Berkeley DB version when your system provides multiple implementations.
|
|
||||||
|
|
||||||
Building Postfix with Sleepycat Berkeley DB
|
|
||||||
===========================================
|
|
||||||
|
|
||||||
Many commercial UNIXes ship without Berkeley DB support. Examples
|
|
||||||
are Solaris, HP-UX, IRIX, UNIXWARE. In order to build Postfix with
|
|
||||||
Berkeley DB support you need to download and install the source
|
|
||||||
code from www.sleepycat.com.
|
|
||||||
|
|
||||||
To build Postfix after you installed the Berkeley DB from Sleepycat,
|
|
||||||
use something like:
|
|
||||||
|
|
||||||
% make tidy
|
|
||||||
% make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB.3.1/include" \
|
|
||||||
AUXLIBS="-L/usr/local/BerkeleyDB.3.1/lib -ldb"
|
|
||||||
% make
|
|
||||||
|
|
||||||
The exact pathnames depend on the DB version that you installed.
|
|
||||||
For example, Berkeley DB version 2 installs in /usr/local/BerkeleyDB.
|
|
||||||
|
|
||||||
Beware, the file format produced by Berkeley DB version 1 is not
|
|
||||||
compatible with that of versions 2 and 3 (versions 2 and 3 have
|
|
||||||
the same format). If you switch between DB versions, then you may
|
|
||||||
have to rebuild all your Postfix DB files.
|
|
||||||
|
|
||||||
Building Postfix on BSD systems with a specific Berkeley DB version
|
|
||||||
===================================================================
|
|
||||||
|
|
||||||
Some BSD systems ship with multiple Berkeley DB implementations.
|
|
||||||
Normally, Postfix builds with the default DB version that ships
|
|
||||||
with the system.
|
|
||||||
|
|
||||||
To build Postfix on BSD systems with a specific DB version, use a
|
|
||||||
variant of the following commands:
|
|
||||||
|
|
||||||
% make tidy
|
|
||||||
% make makefiles CCARGS=-I/usr/include/db2 AUXLIBS=-ldb2
|
|
||||||
% make
|
|
||||||
|
|
||||||
Beware, the file format produced by Berkeley DB version 1 is not
|
|
||||||
compatible with that of versions 2 and 3 (versions 2 and 3 have
|
|
||||||
the same format). If you switch between DB versions, then you may
|
|
||||||
have to rebuild all your Postfix DB files.
|
|
||||||
|
|
||||||
Building Postfix on Linux with a specific Berkeley DB version
|
|
||||||
=============================================================
|
|
||||||
|
|
||||||
Some Linux systems systems ship with multiple Berkeley DB
|
|
||||||
implementations. Normally, Postfix builds with the default DB
|
|
||||||
version that ships with the system.
|
|
||||||
|
|
||||||
On Linux, you need to edit the makedefs script in order to specify
|
|
||||||
a non-default DB library.
|
|
||||||
|
|
||||||
The reason is that the location of the default db.h include file
|
|
||||||
changes randomly between vendors and between versions, so that
|
|
||||||
Postfix has to choose the file for you.
|
|
||||||
|
|
||||||
Beware, the file format produced by Berkeley DB version 1 is not
|
|
||||||
compatible with that of versions 2 and 3 (versions 2 and 3 have
|
|
||||||
the same format). If you switch between DB versions, then you may
|
|
||||||
have to rebuild all your Postfix DB files.
|
|
|
@ -1,153 +0,0 @@
|
||||||
1 - Purpose of this document
|
|
||||||
============================
|
|
||||||
|
|
||||||
This document describes how to debug parts of the Postfix mail
|
|
||||||
system, either by making the software log a lot of detail to the
|
|
||||||
syslog daemon, or by running some daemon processes under control
|
|
||||||
of an interactive debugger.
|
|
||||||
|
|
||||||
2 - Verbose logging for specific SMTP connections
|
|
||||||
=================================================
|
|
||||||
|
|
||||||
In /etc/postfix/main.cf, list the remote site name or address in
|
|
||||||
the "debug_peer_list" parameter. For example, in order to make the
|
|
||||||
software log a lot of information to the syslog daemon for connections
|
|
||||||
from or to the loopback interface:
|
|
||||||
|
|
||||||
debug_peer_list = 127.0.0.1
|
|
||||||
|
|
||||||
You can specify one or more hosts, domains, addresses or net/masks.
|
|
||||||
|
|
||||||
2b - Record the SMTP connection with a sniffer
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
This example uses tcpdump. In order to record a conversation you
|
|
||||||
need to specify a large enough buffer or else you will miss some
|
|
||||||
or all of the packet payload.
|
|
||||||
|
|
||||||
tcpdump -w /file/name -s 2000 host hostname and port 25
|
|
||||||
|
|
||||||
Run this for a while, stop with Ctrl-C when done. To view the data
|
|
||||||
use a binary viewer, or use my tcpdumpx utility that is available
|
|
||||||
from ftp://ftp.porcupine.org/pub/debugging.
|
|
||||||
|
|
||||||
3 - Making Postfix daemon programs more verbose
|
|
||||||
===============================================
|
|
||||||
|
|
||||||
Append one or more -v options to selected daemon definitions in
|
|
||||||
/etc/postfix/master.cf and type "postfix reload". This will cause
|
|
||||||
a lot of activity to be logged to the syslog daemon.
|
|
||||||
|
|
||||||
4 - Manually tracing a Postfix daemon process
|
|
||||||
=============================================
|
|
||||||
|
|
||||||
Some systems allow you to inspect a running process with a system
|
|
||||||
call tracer. For example:
|
|
||||||
|
|
||||||
# trace -p process-id
|
|
||||||
# strace -p process-id
|
|
||||||
# truss -p process-id
|
|
||||||
# ktrace -p process-id
|
|
||||||
|
|
||||||
See your system documentation for details.
|
|
||||||
|
|
||||||
Tracing a running process can give valuable information about what
|
|
||||||
a process is attempting to do. This is as much information as you
|
|
||||||
can get without running an interactive debugger program, as described
|
|
||||||
in a later section.
|
|
||||||
|
|
||||||
5 - Automatically tracing a Postfix daemon process
|
|
||||||
==================================================
|
|
||||||
|
|
||||||
Postfix can attach a call tracer whenever a daemon process starts.
|
|
||||||
|
|
||||||
Append a -D option to the suspect command in /etc/postfix/master.cf,
|
|
||||||
for example:
|
|
||||||
|
|
||||||
smtp inet n - n - - smtpd -D
|
|
||||||
|
|
||||||
Edit the debugger_command definition in /etc/postfix/main.cf so
|
|
||||||
that it invokes the call tracer of your choice, for example:
|
|
||||||
|
|
||||||
debugger_command =
|
|
||||||
PATH=/bin:/usr/bin:/usr/local/bin
|
|
||||||
(truss -p $process_id 2>&1 | logger -p mail.info) & sleep 5
|
|
||||||
|
|
||||||
Instead of truss use trace or strace.
|
|
||||||
|
|
||||||
Type "postfix reload" and watch the logfile.
|
|
||||||
|
|
||||||
6 - Running daemon programs under an interactive debugger
|
|
||||||
=========================================================
|
|
||||||
|
|
||||||
Append a -D option to the suspect command in /etc/postfix/master.cf,
|
|
||||||
for example:
|
|
||||||
|
|
||||||
smtp inet n - n - - smtpd -D
|
|
||||||
|
|
||||||
Edit the debugger_command definition in /etc/postfix/main.cf so
|
|
||||||
that it invokes the debugger of your choice, for example:
|
|
||||||
|
|
||||||
debugger_command =
|
|
||||||
PATH=/usr/bin:/usr/X11R6/bin
|
|
||||||
xxgdb $daemon_directory/$process_name $process_id & sleep 5
|
|
||||||
|
|
||||||
If you use xxgdb, be sure that gdb is in the command search path.
|
|
||||||
|
|
||||||
Export XAUTHORITY so that X access control works, for example:
|
|
||||||
|
|
||||||
% setenv XAUTHORITY ~/.Xauthority
|
|
||||||
|
|
||||||
Stop and start the Postfix system.
|
|
||||||
|
|
||||||
Whenever the suspect daemon process is started, a debugger window
|
|
||||||
pops up and you can watch in detail what happens.
|
|
||||||
|
|
||||||
7 - Unreasonable behavior
|
|
||||||
=========================
|
|
||||||
|
|
||||||
Sometimes the behavior exhibit by Postfix just does not match the
|
|
||||||
source code. Why can a program deviate from the instructions given
|
|
||||||
by its author? There are two possibilities.
|
|
||||||
|
|
||||||
1 - The compiler has messed up.
|
|
||||||
|
|
||||||
2 - The hardware has messed up.
|
|
||||||
|
|
||||||
In both cases, the program being executed is not the program that
|
|
||||||
was supposed to be executed, so anything can happen.
|
|
||||||
|
|
||||||
There is a third possibility:
|
|
||||||
|
|
||||||
3 - Bugs in system software (kernel or libraries).
|
|
||||||
|
|
||||||
Hardware-related failures happen erratically, and they usually do
|
|
||||||
not reproduce after power cycling and rebooting the system. There's
|
|
||||||
little I can do about bad hardware. Be sure to use hardware that
|
|
||||||
at the very least can detect memory errors. Otherwise, Postfix will
|
|
||||||
just be a sitting duck waiting to be hit by a bit error. Critical
|
|
||||||
systems deserve real hardware.
|
|
||||||
|
|
||||||
When a compiler messes up, the problem can be reproduced whenever
|
|
||||||
the resulting program is run. Compiler errors are most likely to
|
|
||||||
happen in the code optimizer. If a problem is reproducible across
|
|
||||||
power cycles and system reboots, it can be worthwhile to rebuild
|
|
||||||
Postfix with optimization disabled, and to see if optimization
|
|
||||||
makes a difference.
|
|
||||||
|
|
||||||
In order to compile Postfix with optimizations turned off:
|
|
||||||
|
|
||||||
% make tidy
|
|
||||||
% make makefiles OPT=
|
|
||||||
|
|
||||||
This produces a set of Makefiles that do not request compiler
|
|
||||||
optimization.
|
|
||||||
|
|
||||||
Once the makefiles are set up, build the software:
|
|
||||||
|
|
||||||
% make
|
|
||||||
% su
|
|
||||||
# make install
|
|
||||||
|
|
||||||
And see if the problem reproduces. If the problem goes away, talk
|
|
||||||
to your vendor.
|
|
|
@ -1,117 +0,0 @@
|
||||||
Purpose of this document
|
|
||||||
========================
|
|
||||||
|
|
||||||
This document describes the purpose of the Postfix fast ETRN service,
|
|
||||||
how the service works, and how it can be tested.
|
|
||||||
|
|
||||||
Other documents with information on this subject:
|
|
||||||
|
|
||||||
- conf/sample-flush.cf, sample configuration file
|
|
||||||
- conf/main.cf, sample configuration file
|
|
||||||
- flush(8), flush service implementation
|
|
||||||
|
|
||||||
The Postfix fast ETRN service
|
|
||||||
=============================
|
|
||||||
|
|
||||||
The SMTP ETRN command was designed for sites that have intermittent
|
|
||||||
Internet connectivity. With ETRN, a site can tell the mail server
|
|
||||||
of its provider to "Please deliver all my mail now".
|
|
||||||
|
|
||||||
Postfix versions before 20001005 implemented the ETRN command in
|
|
||||||
a lame manner: they simply attempted to deliver all queued mail.
|
|
||||||
This is slow on mail servers that queue mail for many customers.
|
|
||||||
|
|
||||||
As of version 20001005, Postfix has a fast ETRN implementation that
|
|
||||||
does not require Postfix to examine every queue file. The command
|
|
||||||
"sendmail -qR" is now implemented by sending an ETRN command to
|
|
||||||
the local SMTP server.
|
|
||||||
|
|
||||||
Postfix "fast ETRN/sendmail -qR" speeds up deliveries by attempting
|
|
||||||
to deliver only mail that is queued for a given destination site.
|
|
||||||
The old Postfix "slow ETRN" is still used as a fall-back method.
|
|
||||||
|
|
||||||
How Postfix fast ETRN works
|
|
||||||
===========================
|
|
||||||
|
|
||||||
The "fast ETRN" service uses the new "flush" daemon which maintains
|
|
||||||
per-destination logfiles of queued mail. These logfiles are kept
|
|
||||||
below /var/spool/postfix/flush. Each logfile is named after its
|
|
||||||
destination domain name. Only destinations with syntactically valid
|
|
||||||
domain names can have per-destination logfiles.
|
|
||||||
|
|
||||||
The behavior of the new "flush" daemon is controlled by parameters
|
|
||||||
in the main.cf configuration file.
|
|
||||||
|
|
||||||
By default, Postfix "fast ETRN/sendmail -qR" service is available
|
|
||||||
only for destinations that Postfix is willing to relay mail to:
|
|
||||||
|
|
||||||
fast_flush_domains = $relay_domains
|
|
||||||
|
|
||||||
The "relay_domains" parameter specifies what destinations Postfix
|
|
||||||
will relay to.
|
|
||||||
|
|
||||||
For destinations that are not eligible for the new "fast ETRN/sendmail
|
|
||||||
-qR" service, Postfix falls back to the old "slow ETRN" method
|
|
||||||
which attempts to deliver all queued mail.
|
|
||||||
|
|
||||||
To enable "fast ETRN/sendmail -qR" for some other destination, specify:
|
|
||||||
|
|
||||||
fast_flush_domains = $relay_domains, some.other.domain
|
|
||||||
|
|
||||||
To disable "fast ETRN/sendmail -qR", so that Postfix always uses
|
|
||||||
the old "slow ETRN" which delivers all queued mail, specify:
|
|
||||||
|
|
||||||
fast_flush_domains =
|
|
||||||
|
|
||||||
Testing the fast ETRN service
|
|
||||||
=============================
|
|
||||||
|
|
||||||
If you run Postfix with "fast ETRN" service for the very first
|
|
||||||
time, you need to run "sendmail -q" to populate the per-site deferred
|
|
||||||
mail logfiles. If you omit this step, the logfiles will eventually
|
|
||||||
become populated as Postfix routinely attempts to deliver delayed
|
|
||||||
mail, but that will take a couple hours.
|
|
||||||
|
|
||||||
After the "sendmail -q" has completed all delivery attempts (that
|
|
||||||
can take a while), you're ready to test the "fast ETRN" service.
|
|
||||||
Telnet to the Postfix SMTP server from a client that is allowed to
|
|
||||||
execute ETRN commands (by default, that's every client), and type:
|
|
||||||
|
|
||||||
helo my.client.name
|
|
||||||
etrn some.customer.domain
|
|
||||||
|
|
||||||
where "some.customer.domain" is the name of a domain that has a
|
|
||||||
non-empty logfile somewhere under /var/spool/postfix/flush.
|
|
||||||
|
|
||||||
In the maillog file, you should immediately see a couple of logfile
|
|
||||||
records, as evidence that the queue manager has opened queue files:
|
|
||||||
|
|
||||||
Oct 2 10:51:19 localhost postfix/qmgr[51999]: 682E8440A4:
|
|
||||||
from=<whatever>, size=12345, nrcpt=1 (queue active)
|
|
||||||
Oct 2 10:51:19 localhost postfix/qmgr[51999]: 02249440B7:
|
|
||||||
from=<whatever>, size=4711, nrcpt=1 (queue active)
|
|
||||||
|
|
||||||
What happens next depends on whether the destination is reachable.
|
|
||||||
If it's not reachable, the mail queue IDs will be added back to
|
|
||||||
the some.customer.domain logfile under /var/spool/postfix/flush.
|
|
||||||
|
|
||||||
Repeat the exercise with another domain that your server is willing
|
|
||||||
to relay to (domain listed in "relay_domains"), but that has no mail
|
|
||||||
queued.
|
|
||||||
|
|
||||||
helo my.client.name
|
|
||||||
etrn some.other.customer.domain
|
|
||||||
|
|
||||||
This time, the "etrn" command should trigger NO mail deliveries at
|
|
||||||
all. If this triggers delivery of all mail, then you used the wrong
|
|
||||||
domain name, or "fast ETRN" service is turned off.
|
|
||||||
|
|
||||||
Finally, repeat the exercise with a destination that your mail
|
|
||||||
server is not willing to relay to. It does not matter if your
|
|
||||||
server has mail queued for that destination.
|
|
||||||
|
|
||||||
helo my.client.name
|
|
||||||
etrn not.a.customer.domain
|
|
||||||
|
|
||||||
If your "fast ETRN" caching policy is left at its default setting,
|
|
||||||
then the "etrn" command should trigger delivery of all queued mail.
|
|
|
@ -1,216 +0,0 @@
|
||||||
This is a very first implementation of Postfix content filtering.
|
|
||||||
A Postfix content filter receives unfiltered mail from Postfix and
|
|
||||||
either bounces the mail or re-injects filtered mail back into Postfix.
|
|
||||||
|
|
||||||
It involves an incompatible change to queue file formats. Older
|
|
||||||
Postfix versions will reject mail that needs to be content filtered,
|
|
||||||
and will move the queue file to the "corrupt" mail queue subdirectory.
|
|
||||||
|
|
||||||
This document describes two approaches to content filtering.
|
|
||||||
|
|
||||||
Simple content filtering example
|
|
||||||
================================
|
|
||||||
|
|
||||||
The first example is simpler to set up, but is also more resource
|
|
||||||
intensive. With the shell script as shown you will lose a factor
|
|
||||||
of four in Postfix performance for transit mail that arrives and
|
|
||||||
leaves via SMTP. You will lose another factor in transit performance
|
|
||||||
for each additional temporary file that is created and deleted in
|
|
||||||
the process of content filtering. The performance impact is less
|
|
||||||
for mail that is submitted or delivered locally, because such
|
|
||||||
deliveries are not as fast as SMTP transit mail.
|
|
||||||
|
|
||||||
The example assumes that only mail arriving via SMTP needs to be
|
|
||||||
content filtered.
|
|
||||||
|
|
||||||
..................................
|
|
||||||
: Postfix :
|
|
||||||
----->smtpd \ /local---->
|
|
||||||
: -cleanup->queue- :
|
|
||||||
---->pickup / \smtp----->
|
|
||||||
^ : | :
|
|
||||||
| : \pipe-----+
|
|
||||||
| .................................. |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
+------sendmail<-------filter<---------+
|
|
||||||
|
|
||||||
1 - Create a dedicated local user account called "filter". The
|
|
||||||
user will never log in, and can be given a "*" password and
|
|
||||||
non-existent shell and home directory. This user handles all
|
|
||||||
potentially dangerous mail content - that is why it should be
|
|
||||||
a separate account.
|
|
||||||
|
|
||||||
2 - Create a directory /var/spool/filter that is accessible only
|
|
||||||
to the "filter" user. This is where the content filtering will
|
|
||||||
store its temporary files.
|
|
||||||
|
|
||||||
3 - Define a content filtering entry in the Postfix master file:
|
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
|
||||||
filter unix - n n - - pipe
|
|
||||||
flags=R user=filter argv=/some/where/filter -f ${sender} -- ${recipient}
|
|
||||||
|
|
||||||
The /some/where/filter program can be a simple shell script like this:
|
|
||||||
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Localize these
|
|
||||||
INSPECT_DIR=/var/spool/filter
|
|
||||||
SENDMAIL="/usr/sbin/sendmail -i"
|
|
||||||
|
|
||||||
# Exit codes from <sysexits.h>
|
|
||||||
EX_TEMPFAIL=75
|
|
||||||
EX_UNAVAILABLE=69
|
|
||||||
|
|
||||||
# Clean up when done or when aborting.
|
|
||||||
trap "rm -f in.$$" 0 1 2 3 15
|
|
||||||
|
|
||||||
# Start processing.
|
|
||||||
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
|
|
||||||
|
|
||||||
cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
|
|
||||||
|
|
||||||
# filter <in.$$ || { echo Message content rejected; exit $EX_UNAVAILABLE; }
|
|
||||||
|
|
||||||
$SENDMAIL "$@" <in.$$
|
|
||||||
|
|
||||||
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
|
|
||||||
mail cannot be captured to file, mail delivery is deferred by
|
|
||||||
terminating with exit status 75 (EX_TEMPFAIL). If the content
|
|
||||||
filter program finds a problem, the mail is bounced by terminating
|
|
||||||
the shell script with exit status 69 (EX_UNAVAILABLE). If the
|
|
||||||
content is OK, it is given as input to Postfix sendmail, and the
|
|
||||||
exit status of the filter command is whatever exit status Postfix
|
|
||||||
sendmail produces.
|
|
||||||
|
|
||||||
I suggest that you play with this script for a while until you are
|
|
||||||
satisfied with the results. Run it as the filter user, with a real
|
|
||||||
message (headers+body) as input:
|
|
||||||
|
|
||||||
% /some/where/filter -f sender recipient... <message-file
|
|
||||||
|
|
||||||
Turn on content filtering for mail arriving via SMTP only, by
|
|
||||||
appending "-o content_filter=filter:dummy" to the master.cf
|
|
||||||
entry that defines the Postfix SMTP server:
|
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
|
||||||
smtp inet ...stuff... smtpd
|
|
||||||
-o content_filter=filter:dummy
|
|
||||||
|
|
||||||
The content_filter configuration parameter accepts the same
|
|
||||||
syntax as the right-hand side in a Postfix transport table.
|
|
||||||
|
|
||||||
Simple content filter limitations
|
|
||||||
=================================
|
|
||||||
|
|
||||||
The problem with content filters like the one above is that they
|
|
||||||
are not very robust, because the software does not talk a well-defined
|
|
||||||
protocol with Postfix. If the filter shell script aborts because
|
|
||||||
the shell runs into some memory allocation problem, the script will
|
|
||||||
not produce a nice exit status as per /usr/include/sysexits.h and
|
|
||||||
mail will probably bounce. The same lack of robustness is possible
|
|
||||||
when the content filtering software itself runs into a resource
|
|
||||||
problem.
|
|
||||||
|
|
||||||
Advanced content filtering example
|
|
||||||
===================================
|
|
||||||
|
|
||||||
The second example is considerably more complex, but can give much
|
|
||||||
better performance, and is less likely to bounce mail when the
|
|
||||||
machine runs into a resource problem. This approach uses content
|
|
||||||
filtering software that can receive and deliver mail via SMTP.
|
|
||||||
You can expect to lose about a factor of two in Postfix performance
|
|
||||||
for transit mail that arrives and leaves via SMTP, provided that
|
|
||||||
you create no temporary files. Each temporary file adds another
|
|
||||||
factor to the performance loss.
|
|
||||||
|
|
||||||
We will set up a content filtering program that receives SMTP mail
|
|
||||||
via localhost port 10025, and that submits SMTP mail back into
|
|
||||||
Postfix via localhost port 10026.
|
|
||||||
|
|
||||||
..................................
|
|
||||||
: Postfix :
|
|
||||||
----->smtpd \ /local---->
|
|
||||||
: -cleanup->queue- :
|
|
||||||
---->pickup / ^ | \smtp----->
|
|
||||||
: | v :
|
|
||||||
: smtpd smtp :
|
|
||||||
: 10026 | :
|
|
||||||
......................|...........
|
|
||||||
^ |
|
|
||||||
| v
|
|
||||||
....|............
|
|
||||||
: | 10025 :
|
|
||||||
: filter :
|
|
||||||
: :
|
|
||||||
.................
|
|
||||||
|
|
||||||
To enable content filtering in this manner, specify in main.cf a
|
|
||||||
new parameter:
|
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
|
||||||
content_filter = smtp:localhost:10025
|
|
||||||
|
|
||||||
This causes Postfix to add one extra content filtering record to
|
|
||||||
each incoming mail message, with content smtp:localhost:10025.
|
|
||||||
You can use the same syntax as in the right-hand side of a Postfix
|
|
||||||
transport table. The content filtering records are added by the
|
|
||||||
smtpd and pickup servers.
|
|
||||||
|
|
||||||
When a queue file has content filtering information, the queue
|
|
||||||
manager will deliver the mail to the specified content filter
|
|
||||||
regardless of its final destination.
|
|
||||||
|
|
||||||
The content filter can be set up with the Postfix spawn service,
|
|
||||||
which is the Postfix equivalent of inetd. For example, to instantiate
|
|
||||||
up to 10 content filtering processes on demand:
|
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
|
||||||
localhost:10025 inet n n n - 10 spawn
|
|
||||||
user=filter argv=/some/where/filter localhost 10026
|
|
||||||
|
|
||||||
"filter" is a dedicated local user account. The user will never
|
|
||||||
log in, and can be given a "*" password and non-existent shell and
|
|
||||||
home directory. This user handles all potentially dangerous mail
|
|
||||||
content - that is why it should be a separate account.
|
|
||||||
|
|
||||||
In the above example, Postfix listens on port localhost:10025. If
|
|
||||||
you want to have your filter listening on port localhost:10025
|
|
||||||
instead of Postfix, then you must run your filter as a stand-alone
|
|
||||||
program.
|
|
||||||
|
|
||||||
Note: the localhost port 10025 SMTP server filter should announce
|
|
||||||
itself as "220 localhost...", to silence warnings in the log.
|
|
||||||
|
|
||||||
The /some/where/filter command is most likely a PERL script. PERL
|
|
||||||
has modules that make talking SMTP easy. The command-line specifies
|
|
||||||
that mail should be sent back into Postfix via localhost port 10026.
|
|
||||||
|
|
||||||
For now, it is left up to the Postfix users to come up with a
|
|
||||||
PERL/SMTP framework for Postfix content filtering. If done well,
|
|
||||||
it can be used with other mailers too, which is a nice spin-off.
|
|
||||||
|
|
||||||
The simplest content filter just copies SMTP commands and data
|
|
||||||
between its inputs and outputs. If it has a problem, all it has to
|
|
||||||
do is to reply to an input of `.' with `550 content rejected', and
|
|
||||||
to disconnect without sending `.' on the connection that injects
|
|
||||||
mail back into Postfix.
|
|
||||||
|
|
||||||
The job of the content filter is to either bounce mail with a
|
|
||||||
suitable diagnostic, or to feed the mail back into Postfix through
|
|
||||||
a dedicated listener on port localhost 10026:
|
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
|
||||||
localhost:10026 inet n - n - 10 smtpd
|
|
||||||
-o content_filter= -o myhostname=localhost.domain.name
|
|
||||||
|
|
||||||
This is just another SMTP server. It is configured NOT to request
|
|
||||||
content filtering for incoming mail, has the same process limit
|
|
||||||
as the filter master.cf entry, and is configured to use a different
|
|
||||||
hostname in the greeting message (this is necessary for testing
|
|
||||||
when I simply use no filtering program and let the SMTP content
|
|
||||||
filtering interfaces talk directly to each other).
|
|
|
@ -1,373 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Sample Postfix installation script. Run this from the top-level
|
|
||||||
# Postfix source directory.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc
|
|
||||||
umask 022
|
|
||||||
|
|
||||||
test -t 0 &&
|
|
||||||
cat <<EOF
|
|
||||||
|
|
||||||
Warning: this script replaces existing sendmail or Postfix programs.
|
|
||||||
Make backups if you want to be able to recover.
|
|
||||||
|
|
||||||
In addition to doing a fresh install, this script can change an
|
|
||||||
existing installation from using a world-writable maildrop to a
|
|
||||||
group-writable one. It cannot be used to change Postfix queue
|
|
||||||
file/directory ownership.
|
|
||||||
|
|
||||||
Before installing files, this script prompts you for some definitions.
|
|
||||||
Most definitions will be remembered, so you have to specify them
|
|
||||||
only once. All definitions have a reasonable default value.
|
|
||||||
|
|
||||||
install_root - prefix for installed file names (for package building)
|
|
||||||
|
|
||||||
tempdir - where to write scratch files
|
|
||||||
|
|
||||||
config_directory - directory with Postfix configuration files.
|
|
||||||
daemon_directory - directory with Postfix daemon programs.
|
|
||||||
command_directory - directory with Postfix administrative commands.
|
|
||||||
queue_directory - directory with Postfix queues.
|
|
||||||
|
|
||||||
sendmail_path - full pathname of the Postfix sendmail command.
|
|
||||||
newaliases_path - full pathname of the Postfix newaliases command.
|
|
||||||
mailq_path - full pathname of the Postfix mailq command.
|
|
||||||
|
|
||||||
mail_owner - owner of Postfix queue files.
|
|
||||||
|
|
||||||
setgid - groupname, e.g., postdrop (default: no). See INSTALL section 12.
|
|
||||||
manpages - "no" or path to man tree. Example: /usr/local/man.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# By now, shells must have functions. Ultrix users must use sh5 or lose.
|
|
||||||
# The following shell functions replace files/symlinks while minimizing
|
|
||||||
# the time that a file does not exist, and avoid copying over programs
|
|
||||||
# in order to not disturb running programs.
|
|
||||||
|
|
||||||
censored_ls() {
|
|
||||||
ls "$@" | egrep -v '^\.|/\.|CVS|RCS|SCCS'
|
|
||||||
}
|
|
||||||
|
|
||||||
compare_or_replace() {
|
|
||||||
(cmp $2 $3 >/dev/null 2>&1 && echo Skipping $3...) || {
|
|
||||||
echo Updating $3...
|
|
||||||
rm -f $tempdir/junk || exit 1
|
|
||||||
cp $2 $tempdir/junk || exit 1
|
|
||||||
chmod $1 $tempdir/junk || exit 1
|
|
||||||
mv -f $tempdir/junk $3 || exit 1
|
|
||||||
chmod $1 $3 || exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compare_or_symlink() {
|
|
||||||
(cmp $1 $2 >/dev/null 2>&1 && echo Skipping $2...) || {
|
|
||||||
echo Updating $2...
|
|
||||||
rm -f $tempdir/junk || exit 1
|
|
||||||
dest=`echo $1 | sed '
|
|
||||||
s;^'$install_root';;
|
|
||||||
s;/\./;/;g
|
|
||||||
s;//*;/;g
|
|
||||||
s;^/;;
|
|
||||||
'`
|
|
||||||
link=`echo $2 | sed '
|
|
||||||
s;^'$install_root';;
|
|
||||||
s;/\./;/;g
|
|
||||||
s;//*;/;g
|
|
||||||
s;^/;;
|
|
||||||
s;/[^/]*$;/;
|
|
||||||
s;[^/]*/;../;g
|
|
||||||
s;$;'$dest';
|
|
||||||
'`
|
|
||||||
ln -s $link $tempdir/junk || exit 1
|
|
||||||
mv -f $tempdir/junk $2 || {
|
|
||||||
echo Error: your mv command is unable to rename symlinks. 1>&2
|
|
||||||
echo If you run Linux, upgrade to GNU fileutils-4.0 or better, 1>&2
|
|
||||||
echo or choose a tempdir that is in the same file system as $2. 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compare_or_move() {
|
|
||||||
(cmp $2 $3 >/dev/null 2>&1 && echo Skipping $3...) || {
|
|
||||||
echo Updating $3...
|
|
||||||
mv -f $2 $3 || exit 1
|
|
||||||
chmod $1 $3 || exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# How to supress newlines in echo
|
|
||||||
|
|
||||||
case `echo -n` in
|
|
||||||
"") n=-n; c=;;
|
|
||||||
*) n=; c='\c';;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Default settings. Most are clobbered by remembered settings.
|
|
||||||
|
|
||||||
: ${install_root=/}
|
|
||||||
: ${tempdir=`pwd`}
|
|
||||||
: ${config_directory=/etc/postfix}
|
|
||||||
: ${daemon_directory=/usr/libexec/postfix}
|
|
||||||
: ${command_directory=/usr/sbin}
|
|
||||||
: ${queue_directory=/var/spool/postfix}
|
|
||||||
if [ -f /usr/lib/sendmail ]
|
|
||||||
then : ${sendmail_path=/usr/lib/sendmail}
|
|
||||||
else : ${sendmail_path=/usr/sbin/sendmail}
|
|
||||||
fi
|
|
||||||
: ${newaliases_path=/usr/bin/newaliases}
|
|
||||||
: ${mailq_path=/usr/bin/mailq}
|
|
||||||
: ${mail_owner=postfix}
|
|
||||||
: ${setgid=no}
|
|
||||||
: ${manpages=/usr/local/man}
|
|
||||||
|
|
||||||
# Find out the location of configuration files.
|
|
||||||
|
|
||||||
test -t 0 &&
|
|
||||||
for name in install_root tempdir config_directory
|
|
||||||
do
|
|
||||||
while :
|
|
||||||
do
|
|
||||||
eval echo \$n "$name: [\$$name]\ \$c"
|
|
||||||
read ans
|
|
||||||
case $ans in
|
|
||||||
"") break;;
|
|
||||||
*) eval $name=\$ans; break;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# Sanity checks
|
|
||||||
|
|
||||||
for path in $tempdir $install_root $config_directory
|
|
||||||
do
|
|
||||||
case $path in
|
|
||||||
/*) ;;
|
|
||||||
*) echo Error: $path should be an absolute path name. 1>&2; exit 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# In case some systems special-case pathnames beginning with //.
|
|
||||||
|
|
||||||
case $install_root in
|
|
||||||
/) install_root=
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Load defaults from existing installation.
|
|
||||||
|
|
||||||
CONFIG_DIRECTORY=$install_root$config_directory
|
|
||||||
|
|
||||||
test -f $CONFIG_DIRECTORY/main.cf && {
|
|
||||||
for name in daemon_directory command_directory queue_directory mail_owner
|
|
||||||
do
|
|
||||||
eval $name='"`bin/postconf -c $CONFIG_DIRECTORY -h $name`"' || kill $$
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -f $CONFIG_DIRECTORY/install.cf ]
|
|
||||||
then
|
|
||||||
. $CONFIG_DIRECTORY/install.cf
|
|
||||||
elif [ ! -t 0 -a -z "$install_root" ]
|
|
||||||
then
|
|
||||||
echo Non-interactive install needs the $CONFIG_DIRECTORY/install.cf 1>&2
|
|
||||||
echo file from a previous Postfix installation. 1>&2
|
|
||||||
echo 1>&2
|
|
||||||
echo Use interactive installation instead. 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Override default settings.
|
|
||||||
|
|
||||||
test -t 0 &&
|
|
||||||
for name in daemon_directory command_directory \
|
|
||||||
queue_directory sendmail_path newaliases_path mailq_path mail_owner\
|
|
||||||
setgid manpages
|
|
||||||
do
|
|
||||||
while :
|
|
||||||
do
|
|
||||||
eval echo \$n "$name: [\$$name]\ \$c"
|
|
||||||
read ans
|
|
||||||
case $ans in
|
|
||||||
"") break;;
|
|
||||||
*) eval $name=\$ans; break;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# Sanity checks
|
|
||||||
|
|
||||||
for path in $daemon_directory $command_directory \
|
|
||||||
$queue_directory $sendmail_path $newaliases_path $mailq_path $manpages
|
|
||||||
do
|
|
||||||
case $path in
|
|
||||||
/*) ;;
|
|
||||||
no) ;;
|
|
||||||
*) echo Error: $path should be an absolute path name. 1>&2; exit 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
test -d $tempdir || mkdir -p $tempdir || exit 1
|
|
||||||
|
|
||||||
( rm -f $tempdir/junk && touch $tempdir/junk ) || {
|
|
||||||
echo Error: you have no write permission to $tempdir. 1>&2
|
|
||||||
echo Specify an alternative directory for scratch files. 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
chown root $tempdir/junk >/dev/null 2>&1 || {
|
|
||||||
echo Error: you have no permission to change file ownership. 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
chown "$mail_owner" $tempdir/junk >/dev/null 2>&1 || {
|
|
||||||
echo Error: $mail_owner needs an entry in the passwd file. 1>&2
|
|
||||||
echo Remember, $mail_owner must have a dedicated user id and group id. 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
case $setgid in
|
|
||||||
no) ;;
|
|
||||||
*) chgrp "$setgid" $tempdir/junk >/dev/null 2>&1 || {
|
|
||||||
echo Error: $setgid needs an entry in the group file. 1>&2
|
|
||||||
echo Remember, $setgid must have a dedicated group id. 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
esac
|
|
||||||
|
|
||||||
rm -f $tempdir/junk
|
|
||||||
|
|
||||||
# Avoid clumsiness.
|
|
||||||
|
|
||||||
DAEMON_DIRECTORY=$install_root$daemon_directory
|
|
||||||
COMMAND_DIRECTORY=$install_root$command_directory
|
|
||||||
QUEUE_DIRECTORY=$install_root$queue_directory
|
|
||||||
SENDMAIL_PATH=$install_root$sendmail_path
|
|
||||||
NEWALIASES_PATH=$install_root$newaliases_path
|
|
||||||
MAILQ_PATH=$install_root$mailq_path
|
|
||||||
MANPAGES=$install_root$manpages
|
|
||||||
|
|
||||||
# Create any missing directories.
|
|
||||||
|
|
||||||
test -d $CONFIG_DIRECTORY || mkdir -p $CONFIG_DIRECTORY || exit 1
|
|
||||||
test -d $DAEMON_DIRECTORY || mkdir -p $DAEMON_DIRECTORY || exit 1
|
|
||||||
test -d $COMMAND_DIRECTORY || mkdir -p $COMMAND_DIRECTORY || exit 1
|
|
||||||
test -d $QUEUE_DIRECTORY || mkdir -p $QUEUE_DIRECTORY || exit 1
|
|
||||||
for path in $SENDMAIL_PATH $NEWALIASES_PATH $MAILQ_PATH
|
|
||||||
do
|
|
||||||
dir=`echo $path|sed -e 's/[/][/]*[^/]*$//' -e 's/^$/\//'`
|
|
||||||
test -d $dir || mkdir -p $dir || exit 1
|
|
||||||
done
|
|
||||||
|
|
||||||
# Install files. Be careful to not copy over running programs.
|
|
||||||
|
|
||||||
for file in `censored_ls libexec`
|
|
||||||
do
|
|
||||||
compare_or_replace a+x,go-w libexec/$file $DAEMON_DIRECTORY/$file || exit 1
|
|
||||||
done
|
|
||||||
|
|
||||||
for file in `censored_ls bin | grep '^post'`
|
|
||||||
do
|
|
||||||
compare_or_replace a+x,go-w bin/$file $COMMAND_DIRECTORY/$file || exit 1
|
|
||||||
done
|
|
||||||
|
|
||||||
test -f bin/sendmail && {
|
|
||||||
compare_or_replace a+x,go-w bin/sendmail $SENDMAIL_PATH || exit 1
|
|
||||||
compare_or_symlink $SENDMAIL_PATH $NEWALIASES_PATH
|
|
||||||
compare_or_symlink $SENDMAIL_PATH $MAILQ_PATH
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -f $CONFIG_DIRECTORY/main.cf ]
|
|
||||||
then
|
|
||||||
for file in LICENSE `cd conf; censored_ls sample*` main.cf.default
|
|
||||||
do
|
|
||||||
compare_or_replace a+r,go-w conf/$file $CONFIG_DIRECTORY/$file || exit 1
|
|
||||||
done
|
|
||||||
else
|
|
||||||
cp `censored_ls conf/*` $CONFIG_DIRECTORY || exit 1
|
|
||||||
chmod a+r,go-w $CONFIG_DIRECTORY/* || exit 1
|
|
||||||
|
|
||||||
test -z "$install_root" && need_config=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Save settings.
|
|
||||||
|
|
||||||
bin/postconf -c $CONFIG_DIRECTORY -e \
|
|
||||||
"daemon_directory = $daemon_directory" \
|
|
||||||
"command_directory = $command_directory" \
|
|
||||||
"queue_directory = $queue_directory" \
|
|
||||||
"mail_owner = $mail_owner" \
|
|
||||||
|| exit 1
|
|
||||||
|
|
||||||
(echo "# This file was generated by $0"
|
|
||||||
for name in sendmail_path newaliases_path mailq_path setgid manpages
|
|
||||||
do
|
|
||||||
eval echo $name=\$$name
|
|
||||||
done) >$tempdir/junk || exit 1
|
|
||||||
compare_or_move a+x,go-w $tempdir/junk $CONFIG_DIRECTORY/install.cf || exit 1
|
|
||||||
rm -f $tempdir/junk
|
|
||||||
|
|
||||||
# Use set-gid privileges instead of writable maildrop (optional).
|
|
||||||
|
|
||||||
test -d $QUEUE_DIRECTORY/maildrop || {
|
|
||||||
mkdir -p $QUEUE_DIRECTORY/maildrop || exit 1
|
|
||||||
chown $mail_owner $QUEUE_DIRECTORY/maildrop || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
case $setgid in
|
|
||||||
no)
|
|
||||||
chmod 1733 $QUEUE_DIRECTORY/maildrop || exit 1
|
|
||||||
chmod g-s $COMMAND_DIRECTORY/postdrop || exit 1
|
|
||||||
postfix_script=conf/postfix-script-nosgid
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
chgrp $setgid $COMMAND_DIRECTORY/postdrop || exit 1
|
|
||||||
chmod g+s $COMMAND_DIRECTORY/postdrop || exit 1
|
|
||||||
chgrp $setgid $QUEUE_DIRECTORY/maildrop || exit 1
|
|
||||||
chmod 1730 $QUEUE_DIRECTORY/maildrop || exit 1
|
|
||||||
postfix_script=conf/postfix-script-sgid
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
compare_or_replace a+x,go-w $postfix_script $CONFIG_DIRECTORY/postfix-script ||
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
# Install manual pages (optional).
|
|
||||||
|
|
||||||
case $manpages in
|
|
||||||
no) ;;
|
|
||||||
*) (
|
|
||||||
cd man || exit 1
|
|
||||||
for dir in man?
|
|
||||||
do test -d $MANPAGES/$dir || mkdir -p $MANPAGES/$dir || exit 1
|
|
||||||
done
|
|
||||||
for file in `censored_ls man?/*`
|
|
||||||
do
|
|
||||||
(test -f $MANPAGES/$file && cmp -s $file $MANPAGES/$file &&
|
|
||||||
echo Skipping $MANPAGES/$file...) || {
|
|
||||||
echo Updating $MANPAGES/$file...
|
|
||||||
rm -f $MANPAGES/$file
|
|
||||||
cp $file $MANPAGES/$file || exit 1
|
|
||||||
chmod 644 $MANPAGES/$file || exit 1
|
|
||||||
}
|
|
||||||
done
|
|
||||||
)
|
|
||||||
esac
|
|
||||||
|
|
||||||
test "$need_config" = 1 || exit 0
|
|
||||||
|
|
||||||
ALIASES=`bin/postconf -h alias_database | sed 's/^[^:]*://'`
|
|
||||||
cat <<EOF 1>&2
|
|
||||||
|
|
||||||
Warning: you still need to edit myorigin/mydestination/mynetworks
|
|
||||||
in $CONFIG_DIRECTORY/main.cf. See also html/faq.html for dialup
|
|
||||||
sites or for sites inside a firewalled network.
|
|
||||||
|
|
||||||
BTW: Check your $ALIASES file and be sure to set up aliases
|
|
||||||
for root and postmaster that direct mail to a real person, then
|
|
||||||
run $NEWALIASES_PATH.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,328 +0,0 @@
|
||||||
LDAP SUPPORT IN POSTFIX
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Postfix can use an LDAP directory as a source for any of its lookups:
|
|
||||||
aliases, virtual, canonical, etc. This allows you to keep information
|
|
||||||
for your mail service in a replicated network database with fine-grained
|
|
||||||
access controls. By not storing it locally on the mail server, the
|
|
||||||
administrators can maintain it from anywhere, and the users can control
|
|
||||||
whatever bits of it you think appropriate. You can have multiple mail
|
|
||||||
servers using the same information, without the hassle and delay of
|
|
||||||
having to copy it to each.
|
|
||||||
|
|
||||||
BUILDING WITH LDAP SUPPORT
|
|
||||||
==========================
|
|
||||||
|
|
||||||
You need to have LDAP libraries and include files installed somewhere on
|
|
||||||
your system, and you need to configure the Postfix Makefiles
|
|
||||||
accordingly.
|
|
||||||
|
|
||||||
If you're using the libraries from the UM distribution
|
|
||||||
(http://www.umich.edu/~dirsvcs/ldap/ldap.html) or OpenLDAP
|
|
||||||
(http://www.openldap.org), something like this in the top level of your
|
|
||||||
Postfix source tree should work:
|
|
||||||
|
|
||||||
% make tidy
|
|
||||||
% make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \
|
|
||||||
AUXLIBS="-L/usr/local/lib -lldap -L/usr/local/lib -llber"
|
|
||||||
|
|
||||||
On Solaris 2.x you may have to specify run-time link information,
|
|
||||||
otherwise ld.so will not find some of the shared libraries:
|
|
||||||
|
|
||||||
% make tidy
|
|
||||||
% make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \
|
|
||||||
AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lldap \
|
|
||||||
-L/usr/local/lib -R/usr/local/lib -llber"
|
|
||||||
|
|
||||||
The 'make tidy' command is needed only if you have previously built
|
|
||||||
Postfix without LDAP support.
|
|
||||||
|
|
||||||
Instead of '/usr/local' specify the actual locations of your LDAP
|
|
||||||
include files and libraries. Be sure to not mix LDAP include files
|
|
||||||
and LDAP libraries of different versions!!
|
|
||||||
|
|
||||||
If your LDAP libraries were built with Kerberos support, you'll also
|
|
||||||
need to include your Kerberos libraries in this line. Note that the KTH
|
|
||||||
Kerberos IV libraries might conflict with Postfix's lib/libdns.a, which
|
|
||||||
defines dns_lookup. If that happens, you'll probably want to link with
|
|
||||||
LDAP libraries that lack Kerberos support just to build Postfix, as it
|
|
||||||
doesn't support Kerberos binds to the LDAP server anyway. Sorry about
|
|
||||||
the bother.
|
|
||||||
|
|
||||||
If you're using one of the Netscape LDAP SDKs, you'll need to change the
|
|
||||||
AUXLIBS line to point to libldap10.so or libldapssl30.so or whatever you
|
|
||||||
have, and you may need to use the appropriate linker option (e.g. '-R')
|
|
||||||
so the executables can find it at runtime.
|
|
||||||
|
|
||||||
CONFIGURING LDAP LOOKUPS
|
|
||||||
========================
|
|
||||||
|
|
||||||
In order to use LDAP lookups, define at least one LDAP source as a table
|
|
||||||
lookup in main.cf, for example:
|
|
||||||
|
|
||||||
alias_maps = hash:/etc/aliases, ldap:ldapsource
|
|
||||||
|
|
||||||
Each LDAP source can have the following parameters, which should be
|
|
||||||
prefixed in main.cf with the name you've given the source in its
|
|
||||||
definition and an underscore. To continue the example, the first
|
|
||||||
parameter below, "server_host", would be defined in main.cf as
|
|
||||||
"ldapsource_server_host". Defaults are given in parentheses:
|
|
||||||
|
|
||||||
server_host (localhost)
|
|
||||||
The name of the host running the LDAP server, e.g.
|
|
||||||
ldapsource_server_host = ldap.your.com
|
|
||||||
It should be possible with all the libraries mentioned above to
|
|
||||||
specify multiple servers separated by spaces, with the libraries
|
|
||||||
trying them in order should the first one fail. It should also
|
|
||||||
be possible to give each server in the list a different port, by
|
|
||||||
naming them like "ldap.your.com:1444".
|
|
||||||
|
|
||||||
server_port (389)
|
|
||||||
The port the LDAP server listens on, e.g.
|
|
||||||
ldapsource_server_port = 778
|
|
||||||
|
|
||||||
search_base (No default; you must configure this.)
|
|
||||||
The base at which to conduct the search, e.g.
|
|
||||||
ldapsource_search_base = dc=your, dc=com
|
|
||||||
|
|
||||||
timeout (10 seconds)
|
|
||||||
The number of seconds a search can take before timing out, e.g.
|
|
||||||
ldapsource_timeout = 5
|
|
||||||
|
|
||||||
query_filter (mailacceptinggeneralid=%s)
|
|
||||||
The RFC2254 filter used to search the directory, where %s is a
|
|
||||||
substitute for the address Postfix is trying to resolve, e.g.
|
|
||||||
ldapsource_query_filter = (&(mail=%s)(paid_up=true))
|
|
||||||
|
|
||||||
domain (Default is to ignore this.)
|
|
||||||
This is a list of domain names, paths to files, or dictionaries.
|
|
||||||
If specified, only lookups for the domains on this list will be
|
|
||||||
performed. This means that the LDAP map won't get searched for
|
|
||||||
'user', nor will it get searched for any domain not listed. This
|
|
||||||
can significantly reduce the query load on the LDAP server.
|
|
||||||
ldapsource_domain = postfix.org, hash:/etc/postfix/searchdomains
|
|
||||||
|
|
||||||
result_attribute (maildrop)
|
|
||||||
The attribute(s) Postfix will read from any directory entries
|
|
||||||
returned by the lookup, to be resolved to an email address.
|
|
||||||
ldapsource_result_attribute = mailbox,maildrop
|
|
||||||
|
|
||||||
special_result_attribute (No default)
|
|
||||||
The attribute(s) of directory entries that can contain DNs or URLs.
|
|
||||||
If found, a recursive subsequent search is done using their values.
|
|
||||||
ldapsource_special_result_attribute = member
|
|
||||||
|
|
||||||
scope (sub)
|
|
||||||
The LDAP search scope: sub, base, or one. These translate into
|
|
||||||
LDAP_SCOPE_SUBTREE, LDAP_SCOPE_BASE, and LDAP_SCOPE_ONELEVEL.
|
|
||||||
|
|
||||||
bind (yes)
|
|
||||||
Whether or not to bind to the LDAP server. Newer LDAP
|
|
||||||
implementations don't require clients to bind, which saves
|
|
||||||
time. Example:
|
|
||||||
ldapsource_bind = no
|
|
||||||
|
|
||||||
If you do need to bind, you might consider configuring Postfix
|
|
||||||
to connect to the local machine on a port that's an SSL tunnel
|
|
||||||
to your LDAP server. If your LDAP server doesn't natively
|
|
||||||
support SSL, put a tunnel (wrapper, proxy, whatever you want to
|
|
||||||
call it) on that system too. This should prevent the password
|
|
||||||
from traversing the network in the clear.
|
|
||||||
|
|
||||||
bind_dn ("")
|
|
||||||
If you do have to bind, do it with this distinguished name.
|
|
||||||
Example:
|
|
||||||
ldapsource_bind_dn = uid=postfix, dc=your, dc=com
|
|
||||||
|
|
||||||
bind_pw ("")
|
|
||||||
The password for the distinguished name above. If you have to
|
|
||||||
use this, you probably want to make main.cf readable only by
|
|
||||||
the Postfix user. Example:
|
|
||||||
ldapsource_bind_pw = postfixpw
|
|
||||||
|
|
||||||
cache (no)
|
|
||||||
Whether to use a client-side cache for the LDAP connection. See
|
|
||||||
ldap_enable_cache(3). It's off by default.
|
|
||||||
|
|
||||||
cache_expiry (30 seconds)
|
|
||||||
If the client-side cache is enabled, cached results will expire
|
|
||||||
after this many seconds.
|
|
||||||
|
|
||||||
cache_size (32768 bytes)
|
|
||||||
If the client-side cache is enabled, this is its size in bytes.
|
|
||||||
|
|
||||||
dereference (0)
|
|
||||||
When to dereference LDAP aliases. (Note that this has nothing
|
|
||||||
do with Postfix aliases.) The permitted values are those
|
|
||||||
legal for the OpenLDAP/UM LDAP implementations:
|
|
||||||
|
|
||||||
0 never
|
|
||||||
1 when searching
|
|
||||||
2 when locating the base object for the search
|
|
||||||
3 always
|
|
||||||
|
|
||||||
See ldap.h or the ldap_open(3) or ldapsearch(1) man pages for
|
|
||||||
more information. And if you're using an LDAP package that has
|
|
||||||
other possible values, please bring it to the attention of the
|
|
||||||
postfix-users@postfix.org mailing list.
|
|
||||||
|
|
||||||
Don't use quotes in these variables; at least, not until the Postfix
|
|
||||||
configuration routines understand how to deal with quoted strings.
|
|
||||||
|
|
||||||
EXAMPLES
|
|
||||||
========
|
|
||||||
|
|
||||||
ALIASES
|
|
||||||
-------
|
|
||||||
|
|
||||||
Here's a basic example for using LDAP to look up aliases. Assume that in
|
|
||||||
main.cf, you have these configuration parameters defined:
|
|
||||||
|
|
||||||
alias_maps = hash:/etc/aliases, ldap:ldapsource
|
|
||||||
ldapsource_server_host = ldap.my.com
|
|
||||||
ldapsource_search_base = dc=my, dc=com
|
|
||||||
|
|
||||||
Upon receiving mail for a local address "ldapuser" that isn't found in
|
|
||||||
the /etc/aliases database, Postfix will search the LDAP server listening
|
|
||||||
at port 389 on ldap.my.com. It will bind anonymously, search for any
|
|
||||||
directory entries whose mailacceptinggeneralid attribute is "ldapuser",
|
|
||||||
read the "maildrop" attributes of those found, and build a list of their
|
|
||||||
maildrops, which will be treated as RFC822 addresses to which the
|
|
||||||
message will be delivered.
|
|
||||||
|
|
||||||
VIRTUAL DOMAINS/ADDRESSES
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
If you want to keep information for virtual lookups in your directory,
|
|
||||||
it's only a little more complicated. First you need to make sure Postfix
|
|
||||||
knows about the virtual domain. An easy way to do that is to add the
|
|
||||||
domain to the mailacceptinggeneralid attribute of some entry in the
|
|
||||||
directory. Next you'll want to make sure all of your virtual recipients'
|
|
||||||
mailacceptinggeneralid attributes are fully qualified with their virtual
|
|
||||||
domains. Finally, if you want to designate a directory entry as the
|
|
||||||
default user for a virtual domain, just give it an additional
|
|
||||||
mailacceptinggeneralid (or the equivalent in your directory) of
|
|
||||||
"@virtual.dom". That's right, no user part. If you don't want a catchall
|
|
||||||
user, omit this step and mail to unknown users in the domain will simply
|
|
||||||
bounce.
|
|
||||||
|
|
||||||
If you're using a version of Postfix newer than 19991226, that should do
|
|
||||||
it. If not, you also need to add your virtual domains to relay_domains.
|
|
||||||
Simply add "$virtual_maps" to your relay_domains line. Then you can use
|
|
||||||
the same map you use to find virtual recipients to determine if a domain
|
|
||||||
is a valid virtual domain and should be allowed to relay.
|
|
||||||
|
|
||||||
In summary, you might have a catchall user for a virtual domain that
|
|
||||||
looks like this:
|
|
||||||
|
|
||||||
dn: cn=defaultrecipient, dc=fake, dc=dom
|
|
||||||
objectclass: top
|
|
||||||
objectclass: virtualaccount
|
|
||||||
cn: defaultrecipient
|
|
||||||
owner: uid=root, dc=someserver, dc=isp, dc=dom
|
|
||||||
1 -> mailacceptinggeneralid: fake.dom
|
|
||||||
2 -> mailacceptinggeneralid: @fake.dom
|
|
||||||
3 -> maildrop: realuser@real.dom
|
|
||||||
|
|
||||||
1: Postfix knows fake.dom is a valid virtual domain when it looks for
|
|
||||||
this and gets something (the maildrop) back.
|
|
||||||
|
|
||||||
2: This causes any mail for unknown users in fake.dom to go to this entry ...
|
|
||||||
|
|
||||||
3: ... and then to its maildrop.
|
|
||||||
|
|
||||||
Normal users might simply have one mailacceptinggeneralid and maildrop,
|
|
||||||
e.g. "normaluser@fake.dom" and "normaluser@real.dom".
|
|
||||||
|
|
||||||
OTHER USES
|
|
||||||
----------
|
|
||||||
|
|
||||||
Other common uses for LDAP lookups include rewriting senders and
|
|
||||||
recipients with Postfix' canonical lookups, for example in order to make
|
|
||||||
mail leaving your site appear to be coming from "First.Last@site.dom"
|
|
||||||
instead of "userid@site.dom".
|
|
||||||
|
|
||||||
NOTES AND THINGS TO THINK ABOUT
|
|
||||||
===============================
|
|
||||||
|
|
||||||
- The bits of schema and attribute names used in this document are just
|
|
||||||
examples. There's nothing special about them, other than that some are
|
|
||||||
the defaults in the LDAP configuration parameters. You can use
|
|
||||||
whatever schema you like, and configure Postfix accordingly.
|
|
||||||
|
|
||||||
- You probably want to make sure that mailacceptinggeneralids are
|
|
||||||
unique, and that not just anyone can specify theirs as postmaster or
|
|
||||||
root, say.
|
|
||||||
|
|
||||||
- An entry can have an arbitrary number of mailacceptinggeneralids or
|
|
||||||
maildrops. Maildrops can also be comma-separated lists of addresses.
|
|
||||||
They will all be found and returned by the lookups. For example, you
|
|
||||||
could define an entry intended for use as a mailing list that looks
|
|
||||||
like this (Warning! Schema made up just for this example):
|
|
||||||
|
|
||||||
dn: cn=Accounting Staff List, dc=my, dc=com
|
|
||||||
cn: Accounting Staff List
|
|
||||||
o: my.com
|
|
||||||
objectclass: maillist
|
|
||||||
mailacceptinggeneralid: accountingstaff
|
|
||||||
mailacceptinggeneralid: accounting-staff
|
|
||||||
maildrop: mylist-owner
|
|
||||||
maildrop: an-accountant
|
|
||||||
maildrop: some-other-accountant
|
|
||||||
maildrop: this, that, theother
|
|
||||||
|
|
||||||
- If you use an LDAP map for lookups other than aliases, you may have to
|
|
||||||
make sure the lookup makes sense. In the case of virtual lookups,
|
|
||||||
maildrops other than mail addresses are pretty useless, because
|
|
||||||
Postfix can't know how to set the ownership for program or file
|
|
||||||
delivery. Your query_filter should probably look something like this:
|
|
||||||
|
|
||||||
virtual_query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")(maildrop="*:*")(maildrop="*/*"))))
|
|
||||||
|
|
||||||
- And for that matter, even for aliases, you may not want users able to
|
|
||||||
specify their maildrops as programs, includes, etc. This might be
|
|
||||||
particularly pertinent on a "sealed" server where they don't have
|
|
||||||
local UNIX accounts, but exist only in LDAP and Cyrus. You might allow
|
|
||||||
the fun stuff only for directory entries owned by an administrative
|
|
||||||
account:
|
|
||||||
|
|
||||||
local_query_filter = (&(mailacceptinggeneralid=%s)(|(!(maildrop="*|*")(maildrop="*:*")(maildrop="*/*"))(owner=cn=root, dc=your, dc=com)))
|
|
||||||
|
|
||||||
So that if the object had a program as its maildrop and weren't owned
|
|
||||||
by "cn=root" it wouldn't be returned as a valid local user. This will
|
|
||||||
require some thought on your part to implement safely, considering the
|
|
||||||
ramifications of this type of delivery. You may decide it's not worth
|
|
||||||
the bother to allow any of that nonsense in LDAP lookups, ban it in
|
|
||||||
the query_filter, and keep things like majordomo lists in local alias
|
|
||||||
databases.
|
|
||||||
|
|
||||||
- LDAP lookups are slower than local DB or DBM lookups. For most sites
|
|
||||||
they won't be a bottleneck, but it's a good idea to know how to tune
|
|
||||||
your directory service.
|
|
||||||
|
|
||||||
FEEDBACK
|
|
||||||
========
|
|
||||||
|
|
||||||
If you have questions, send them to postfix-users@postfix.org. Please
|
|
||||||
include relevant information about your Postfix setup: LDAP-related
|
|
||||||
output from postconf, which LDAP libraries you built with, and which
|
|
||||||
directory server you're using. If your question involves your directory
|
|
||||||
contents, please include the applicable bits of some directory entries.
|
|
||||||
|
|
||||||
CREDITS
|
|
||||||
=======
|
|
||||||
|
|
||||||
Manuel Guesdon: Spotted a bug with the ldapsource_timeout attribute.
|
|
||||||
John Hensley: Multiple LDAP sources with more configurable attributes.
|
|
||||||
Carsten Hoeger: Search scope handling.
|
|
||||||
LaMont Jones: Domain restriction, URL and DN searches, multiple result
|
|
||||||
attributes.
|
|
||||||
Mike Mattice: Alias dereferencing control.
|
|
||||||
Hery Rakotoarisoa: Patches for LDAPv3 updating.
|
|
||||||
Prabhat K Singh: Wrote the initial Postfix LDAP lookups and connection caching.
|
|
||||||
Keith Stevenson: RFC 2254 escaping in queries.
|
|
||||||
Samuel Tardieu: Noticed that searches could include wildcards, prompting
|
|
||||||
the work on RFC 2254 escaping in queries. Spotted a bug
|
|
||||||
in binding.
|
|
||||||
|
|
||||||
And of course Wietse.
|
|
|
@ -1,17 +0,0 @@
|
||||||
LINUX PORTABILITY
|
|
||||||
=================
|
|
||||||
|
|
||||||
On RedHat Linux 7.0, you must install the db3-devel RPM before you
|
|
||||||
can compile the Postfix source code.
|
|
||||||
|
|
||||||
LINUX SYSLOGD PERFORMANCE
|
|
||||||
=========================
|
|
||||||
|
|
||||||
LINUX syslogd uses synchronous writes by default, which is very
|
|
||||||
expensive. For services such as mail it is recommended that you
|
|
||||||
disable synchronous logfile writes by editing /etc/syslog.conf and
|
|
||||||
by prepending a - to the logfile name:
|
|
||||||
|
|
||||||
mail.* -/var/log/mail.log
|
|
||||||
|
|
||||||
Send a "kill -HUP" to the syslogd to make the change effective.
|
|
|
@ -1,466 +0,0 @@
|
||||||
[This file still needs to be updated - some information is obsolete]
|
|
||||||
|
|
||||||
1 - Postfix LMTP support
|
|
||||||
========================
|
|
||||||
|
|
||||||
LMTP stands for Local Mail Transfer Protocol, and is detailed in
|
|
||||||
RFC2033. Postfix uses this protocol to communicate with the final
|
|
||||||
delivery agent, which may run on the local host or a remote host.
|
|
||||||
|
|
||||||
This protocol opens up interesting possibilities: one Postfix front
|
|
||||||
end machine can drive multiple mailbox back end machines over LMTP.
|
|
||||||
As the mail load increases, you add more Postfix front end systems
|
|
||||||
and more LMTP mailbox back end systems. This is the model that I
|
|
||||||
had in mind when I began drafting the design for Postfix - a scalable
|
|
||||||
architecture that allows you to keep adding SMTP servers and mailbox
|
|
||||||
servers painlessly.
|
|
||||||
|
|
||||||
Such a distributed architecture needs glue to keep things together.
|
|
||||||
You can use a networked database LDAP or mysql to share the user
|
|
||||||
database among the front end and back end systems. Use a replicated
|
|
||||||
database so that no machine becomes a single point of failure for
|
|
||||||
the entire mail infrastructure.
|
|
||||||
|
|
||||||
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, who also revised
|
|
||||||
much of the documentation. Wietse Venema reduced the code to its
|
|
||||||
present shape.
|
|
||||||
|
|
||||||
|
|
||||||
2 - Overview
|
|
||||||
============
|
|
||||||
|
|
||||||
Most of the examples in this document involve the CMU Cyrus IMAP/POP
|
|
||||||
server, available from:
|
|
||||||
|
|
||||||
http://asg.web.cmu.edu/cyrus/
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
o Connections over UNIX-domain sockets limit delivery to LMTP
|
|
||||||
servers running on the same machine.
|
|
||||||
|
|
||||||
o Connections over TCP sockets allow you to deliver to LMTP
|
|
||||||
servers across a local network.
|
|
||||||
|
|
||||||
The precise syntax for UNIX-domain and TCP connection endpoints is
|
|
||||||
given in the lmtp(8) manual page. Examples are also given in the
|
|
||||||
text below.
|
|
||||||
|
|
||||||
Both socket flavors can be specified in either the Postfix main.cf
|
|
||||||
file (see section 5) or in a Postfix transport map (section 6).
|
|
||||||
What is the best approach for you 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 in performance with these different approaches.
|
|
||||||
|
|
||||||
3 - LMTP over UNIX-domain sockets
|
|
||||||
=================================
|
|
||||||
|
|
||||||
A UNIX-domain socket is specified as the socket type ("unix") and
|
|
||||||
a name in the local file system:
|
|
||||||
|
|
||||||
unix:/path/name
|
|
||||||
|
|
||||||
The "/path/name" part should be the name of a socket created by
|
|
||||||
the LMTP server on the local machine. See the specific examples
|
|
||||||
later in this document.
|
|
||||||
|
|
||||||
NOTE:
|
|
||||||
|
|
||||||
If you run the lmtp client chrooted, the interpretation of the
|
|
||||||
/path/name is relative to the Postfix queue directory (typically,
|
|
||||||
/var/spool/postfix).
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
4 - LMTP over TCP sockets
|
|
||||||
=========================
|
|
||||||
|
|
||||||
A TCP destination is specified as the socket type ("inet"), the
|
|
||||||
destination hostname and the TCP port:
|
|
||||||
|
|
||||||
inet:hostname:port
|
|
||||||
|
|
||||||
The "inet:" part can be omitted, as it is the default socket type.
|
|
||||||
|
|
||||||
The destination port can be omitted as well. Currently the default
|
|
||||||
TCP port number for this type of connection is 24, but this can be
|
|
||||||
customized in the "/etc/services" file. Specific examples are
|
|
||||||
given later in this document.
|
|
||||||
|
|
||||||
NOTE:
|
|
||||||
|
|
||||||
With connections over TCP sockets, later Cyrus LMTP server
|
|
||||||
implementations insist on SASL-style authentication. This means
|
|
||||||
that Postfix must be built with SASL support (see SASL_README).
|
|
||||||
The examples below show how to enable this in the Postfix LMTP
|
|
||||||
client.
|
|
||||||
|
|
||||||
Some Cyrus LMTP server implementations do not allow SASL-style
|
|
||||||
authentication via plaintext passwords. You will have to jump
|
|
||||||
some extra hoops in order to enable MD5 password support, or
|
|
||||||
you will have to wait until this restriction is relaxed.
|
|
||||||
|
|
||||||
|
|
||||||
5 - Configuring LMTP using main.cf configuration
|
|
||||||
================================================
|
|
||||||
|
|
||||||
This is the simplest LMTP configuration.
|
|
||||||
|
|
||||||
5.1 - Delivery mechanisms
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Postfix main.cf supports three mechanisms to deliver mail over
|
|
||||||
LMTP. Each method can use UNIX-domain or TCP sockets as described
|
|
||||||
in a later section.
|
|
||||||
|
|
||||||
main.cf mechanism 1
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
mailbox_transport = lmtp:unix:/path/name (UNIX-domain socket example)
|
|
||||||
mailbox_transport = lmtp:hostname:port (TCP socket example)
|
|
||||||
|
|
||||||
Mail that resolves as local (domain is listed in $mydestination)
|
|
||||||
is given to the Postfix local delivery agent. The Postfix local
|
|
||||||
delivery agent expands aliases and .forward files, and delegates
|
|
||||||
mailbox delivery to the LMTP server.
|
|
||||||
|
|
||||||
main.cf mechanism 2
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
local_transport = lmtp:unix:/path/name (UNIX-domain socket example)
|
|
||||||
local_transport = lmtp:hostname:port (TCP socket example)
|
|
||||||
|
|
||||||
Mail that resolves as local (domain is listed in $mydestination)
|
|
||||||
is directly given to the LMTP server. The mail is not processed
|
|
||||||
by the Postfix local delivery agent; therefore aliases and .forward
|
|
||||||
files are not processed.
|
|
||||||
|
|
||||||
main.cf mechanism 3
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
fallback_transport = lmtp:unix:/path/name (UNIX-domain socket example)
|
|
||||||
fallback_transport = lmtp:hostname:port (TCP socket example)
|
|
||||||
|
|
||||||
Mail that resolves as local (domain is listed in $mydestination)
|
|
||||||
is given to the Postfix local delivery agent. The Postfix local
|
|
||||||
delivery agent processes aliases and .forward files, and delivers
|
|
||||||
to /var[/spool]/mail/$user for users that have a UNIX account.
|
|
||||||
Mail for other local users is delegated to the LMTP server.
|
|
||||||
|
|
||||||
5.2 - Examples
|
|
||||||
--------------
|
|
||||||
|
|
||||||
5.2.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, the Postfix local delivery agent expands aliases
|
|
||||||
and .forward files, and delegates mailbox delivery to the Cyrus
|
|
||||||
lmtpd server via the socket "/var/imap/socket/lmtp".
|
|
||||||
|
|
||||||
5.2.2 - LMTP over TCP sockets
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
For this example, suppose the following files are configured
|
|
||||||
thusly:
|
|
||||||
|
|
||||||
/etc/cyrus.conf:
|
|
||||||
|
|
||||||
SERVICES {
|
|
||||||
...
|
|
||||||
lmtp cmd="lmtpd" listen="127.0.0.1:lmtp" prefork=0
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/etc/services:
|
|
||||||
|
|
||||||
lmtp 24/tcp
|
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
|
||||||
|
|
||||||
mailbox_transport = lmtp:localhost
|
|
||||||
lmtp_sasl_auth_enable = yes
|
|
||||||
lmtp_sasl_password_maps = hash:/etc/postfix/lmtp_sasl_pass
|
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
|
||||||
|
|
||||||
lmtp unix - - n - - lmtp
|
|
||||||
|
|
||||||
/etc/postfix/lmtp_sasl_pass:
|
|
||||||
localhost.my.domain username:password
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
With the above settings, the Postfix local delivery agent expands
|
|
||||||
aliases and .forward files, and delegates mailbox delivery to the
|
|
||||||
the Cyrus LMTP server. Postfix makes a connection to port 24 on
|
|
||||||
the local host, subsequently transmitting the message to the lmtpd
|
|
||||||
server managed by the Cyrus master process.
|
|
||||||
|
|
||||||
|
|
||||||
6 - Configuring LMTP 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,
|
|
||||||
instead of depending on delegation by the Postfix local delivery
|
|
||||||
agent.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
For details of the Cyrus LMTP server configuration, see section 5.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
7 - 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.
|
|
||||||
|
|
||||||
|
|
||||||
8 - 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: the Postfix local delivery agent is
|
|
||||||
designed to deliver 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 virtual table to
|
|
||||||
map these users to the appropriate LMTP destination (at the time
|
|
||||||
of writing, the Postfix transport table supports only per-domain
|
|
||||||
routing, and not per-recipient routing).
|
|
||||||
|
|
||||||
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 (see section 5.1, delivery
|
|
||||||
mechanism 2). If the site is to run software via aliases, like
|
|
||||||
most Mailing List Management (MLM) software, a more complex solution
|
|
||||||
is required. A virtual table should do the trick.
|
|
||||||
|
|
||||||
As an example, suppose we wanted to support single instance message
|
|
||||||
store delivery for the hosted (not local) 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.
|
|
||||||
|
|
||||||
|
|
||||||
9 - Improving connection caching performance
|
|
||||||
============================================
|
|
||||||
|
|
||||||
After delivering a message via LMTP, Postfix will keep the connection
|
|
||||||
open for a while, so that it can be reused for a subsequent delivery.
|
|
||||||
This reduces overhead of LMTP servers that create one process per
|
|
||||||
connection.
|
|
||||||
|
|
||||||
For LMTP connection caching to work, the Postfix LMTP client should
|
|
||||||
not switch destination hosts. This is no problem when you run only
|
|
||||||
one LMTP server. However, if you run multiple LMTP servers, this
|
|
||||||
can be an issue.
|
|
||||||
|
|
||||||
You can prevent the LMTP client from switching between servers by
|
|
||||||
configuring a separate LMTP delivery transport for each LMTP server:
|
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
|
||||||
|
|
||||||
lmtp1 unix - - n - - lmtp
|
|
||||||
lmtp2 unix - - n - - lmtp
|
|
||||||
. . . . . . . .
|
|
||||||
|
|
||||||
Configure transport table entries such that the lmtp1 mail delivery
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
10 - 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 24/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. :-)
|
|
|
@ -1,2 +0,0 @@
|
||||||
See the files in auxiliary/MacOSX for hints and tips to set up
|
|
||||||
Postfix.
|
|
|
@ -1,92 +0,0 @@
|
||||||
[Code contributed by Scott Cotton and Joshua Marcus, IC Group, Inc.]
|
|
||||||
|
|
||||||
We've written code to add a mysql map type. It utilizes the mysql
|
|
||||||
client library, which can be obtained from:
|
|
||||||
|
|
||||||
http://www.mysql.com/downloads/
|
|
||||||
http://sourceforge.net/projects/mysql/
|
|
||||||
|
|
||||||
In order to build postfix with mysql map support, you will need to add
|
|
||||||
-DHAS_MYSQL and -I for the directory containing the mysql headers, and
|
|
||||||
the mysqlclient library (and libm) to AUXLIBS, for example:
|
|
||||||
|
|
||||||
make -f Makefile.init makefiles \
|
|
||||||
'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \
|
|
||||||
'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lz -lm'
|
|
||||||
|
|
||||||
then, just run 'make'. This requires libz, the compression library.
|
|
||||||
Older mysql implementations build without libz.
|
|
||||||
|
|
||||||
Postfix installations which may benefit from using mysql map types
|
|
||||||
include sites that have a need for instantaneous updates of
|
|
||||||
forwarding, and sites that may benefit from having mail exchangers
|
|
||||||
reference a networked database, possibly working in conjunction with a
|
|
||||||
customer database of sorts.
|
|
||||||
|
|
||||||
Once postfix is built with mysql support, you can specify a map type
|
|
||||||
in main.cf like this:
|
|
||||||
|
|
||||||
alias_maps = mysql:/etc/postfix/mysql-aliases.cf
|
|
||||||
|
|
||||||
The file /etc/postfix/mysql-aliases.cf specifies lots of information
|
|
||||||
telling postfix how to reference the mysql database. An example mysql
|
|
||||||
map config file follows:
|
|
||||||
|
|
||||||
#
|
|
||||||
# mysql config file for alias lookups on postfix
|
|
||||||
# comments are ok.
|
|
||||||
#
|
|
||||||
|
|
||||||
# the user name and password to log into the mysql server
|
|
||||||
user = someone
|
|
||||||
password = some_password
|
|
||||||
|
|
||||||
# the database name on the servers
|
|
||||||
dbname = customer_database
|
|
||||||
|
|
||||||
# the table name
|
|
||||||
table = mxaliases
|
|
||||||
|
|
||||||
#
|
|
||||||
select_field = forw_addr
|
|
||||||
where_field = alias
|
|
||||||
|
|
||||||
# you may specify additional_conditions here
|
|
||||||
additional_conditions = and status = 'paid'
|
|
||||||
|
|
||||||
# the above variables will result in a query of
|
|
||||||
# the form:
|
|
||||||
# select forw_addr from mxaliases where alias = '$lookup' and status = 'paid'
|
|
||||||
# ($lookup is escaped so if it contains single quotes or other odd
|
|
||||||
# characters, it will not cause a parse error in the sql).
|
|
||||||
#
|
|
||||||
# the hosts that postfix will try to connect to
|
|
||||||
# and query from (in the order listed)
|
|
||||||
# specify unix: for unix-domain sockets, inet: for TCP connections (default)
|
|
||||||
hosts = host1.some.domain host2.some.domain unix:/file/name
|
|
||||||
|
|
||||||
# end mysql config file
|
|
||||||
|
|
||||||
Some notes:
|
|
||||||
|
|
||||||
This configuration interface setup allows for multiple mysql
|
|
||||||
databases: you can use one for a virtual table, one for an access
|
|
||||||
table, and one for an aliases table if you want.
|
|
||||||
|
|
||||||
Since sites that have a need for multiple mail exchangers may enjoy
|
|
||||||
the convenience of using a networked mailer database, but do not want
|
|
||||||
to introduce a single point of failure to their system, we've included
|
|
||||||
the ability to have postfix reference multiple hosts for access to a
|
|
||||||
single mysql map. This will work if sites set up mirrored mysql
|
|
||||||
databases on two or more hosts. Whenever queries fail with an error
|
|
||||||
at one host, the rest of the hosts will be tried in order. Each host
|
|
||||||
that is in an error state will undergo a reconnection attempt every so
|
|
||||||
often, and if no mysql server hosts are reachable, then mail will be
|
|
||||||
deferred until at least one of those hosts is reachable.
|
|
||||||
|
|
||||||
Performance of postfix with mysql has not been thoroughly tested,
|
|
||||||
however, we have found it to be stable. Busy mail servers using mysql
|
|
||||||
maps will generate lots of concurrent mysql clients, so the mysql
|
|
||||||
server(s) should be run with this fact in mind. Any further
|
|
||||||
performance information, in addition to any feedback is most welcome.
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
To: wietse@porcupine.org (Wietse Venema)
|
|
||||||
Cc: postfix-users@postfix.org (Postfix users)
|
|
||||||
Subject: regexp map patch
|
|
||||||
In-reply-to: Your message of "Thu, 25 Feb 1999 19:51:25 CDT."
|
|
||||||
<19990226005125.69B3C4596E@spike.porcupine.org>
|
|
||||||
Date: Tue, 02 Mar 1999 11:04:02 +1100
|
|
||||||
From: Andrew McNamara <andrewm@connect.com.au>
|
|
||||||
Message-Id: <19990302000403.074C7ED7D@melang.off.connect.com.au>
|
|
||||||
Sender: owner-postfix-users@postfix.org
|
|
||||||
Precedence: bulk
|
|
||||||
Return-Path: <owner-postfix-users@postfix.org>
|
|
||||||
|
|
||||||
I've written [code] to add a regexp map type. It utilises the PCRE
|
|
||||||
library (Perl Compatible Regular Expressions), which can be obtained
|
|
||||||
from:
|
|
||||||
|
|
||||||
ftp://ftp.cus.cam.ac.uk/pub/software/programs/pcre/
|
|
||||||
|
|
||||||
You will need to add -DHAS_PCRE and a -I for the PCRE header to CCARGS,
|
|
||||||
and add the path to the PCRE library to AUXLIBS, for example:
|
|
||||||
|
|
||||||
make -f Makefile.init makefiles 'CCARGS=-DHAS_PCRE -I../../../pcre-2.08' \
|
|
||||||
'AUXLIBS=../../../pcre-2.08/libpcre.a'
|
|
||||||
|
|
||||||
[note: pcre versions before 2.06 are no longer compatible -- Wietse]
|
|
||||||
|
|
||||||
One possible use is to add a line to main.cf:
|
|
||||||
|
|
||||||
smtpd_recipient_restrictions = pcre:/opt/postfix/etc/smtprecipient
|
|
||||||
|
|
||||||
The regular expressions are read from the file specified and compiled -
|
|
||||||
a sample regexp file for this usage is included in the patch.
|
|
||||||
|
|
||||||
Any feedback is appreciated (from Wietse in particular :-). Have
|
|
||||||
fun.
|
|
||||||
|
|
||||||
[I've changed the code so that it can be used for other Postfix
|
|
||||||
table lookups, not just for junk mail control. In particular,
|
|
||||||
regular expressions in canonical tables could be very useful.
|
|
||||||
|
|
||||||
For the sake of robustness, I have disabled the matching of partial
|
|
||||||
addresses (user@, domain, user, @domain) that is normally done with
|
|
||||||
Postfix access control tables, canonical maps and virtual maps.
|
|
||||||
|
|
||||||
As a side effect, pcre maps can only match user@domain strings, so
|
|
||||||
that regexps cannot be used for local alias database lookups. That
|
|
||||||
would be a security exposure anyway -- Wietse.]
|
|
|
@ -1,24 +0,0 @@
|
||||||
Per client/helo/sender/recipient UCE restrictions
|
|
||||||
=================================================
|
|
||||||
|
|
||||||
The Postfix SMTP server allows you to specify UCE restrictions on
|
|
||||||
the right-hand side of SMTPD access tables, so that you can have
|
|
||||||
different UCE restrictions for different clients or users.
|
|
||||||
|
|
||||||
The only anomalies in this scheme are that (1) message header_checks
|
|
||||||
and body_checks are still the same for every message, and (2) you
|
|
||||||
must use a restriction class name (see below) if you want to specify
|
|
||||||
a lookup table on the right-hand side of an access table (this is
|
|
||||||
because Postfix needs to open those tables ahead of time).
|
|
||||||
|
|
||||||
Restriction classes allow you to give easy-to-remember names to
|
|
||||||
groups of UCE restrictions (such as permissive, restrictive, and
|
|
||||||
so on). For example in main.cf:
|
|
||||||
|
|
||||||
smtpd_restriction_classes = restrictive, permissive
|
|
||||||
restrictive = reject_unknown_sender reject_unknown_client ...
|
|
||||||
permissive = permit
|
|
||||||
|
|
||||||
With this in place, you can use "restrictive" or "permissive" on
|
|
||||||
the right-hand side of your per-client/helo/sender/recipient SMTPD
|
|
||||||
access tables.
|
|
|
@ -1,206 +0,0 @@
|
||||||
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
|
||||||
===============================================================
|
|
||||||
|
|
||||||
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
|
|
||||||
or sasldb), and FreeBSD 3.4 (pwcheck_method set to sasldb). On
|
|
||||||
RedHat 6.1, SASL 1.5.5 insisted on write access to /etc/sasldb.
|
|
||||||
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".
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
============
|
|
||||||
|
|
||||||
The Postfix SASL support (RFC 2554) was originally implemented by
|
|
||||||
Till Franke of SuSE Rhein/Main AG. The present code is a trimmed-down
|
|
||||||
version with only the bare necessities.
|
|
||||||
|
|
||||||
When receiving mail, Postfix logs the client-provided username,
|
|
||||||
authentication method, and sender address to the maillog file, and
|
|
||||||
optionally grants mail access via the permit_sasl_authenticated
|
|
||||||
UCE restriction. SASL authentication information is not passed on
|
|
||||||
via message headers or via SMTP. It is no-one's business what
|
|
||||||
username and authentication method the poster was using in order
|
|
||||||
to access the mail server.
|
|
||||||
|
|
||||||
When sending mail, Postfix looks up the server hostname or destination
|
|
||||||
domain (the address remote part) in a table, and if a username/password
|
|
||||||
is found, it will use that username and password to authenticate
|
|
||||||
to the server.
|
|
||||||
|
|
||||||
Building the SASL library
|
|
||||||
=========================
|
|
||||||
|
|
||||||
Postfix appears to work with cyrus-sasl-1.5.5, which is available
|
|
||||||
from:
|
|
||||||
|
|
||||||
ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/
|
|
||||||
|
|
||||||
IMPORTANT: if you install the Cyrus SASL libraries as per the default,
|
|
||||||
you will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl.
|
|
||||||
|
|
||||||
Reportedly, Microsoft Internet Explorer version 5 requires the
|
|
||||||
non-standard SASL LOGIN authentication method. To enable this
|
|
||||||
authentication method, specify ``./configure --enable-login''.
|
|
||||||
|
|
||||||
If you install the Cyrus SASL libraries as per the default, you
|
|
||||||
will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl.
|
|
||||||
|
|
||||||
Building Postfix with SASL authentication support
|
|
||||||
=================================================
|
|
||||||
|
|
||||||
To build Postfix with SASL authentication support, the following
|
|
||||||
assumes that the Cyrus SASL include files are in /usr/local/include,
|
|
||||||
and that the Cyrus SASL libraries are in /usr/local/lib.
|
|
||||||
|
|
||||||
On some systems this generates the necessary Makefile definitions:
|
|
||||||
|
|
||||||
% make tidy # if you have left-over files from a previous build
|
|
||||||
% make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include" \
|
|
||||||
AUXLIBS="-L/usr/local/lib -lsasl"
|
|
||||||
|
|
||||||
On Solaris 2.x you need to specify run-time link information,
|
|
||||||
otherwise ld.so will not find the SASL shared library:
|
|
||||||
|
|
||||||
% make tidy # if you have left-over files from a previous build
|
|
||||||
% make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include" \
|
|
||||||
AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lsasl"
|
|
||||||
|
|
||||||
Enabling SASL authentication in the Postfix SMTP server
|
|
||||||
=======================================================
|
|
||||||
|
|
||||||
See conf/sample-auth.cf for examples.
|
|
||||||
|
|
||||||
In order to enable SASL support in the SMTP server:
|
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
|
||||||
smtpd_sasl_auth_enable = yes
|
|
||||||
|
|
||||||
In order to allow mail relaying by authenticated clients:
|
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
|
||||||
smtpd_recipient_restrictions =
|
|
||||||
permit_mynetworks permit_sasl_authenticated ...
|
|
||||||
|
|
||||||
In /usr/local/lib/sasl/smtpd.conf you need to specify how the server
|
|
||||||
should validate client passwords.
|
|
||||||
|
|
||||||
In order to authenticate against the UNIX password database, try:
|
|
||||||
|
|
||||||
/usr/local/lib/sasl/smtpd.conf:
|
|
||||||
pwcheck_method: pwcheck
|
|
||||||
|
|
||||||
The pwcheck daemon is contained in the cyrus-sasl source tarball.
|
|
||||||
|
|
||||||
In order to authenticate against SASL's own password database:
|
|
||||||
|
|
||||||
/usr/local/lib/sasl/smtpd.conf:
|
|
||||||
pwcheck_method: sasldb
|
|
||||||
|
|
||||||
This will use the SASL password file (default: /etc/sasldb), which
|
|
||||||
is maintained with the saslpasswd command (part of the Cyrus SASL
|
|
||||||
software). On some poorly-supported systems the saslpasswd command
|
|
||||||
needs to be run multiple times before it stops complaining. The
|
|
||||||
Postfix SMTP server needs read access to the sasldb file - you may
|
|
||||||
have to play games with group access permissions. On RedHat 6.1,
|
|
||||||
SASL 1.5.5 insists on write access to /etc/sasldb.
|
|
||||||
|
|
||||||
IMPORTANT: To get sasldb running, make sure that you set the SASL domain
|
|
||||||
(realm) to a fully qualified domain name.
|
|
||||||
|
|
||||||
EXAMPLE: saslpasswd -c -u `postconf -h myhostname` exampleuser
|
|
||||||
|
|
||||||
To run software chrooted with SASL support is an interesting
|
|
||||||
exercise. It probably is not worth the trouble.
|
|
||||||
|
|
||||||
Older Microsoft SMTP client software implements a non-standard
|
|
||||||
version of the AUTH protocol syntax, and expects that the SMTP
|
|
||||||
server replies to EHLO with "250 AUTH=stuff" instead of "250 AUTH
|
|
||||||
stuff". To accomodate such clients in addition to conformant
|
|
||||||
clients, set "broken_sasl_auth_clients = yes" in the main.cf file.
|
|
||||||
|
|
||||||
Testing SASL authentication in the Postfix SMTP server
|
|
||||||
======================================================
|
|
||||||
|
|
||||||
To test the whole mess, connect to the SMTP server, and you should
|
|
||||||
be able to have a conversation like this:
|
|
||||||
|
|
||||||
220 server.host.name ESMTP Postfix
|
|
||||||
EHLO client.host.name
|
|
||||||
250-server.host.name
|
|
||||||
250-PIPELINING
|
|
||||||
250-SIZE 10240000
|
|
||||||
250-ETRN
|
|
||||||
250-AUTH DIGEST-MD5 PLAIN CRAM-MD5
|
|
||||||
250 8BITMIME
|
|
||||||
AUTH PLAIN dGVzdAB0ZXN0AHRlc3RwYXNz
|
|
||||||
235 Authentication successful
|
|
||||||
|
|
||||||
Instead of dGVzdAB0ZXN0AHRlc3RwYXNz, specify the base64 encoded
|
|
||||||
form of username\0username\0password (the \0 is a null byte). The
|
|
||||||
example above is for a user named `test' with password `testpass'.
|
|
||||||
|
|
||||||
In order to generate base64 encoded authentication information you
|
|
||||||
can use one of the following commands:
|
|
||||||
|
|
||||||
% printf 'username\0username\0password' | mmencode
|
|
||||||
|
|
||||||
% perl -MMIME::Base64 -e \
|
|
||||||
'print encode_base64("username\0username\0password");'
|
|
||||||
|
|
||||||
MIME::Base64 is available from www.cpan.org.
|
|
||||||
|
|
||||||
Enabling SASL authentication in the Postfix SMTP client
|
|
||||||
=======================================================
|
|
||||||
|
|
||||||
Turn on client-side SASL authentication, and specify a table with
|
|
||||||
per-host or per-destination username and password information.
|
|
||||||
Postfix first looks up the server hostname; if no entry is found,
|
|
||||||
then Postfix looks up the destination domain name (usually, the
|
|
||||||
remote part of an email address).
|
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
|
||||||
smtp_sasl_auth_enable = yes
|
|
||||||
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
|
||||||
|
|
||||||
/etc/postfix/sasl_passwd:
|
|
||||||
foo.com username:password
|
|
||||||
bar.com username
|
|
||||||
|
|
||||||
Note: some SMTP servers support PLAIN or LOGIN authentication only.
|
|
||||||
By default, the Postfix SMTP client does not use authentication
|
|
||||||
methods that send plaintext passwords, and defers delivery with
|
|
||||||
the following error message: "Authentication failed: cannot SASL
|
|
||||||
authenticate to server". To enable plaintext authentication specify,
|
|
||||||
for example:
|
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
|
||||||
smtp_sasl_security_options =
|
|
||||||
|
|
||||||
The SASL client password file is opened before the SMTP server
|
|
||||||
enters the optional chroot jail, so you can keep the file in
|
|
||||||
/etc/postfix.
|
|
||||||
|
|
||||||
The Postfix SMTP client is backwards compatible with SMTP servers
|
|
||||||
that use the non-standard AUTH=stuff... syntax in response to the
|
|
||||||
EHLO command.
|
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
|
|
||||||
one queue per rcpt hurts when delivering to agents that don't
|
|
||||||
get stuck on shell commands or mailbox locks
|
|
||||||
|
|
||||||
xxx: bounced as yyy (bounced mail); xxx forwarded as zzz (mail
|
|
||||||
expanded via :include:).
|
|
||||||
|
|
||||||
postconf -f filename
|
|
||||||
|
|
||||||
get rid of the relocated feature - perhaps better to bounce recipients
|
|
||||||
at the SMTP port.
|
|
||||||
|
|
||||||
make sendmail/smtpd/cleanup output directory/fifo configurable
|
|
||||||
|
|
||||||
if postdrop scrutinizes input, skip the overhead in the pickup
|
|
||||||
daemon.
|
|
||||||
|
|
||||||
add a threshold to sendmail etc. stderr logging, so that class
|
|
||||||
"info" messages don't go to stderr.
|
|
||||||
|
|
||||||
implement an UCE control to accept mail if the sender domain sender
|
|
||||||
lists us as MX host (rafal wiosna). By the same token, implement
|
|
||||||
a control to accept mail when the client hostname/parent domain
|
|
||||||
lists us as their MX host.
|
|
||||||
|
|
||||||
received: headers should be generated by the cleanup daemon, and
|
|
||||||
client attributes ("with", "from", etc.) should be passed along
|
|
||||||
with the message. This guarantees that forwarded/aliased mail gets
|
|
||||||
stamped with the queue ID.
|
|
||||||
|
|
||||||
toss double-bounce mail even when mail for the local machine is
|
|
||||||
redirected to another box. See mail_addr_double_bounce().
|
|
||||||
|
|
||||||
remote showq access (cookie in maildrop or print some text to inform
|
|
||||||
the user)
|
|
||||||
|
|
||||||
defer: explain mail was bounced after N days
|
|
||||||
|
|
||||||
multiple rewrite processes?
|
|
||||||
|
|
||||||
gethostbyaddr() uses native name services, which can be slow.
|
|
||||||
|
|
||||||
can we detect a client that ignores error responses?
|
|
||||||
|
|
||||||
way to block inbound mail based on recipient suffix?
|
|
||||||
|
|
||||||
can Postfix implement one switchboard instead of having all these
|
|
||||||
little lookup tables?
|
|
||||||
|
|
||||||
make canonical/virtual/etc. table lookup order configurable
|
|
||||||
|
|
||||||
pass on client etc/ attributes along with message to delivery agent
|
|
||||||
|
|
||||||
scrutinize file opens in delivery agents just like in qmgr (better:
|
|
||||||
open the file and see if someone compromised the vmailer account
|
|
||||||
and is racing against us).
|
|
||||||
|
|
||||||
suspend/resume signals + master status (suspended/running) in PID
|
|
||||||
file. Maybe use FIFO instead. But, that means requests do not
|
|
||||||
arrive when the master is stuck.
|
|
||||||
|
|
||||||
postedit queue-id command...
|
|
||||||
|
|
||||||
more flexible mail queue list command
|
|
||||||
|
|
||||||
multiple queues may make ETRN processing less painful because there
|
|
||||||
is less delayed mail to plow through.
|
|
||||||
|
|
||||||
qmgr: configurable incoming/deferred mixing ratio so we can prioritize
|
|
||||||
new mail over old mail
|
|
||||||
|
|
||||||
Replace [my.own.ip.addr] by domain name so that delivered-to has
|
|
||||||
the desired effect.
|
|
||||||
|
|
||||||
Received: header and bounce text will be configurable with ${name}
|
|
||||||
macros. This requires that everything must cope with newlines in
|
|
||||||
config parameters (including the SMTP greeting bannner, yuck).
|
|
||||||
|
|
||||||
Pass along the client hostname/posting user with queue files, to
|
|
||||||
be logged by the queue manager.
|
|
||||||
|
|
||||||
showq: don't use mail_open_ok() - it assumes coordinated queue
|
|
||||||
access.
|
|
||||||
|
|
||||||
trivial-rewrite: optionally, use DNS to fully qualify hostnames.
|
|
||||||
|
|
||||||
pickup/cleanup/qmgr/local: add options record to control internal
|
|
||||||
features such as canonical/virtual mapping, VERPs etcetera.
|
|
||||||
|
|
||||||
Add hook for (domain, user database) support. This is needed if
|
|
||||||
you have lots of real domains and can't afford a separate master.cf
|
|
||||||
delivery agent entry for each domain.
|
|
||||||
|
|
||||||
Add support for DBZ databases, using the code from INN. Reportedly,
|
|
||||||
GDB handles large numbers of keys poorly.
|
|
||||||
|
|
||||||
Change the front-end to cleanup protocol so that the front-end
|
|
||||||
sends the expected message size, and so that the cleanup service
|
|
||||||
can report if there is enough space. This is useful only for the
|
|
||||||
SMTP server, because pickup can't produce bounce requests: the
|
|
||||||
bounce service can't read the maildrop file.
|
|
||||||
|
|
||||||
On systems with functional UNIX-domain sockets, use that instead
|
|
||||||
of FIFOs to trigger the pickup and qmgr services. This allows for
|
|
||||||
some coupling between front-end programs and queue manager, so that
|
|
||||||
a burst of inbound mail does not lock out the queue manager from
|
|
||||||
accessing the queue, causing outbound delivery to stop.
|
|
||||||
|
|
||||||
There is a need to run `master' services outside the "master"
|
|
||||||
environment, either for testing (new config files) or for production.
|
|
||||||
For consistency reasons, programs file names should be taken from
|
|
||||||
the master.cf file.
|
|
||||||
|
|
||||||
- The showq service. Used by the super user when the mail system
|
|
||||||
is down.
|
|
||||||
|
|
||||||
- The smtpd service for "sendmail -bs" emulation. Used by some
|
|
||||||
mail posting agents. Output to the maildrop, so that messages
|
|
||||||
can be posted even when the mail system is down.
|
|
||||||
|
|
||||||
- The rewrite engine for "sendmail -bt" emulation, for off-line
|
|
||||||
testing of configuration files. Requires a method to override
|
|
||||||
the location of the rewriting rules file. Or, perhaps there
|
|
||||||
should be an official place (/etc/vmailer/testbed?) for playing
|
|
||||||
with config files.
|
|
||||||
|
|
||||||
postfix-script: detect and/or build missing alias database. In
|
|
||||||
order to do this we must extract the alias_maps parameter from the
|
|
||||||
main.cf file, and create any missing files with the right ownerships.
|
|
||||||
|
|
||||||
implement the return-receipt-to notification service.
|
|
||||||
|
|
||||||
bounce/defer: provide attribute-value interface, for better logging
|
|
||||||
(expanded-from etc.) and non-delivery reports.
|
|
||||||
|
|
||||||
Maintain per-client short-term host status, so we can slow down
|
|
||||||
unreasonable clients
|
|
||||||
|
|
||||||
Make archiving delivered mail a REAL option (queue manager). What
|
|
||||||
about one archive per day. The magic could be put into the mail
|
|
||||||
queue name routines. Just make it aware of the date.
|
|
||||||
|
|
||||||
Will the mail system be faster when we avoid moving new messages
|
|
||||||
incoming->active? How would one detect the arrival of new files?
|
|
||||||
|
|
||||||
pickup: pass file descriptor to cleanup instead of copying data.
|
|
||||||
This violates the principle that all front-end programs protect
|
|
||||||
the mail system against unreasonably-long inputs.
|
|
||||||
|
|
||||||
True ETRN means kick the host out of the queue manager's "dead
|
|
||||||
hosts" table & move mail from the "hold" queue for that site to
|
|
||||||
the incoming queue.
|
|
||||||
|
|
||||||
postfix-script: make sure that each queue file matches its file id
|
|
||||||
or we might lose mail.
|
|
||||||
|
|
||||||
postfix-script: do database fixups as the unprivileged user
|
|
||||||
|
|
||||||
Maintain a pool of pre-allocated queue files, to eliminate file
|
|
||||||
creation and deletion overhead.
|
|
|
@ -1,34 +0,0 @@
|
||||||
To: wietse@porcupine.org (Wietse Venema)
|
|
||||||
Subject: postfix-19990317-pl05 on Ultrix4.3a
|
|
||||||
From: Christian von Roques <roques@pond.sub.org>
|
|
||||||
Date: 02 Jun 1999 18:44:34 +0200
|
|
||||||
Message-ID: <87iu96wo0d.fsf_-_@scalar.pond.sub.org>
|
|
||||||
|
|
||||||
I've upgraded the MTA of our DECstation-3100 running Ultrix4.3a to
|
|
||||||
postfix-19990317-pl05 and am sending you the patches I needed to get
|
|
||||||
it running under Ultrix.
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
o One of the bugs of Ultrix's /bin/sh is that shell-variables set in
|
|
||||||
arguments of `:' expand to garbage if expanded in here-documents.
|
|
||||||
Using a different shell helps. I needed to replace all calls of
|
|
||||||
``sh .../makedefs'' by ``$(SHELL) .../makedefs'' in all the
|
|
||||||
Makefile.in and am now able to use
|
|
||||||
|
|
||||||
make SHELL=/bin/sh5 or zsh.
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
o Ultrix's FD_SET_SIZE is 4096, but getdtablesize() returns 64 by
|
|
||||||
default, if not increased when building a new kernel. getrlimit()
|
|
||||||
doesn't know RLIMIT_NOFILE. This makes event_init() always log
|
|
||||||
the warning: `could allocate space for only 64 open files'.
|
|
||||||
|
|
||||||
I just reduced the threshold from 256 to 64, but this is not good.
|
|
||||||
The initial problem still remains: How to disable this warning on
|
|
||||||
Ultrix without making the source ugly?
|
|
||||||
|
|
||||||
[I have updated util/sys_defs.h, and by default set FD_SETSIZE to
|
|
||||||
100. This should be sufficient for a workstation. No-one would
|
|
||||||
run a major mail hub on Ultrix 4. -- Wietse]
|
|
|
@ -1,6 +0,0 @@
|
||||||
In order to receive mail via UUCP, your system needs to have an
|
|
||||||
rmail command installed. A minimal rmail command can be found in
|
|
||||||
the "auxiliary/rmail" directory. Install the command, mode 755, in
|
|
||||||
a place that can be found by the UUCP "uuxqt" command.
|
|
||||||
|
|
||||||
In order to send mail via UUCP, see html/faq.html.
|
|
|
@ -1,31 +0,0 @@
|
||||||
Before you do the build, make sure you run niscript (as root) to properly
|
|
||||||
create a postfix user, and postfix & maildrop groups.
|
|
||||||
|
|
||||||
DO NOT USE THE MULTIPLE USERS APPLICATION TO CREATE THE POSTFIX USER!
|
|
||||||
|
|
||||||
1) su
|
|
||||||
|
|
||||||
2) ./niscript
|
|
||||||
|
|
||||||
this creates the necessary users & groups for proper operation
|
|
||||||
of postfix
|
|
||||||
|
|
||||||
3) ./stash-sendmail
|
|
||||||
|
|
||||||
move your existing sendmail binaries somewhere safe
|
|
||||||
|
|
||||||
4) make install
|
|
||||||
|
|
||||||
When the script asks you for setgid (the default will be no) tell it
|
|
||||||
maildrop
|
|
||||||
|
|
||||||
5) edit /etc/postfix/main.cf to suit your requirements
|
|
||||||
|
|
||||||
6) postfix start
|
|
||||||
|
|
||||||
7) Test. Read INSTALL for a series of suggested tests.
|
|
||||||
|
|
||||||
8) cp -R darwin-Postfix /System/Library/StartupItems/Postfix
|
|
||||||
|
|
||||||
9) edit /System/Library/StartupItems/Sendmail. add "exit 0" as the
|
|
||||||
first line
|
|
|
@ -1,13 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
. /etc/rc.common
|
|
||||||
|
|
||||||
##
|
|
||||||
# Start mail server
|
|
||||||
##
|
|
||||||
|
|
||||||
if [ "${MAILSERVER:=-NO-}" = "-YES-" ]; then
|
|
||||||
|
|
||||||
ConsoleMessage "Starting Postfix mail services"
|
|
||||||
/usr/sbin/postfix start
|
|
||||||
fi
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
Description = "Postfix mail server";
|
|
||||||
Provides = ("SMTP");
|
|
||||||
Requires = ("Resolver");
|
|
||||||
Uses = ("Network Time", "NFS");
|
|
||||||
Preference = "None";
|
|
||||||
Messages =
|
|
||||||
{
|
|
||||||
start = "Starting Postfix";
|
|
||||||
stop = "Stopping Postfix";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
|
|
||||||
mv /usr/bin/newaliases /usr/bin/newaliases.OFF
|
|
||||||
mv /usr/bin/mailq /usr/bin/mailq.OFF
|
|
||||||
chmod 755 /usr/sbin/sendmail.OFF /usr/bin/newaliases.OFF /usr/bin/mailq.OFF
|
|
|
@ -1,22 +0,0 @@
|
||||||
*** postfix-script-nosgid Wed Mar 24 11:20:49 1999
|
|
||||||
--- postfix-script-sgid Wed Mar 24 11:20:53 1999
|
|
||||||
***************
|
|
||||||
*** 174,181 ****
|
|
||||||
test -d maildrop || {
|
|
||||||
$WARN creating missing Postfix maildrop directory
|
|
||||||
mkdir maildrop || exit 1
|
|
||||||
! chmod 1733 maildrop
|
|
||||||
chown $mail_owner maildrop
|
|
||||||
}
|
|
||||||
test -d pid || {
|
|
||||||
$WARN creating missing Postfix pid directory
|
|
||||||
--- 174,182 ----
|
|
||||||
test -d maildrop || {
|
|
||||||
$WARN creating missing Postfix maildrop directory
|
|
||||||
mkdir maildrop || exit 1
|
|
||||||
! chmod 1730 maildrop
|
|
||||||
chown $mail_owner maildrop
|
|
||||||
+ chgrp maildrop maildrop
|
|
||||||
}
|
|
||||||
test -d pid || {
|
|
||||||
$WARN creating missing Postfix pid directory
|
|
|
@ -1,273 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#++
|
|
||||||
# NAME
|
|
||||||
# postfix-script 1
|
|
||||||
# SUMMARY
|
|
||||||
# execute Postfix administrative commands
|
|
||||||
# SYNOPSIS
|
|
||||||
# \fBpostfix-script\fR \fIcommand\fR
|
|
||||||
# DESCRIPTION
|
|
||||||
# The \fBfBpostfix-script\fR script executes Postfix administrative
|
|
||||||
# commands in an environtment that is set up by the \fBpostfix\fR(1)
|
|
||||||
# command.
|
|
||||||
# SEE ALSO
|
|
||||||
# master(8) Postfix master program
|
|
||||||
# postfix(1) Postfix administrative interface
|
|
||||||
# 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
|
|
||||||
#--
|
|
||||||
|
|
||||||
# Avoid POSIX death due to SIGHUP when some parent process exits.
|
|
||||||
|
|
||||||
trap '' 1
|
|
||||||
|
|
||||||
case $daemon_directory in
|
|
||||||
"") echo This script must be run by the postfix command. 1>&2
|
|
||||||
echo Do not run directly. 1>&2
|
|
||||||
exit 1
|
|
||||||
esac
|
|
||||||
|
|
||||||
LOGGER="$command_directory/postlog -t postfix-script"
|
|
||||||
INFO="$LOGGER -p info"
|
|
||||||
WARN="$LOGGER -p warn"
|
|
||||||
ERROR="$LOGGER -p error"
|
|
||||||
FATAL="$LOGGER -p fatal"
|
|
||||||
PANIC="$LOGGER -p panic"
|
|
||||||
|
|
||||||
umask 022
|
|
||||||
|
|
||||||
#
|
|
||||||
# LINUX by default does not synchronously update directories -
|
|
||||||
# that's dangerous for mail.
|
|
||||||
#
|
|
||||||
if [ -f /usr/bin/chattr ]
|
|
||||||
then
|
|
||||||
CHATTR="/usr/bin/chattr +S"
|
|
||||||
else
|
|
||||||
CHATTR=:
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# Can't do much without these in place.
|
|
||||||
#
|
|
||||||
cd $command_directory || {
|
|
||||||
$FATAL no Postfix command directory $command_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
cd $daemon_directory || {
|
|
||||||
$FATAL no Postfix daemon directory $daemon_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
test -f master || {
|
|
||||||
$FATAL no Postfix master program $daemon_directory/master!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
cd $config_directory || {
|
|
||||||
$FATAL no Postfix configuration directory $config_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
cd $queue_directory || {
|
|
||||||
$FATAL no Postfix queue directory $queue_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Parse JCL
|
|
||||||
#
|
|
||||||
case $1 in
|
|
||||||
|
|
||||||
start_msg)
|
|
||||||
|
|
||||||
echo "Start postfix"
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop_msg)
|
|
||||||
|
|
||||||
echo "Stop postfix"
|
|
||||||
;;
|
|
||||||
|
|
||||||
start)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null || {
|
|
||||||
$FATAL the Postfix mail system is already running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$config_directory/postfix-script check || {
|
|
||||||
$FATAL Postfix integrity check failed!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO starting the Postfix mail system
|
|
||||||
$daemon_directory/master &
|
|
||||||
;;
|
|
||||||
|
|
||||||
drain)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO stopping the Postfix mail system
|
|
||||||
kill -9 `sed 1q pid/master.pid`
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO stopping the Postfix mail system
|
|
||||||
kill `sed 1q pid/master.pid`
|
|
||||||
;;
|
|
||||||
|
|
||||||
abort)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO aborting the Postfix mail system
|
|
||||||
kill `sed 1q pid/master.pid`
|
|
||||||
;;
|
|
||||||
|
|
||||||
reload)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO refreshing the Postfix mail system
|
|
||||||
$command_directory/postsuper active || exit 1
|
|
||||||
kill -HUP `sed 1q pid/master.pid`
|
|
||||||
$command_directory/postsuper &
|
|
||||||
;;
|
|
||||||
|
|
||||||
flush)
|
|
||||||
|
|
||||||
cd $queue_directory || {
|
|
||||||
$FATAL no Postfix queue directory $queue_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$command_directory/postkick public qmgr IDFA
|
|
||||||
;;
|
|
||||||
|
|
||||||
check)
|
|
||||||
|
|
||||||
for dir in $daemon_directory $config_directory $queue_directory
|
|
||||||
do
|
|
||||||
ls -lLd $dir | (grep " root " >/dev/null ||
|
|
||||||
$WARN not owned by root: $dir)
|
|
||||||
done
|
|
||||||
|
|
||||||
find $daemon_directory/* $config_directory/* ! -user root \
|
|
||||||
-exec $WARN not owned by root: {} \;
|
|
||||||
|
|
||||||
find $daemon_directory/. $config_directory/. \
|
|
||||||
\( -perm -020 -o -perm -002 \) \
|
|
||||||
-exec $WARN group or other writable: {} \;
|
|
||||||
|
|
||||||
find $queue_directory/* $config_directory/* -name '*core' \
|
|
||||||
-exec $WARN core file: {} \; 2>/dev/null
|
|
||||||
|
|
||||||
test -d maildrop || {
|
|
||||||
$WARN creating missing Postfix maildrop directory
|
|
||||||
mkdir maildrop || exit 1
|
|
||||||
chmod 1733 maildrop
|
|
||||||
chown $mail_owner maildrop
|
|
||||||
}
|
|
||||||
test -d pid || {
|
|
||||||
$WARN creating missing Postfix pid directory
|
|
||||||
mkdir pid || exit 1
|
|
||||||
chmod 755 pid
|
|
||||||
chown $mail_owner pid
|
|
||||||
}
|
|
||||||
for dir in incoming active bounce defer deferred flush saved corrupt; do
|
|
||||||
test -d $dir || {
|
|
||||||
$WARN creating missing Postfix $dir directory
|
|
||||||
mkdir $dir || exit 1
|
|
||||||
chmod 700 $dir; $CHATTR $dir 2>/dev/null
|
|
||||||
chown $mail_owner $dir
|
|
||||||
}
|
|
||||||
done
|
|
||||||
test -d public || {
|
|
||||||
$WARN creating missing Postfix public directory
|
|
||||||
mkdir public || exit 1
|
|
||||||
chmod 755 public
|
|
||||||
chown $mail_owner public
|
|
||||||
}
|
|
||||||
test -d private || {
|
|
||||||
$WARN creating missing Postfix private directory
|
|
||||||
mkdir private || exit 1
|
|
||||||
chmod 700 private
|
|
||||||
chown $mail_owner private
|
|
||||||
}
|
|
||||||
find `ls -d $queue_directory/* | \
|
|
||||||
egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private)$'` \
|
|
||||||
! \( -type p -o -type s \) ! -user $mail_owner \
|
|
||||||
-exec $WARN not owned by $mail_owner: {} \;
|
|
||||||
|
|
||||||
for dir in $queue_directory/maildrop
|
|
||||||
do
|
|
||||||
ls -lLd $dir | (grep " $mail_owner " >/dev/null ||
|
|
||||||
$WARN not owned by $mail_owner: $dir)
|
|
||||||
done
|
|
||||||
|
|
||||||
for dir in bin etc lib sbin usr
|
|
||||||
do
|
|
||||||
test -d $dir && find $dir -type f -print | while read path
|
|
||||||
do
|
|
||||||
cmp -s $path /$path ||
|
|
||||||
$WARN $queue_directory/$path and /$path differ
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# Look for incomplete upgrades.
|
|
||||||
|
|
||||||
test -f $config_directory/master.cf || {
|
|
||||||
$FATAL no $config_directory/master.cf file found
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
grep 'flush.*flush' $config_directory/master.cf >/dev/null || {
|
|
||||||
$WARN adding missing entry for flush service to master.cf
|
|
||||||
cat >>$config_directory/master.cf <<EOF
|
|
||||||
flush unix - - n 1000? 0 flush
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
found=`$command_directory/postconf -h hash_queue_names`
|
|
||||||
missing=
|
|
||||||
(echo "$found" | grep active >/dev/null) || missing="$missing active"
|
|
||||||
(echo "$found" | grep bounce >/dev/null) || missing="$missing bounce"
|
|
||||||
(echo "$found" | grep defer >/dev/null) || missing="$missing defer"
|
|
||||||
(echo "$found" | grep flush >/dev/null) || missing="$missing flush"
|
|
||||||
(echo "$found" | grep incoming>/dev/null)|| missing="$missing incoming"
|
|
||||||
(echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
|
|
||||||
test -n "$missing" && {
|
|
||||||
$WARN fixing main.cf hash_queue_names for missing $missing
|
|
||||||
$command_directory/postconf -e hash_queue_names="$found$missing"
|
|
||||||
}
|
|
||||||
|
|
||||||
# See if all queue files are in the right place.
|
|
||||||
|
|
||||||
$command_directory/postsuper active
|
|
||||||
$command_directory/postsuper &
|
|
||||||
|
|
||||||
find corrupt -type f -exec $WARN damaged message: {} \;
|
|
||||||
|
|
||||||
# XXX also: look for weird stuff, weird permissions, etc.
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
|
|
||||||
$FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
|
@ -1,274 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#++
|
|
||||||
# NAME
|
|
||||||
# postfix-script 1
|
|
||||||
# SUMMARY
|
|
||||||
# execute Postfix administrative commands
|
|
||||||
# SYNOPSIS
|
|
||||||
# \fBpostfix-script\fR \fIcommand\fR
|
|
||||||
# DESCRIPTION
|
|
||||||
# The \fBfBpostfix-script\fR script executes Postfix administrative
|
|
||||||
# commands in an environtment that is set up by the \fBpostfix\fR(1)
|
|
||||||
# command.
|
|
||||||
# SEE ALSO
|
|
||||||
# master(8) Postfix master program
|
|
||||||
# postfix(1) Postfix administrative interface
|
|
||||||
# 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
|
|
||||||
#--
|
|
||||||
|
|
||||||
# Avoid POSIX death due to SIGHUP when some parent process exits.
|
|
||||||
|
|
||||||
trap '' 1
|
|
||||||
|
|
||||||
case $daemon_directory in
|
|
||||||
"") echo This script must be run by the postfix command. 1>&2
|
|
||||||
echo Do not run directly. 1>&2
|
|
||||||
exit 1
|
|
||||||
esac
|
|
||||||
|
|
||||||
LOGGER="$command_directory/postlog -t postfix-script"
|
|
||||||
INFO="$LOGGER -p info"
|
|
||||||
WARN="$LOGGER -p warn"
|
|
||||||
ERROR="$LOGGER -p error"
|
|
||||||
FATAL="$LOGGER -p fatal"
|
|
||||||
PANIC="$LOGGER -p panic"
|
|
||||||
|
|
||||||
umask 022
|
|
||||||
|
|
||||||
#
|
|
||||||
# LINUX by default does not synchronously update directories -
|
|
||||||
# that's dangerous for mail.
|
|
||||||
#
|
|
||||||
if [ -f /usr/bin/chattr ]
|
|
||||||
then
|
|
||||||
CHATTR="/usr/bin/chattr +S"
|
|
||||||
else
|
|
||||||
CHATTR=:
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# Can't do much without these in place.
|
|
||||||
#
|
|
||||||
cd $command_directory || {
|
|
||||||
$FATAL no Postfix command directory $command_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
cd $daemon_directory || {
|
|
||||||
$FATAL no Postfix daemon directory $daemon_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
test -f master || {
|
|
||||||
$FATAL no Postfix master program $daemon_directory/master!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
cd $config_directory || {
|
|
||||||
$FATAL no Postfix configuration directory $config_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
cd $queue_directory || {
|
|
||||||
$FATAL no Postfix queue directory $queue_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Parse JCL
|
|
||||||
#
|
|
||||||
case $1 in
|
|
||||||
|
|
||||||
start_msg)
|
|
||||||
|
|
||||||
echo "Start postfix"
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop_msg)
|
|
||||||
|
|
||||||
echo "Stop postfix"
|
|
||||||
;;
|
|
||||||
|
|
||||||
start)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null || {
|
|
||||||
$FATAL the Postfix mail system is already running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$config_directory/postfix-script check || {
|
|
||||||
$FATAL Postfix integrity check failed!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO starting the Postfix mail system
|
|
||||||
$daemon_directory/master &
|
|
||||||
;;
|
|
||||||
|
|
||||||
drain)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO stopping the Postfix mail system
|
|
||||||
kill -9 `sed 1q pid/master.pid`
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO stopping the Postfix mail system
|
|
||||||
kill `sed 1q pid/master.pid`
|
|
||||||
;;
|
|
||||||
|
|
||||||
abort)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO aborting the Postfix mail system
|
|
||||||
kill `sed 1q pid/master.pid`
|
|
||||||
;;
|
|
||||||
|
|
||||||
reload)
|
|
||||||
|
|
||||||
$daemon_directory/master -t 2>/dev/null && {
|
|
||||||
$FATAL the Postfix mail system is not running
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$INFO refreshing the Postfix mail system
|
|
||||||
$command_directory/postsuper active || exit 1
|
|
||||||
kill -HUP `sed 1q pid/master.pid`
|
|
||||||
$command_directory/postsuper &
|
|
||||||
;;
|
|
||||||
|
|
||||||
flush)
|
|
||||||
|
|
||||||
cd $queue_directory || {
|
|
||||||
$FATAL no Postfix queue directory $queue_directory!
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
$command_directory/postkick public qmgr IDFA
|
|
||||||
;;
|
|
||||||
|
|
||||||
check)
|
|
||||||
|
|
||||||
for dir in $daemon_directory $config_directory $queue_directory
|
|
||||||
do
|
|
||||||
ls -lLd $dir | (grep " root " >/dev/null ||
|
|
||||||
$WARN not owned by root: $dir)
|
|
||||||
done
|
|
||||||
|
|
||||||
find $daemon_directory/* $config_directory/* ! -user root \
|
|
||||||
-exec $WARN not owned by root: {} \;
|
|
||||||
|
|
||||||
find $daemon_directory/. $config_directory/. \
|
|
||||||
\( -perm -020 -o -perm -002 \) \
|
|
||||||
-exec $WARN group or other writable: {} \;
|
|
||||||
|
|
||||||
find $queue_directory/* $config_directory/* -name '*core' \
|
|
||||||
-exec $WARN core file: {} \; 2>/dev/null
|
|
||||||
|
|
||||||
test -d maildrop || {
|
|
||||||
$WARN creating missing Postfix maildrop directory
|
|
||||||
mkdir maildrop || exit 1
|
|
||||||
chmod 1730 maildrop
|
|
||||||
chown $mail_owner maildrop
|
|
||||||
chgrp maildrop maildrop
|
|
||||||
}
|
|
||||||
test -d pid || {
|
|
||||||
$WARN creating missing Postfix pid directory
|
|
||||||
mkdir pid || exit 1
|
|
||||||
chmod 755 pid
|
|
||||||
chown $mail_owner pid
|
|
||||||
}
|
|
||||||
for dir in incoming active bounce defer deferred flush saved corrupt; do
|
|
||||||
test -d $dir || {
|
|
||||||
$WARN creating missing Postfix $dir directory
|
|
||||||
mkdir $dir || exit 1
|
|
||||||
chmod 700 $dir; $CHATTR $dir 2>/dev/null
|
|
||||||
chown $mail_owner $dir
|
|
||||||
}
|
|
||||||
done
|
|
||||||
test -d public || {
|
|
||||||
$WARN creating missing Postfix public directory
|
|
||||||
mkdir public || exit 1
|
|
||||||
chmod 755 public
|
|
||||||
chown $mail_owner public
|
|
||||||
}
|
|
||||||
test -d private || {
|
|
||||||
$WARN creating missing Postfix private directory
|
|
||||||
mkdir private || exit 1
|
|
||||||
chmod 700 private
|
|
||||||
chown $mail_owner private
|
|
||||||
}
|
|
||||||
find `ls -d $queue_directory/* | \
|
|
||||||
egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private)$'` \
|
|
||||||
! \( -type p -o -type s \) ! -user $mail_owner \
|
|
||||||
-exec $WARN not owned by $mail_owner: {} \;
|
|
||||||
|
|
||||||
for dir in $queue_directory/maildrop
|
|
||||||
do
|
|
||||||
ls -lLd $dir | (grep " $mail_owner " >/dev/null ||
|
|
||||||
$WARN not owned by $mail_owner: $dir)
|
|
||||||
done
|
|
||||||
|
|
||||||
for dir in bin etc lib sbin usr
|
|
||||||
do
|
|
||||||
test -d $dir && find $dir -type f -print | while read path
|
|
||||||
do
|
|
||||||
cmp -s $path /$path ||
|
|
||||||
$WARN $queue_directory/$path and /$path differ
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# Look for incomplete upgrades.
|
|
||||||
|
|
||||||
test -f $config_directory/master.cf || {
|
|
||||||
$FATAL no $config_directory/master.cf file found
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
grep 'flush.*flush' $config_directory/master.cf >/dev/null || {
|
|
||||||
$WARN adding missing entry for flush service to master.cf
|
|
||||||
cat >>$config_directory/master.cf <<EOF
|
|
||||||
flush unix - - n 1000? 0 flush
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
found=`$command_directory/postconf -h hash_queue_names`
|
|
||||||
missing=
|
|
||||||
(echo "$found" | grep active >/dev/null) || missing="$missing active"
|
|
||||||
(echo "$found" | grep bounce >/dev/null) || missing="$missing bounce"
|
|
||||||
(echo "$found" | grep defer >/dev/null) || missing="$missing defer"
|
|
||||||
(echo "$found" | grep flush >/dev/null) || missing="$missing flush"
|
|
||||||
(echo "$found" | grep incoming>/dev/null)|| missing="$missing incoming"
|
|
||||||
(echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
|
|
||||||
test -n "$missing" && {
|
|
||||||
$WARN fixing main.cf hash_queue_names for missing $missing
|
|
||||||
$command_directory/postconf -e hash_queue_names="$found$missing"
|
|
||||||
}
|
|
||||||
|
|
||||||
# See if all queue files are in the right place.
|
|
||||||
|
|
||||||
$command_directory/postsuper active
|
|
||||||
$command_directory/postsuper &
|
|
||||||
|
|
||||||
find corrupt -type f -exec $WARN damaged message: {} \;
|
|
||||||
|
|
||||||
# XXX also: look for weird stuff, weird permissions, etc.
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
|
|
||||||
$FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
|
@ -1,52 +0,0 @@
|
||||||
#
|
|
||||||
# Sample pcre (PERL-compatible regular expression) map file
|
|
||||||
#
|
|
||||||
# The first field is a perl-like regular expression. The expression
|
|
||||||
# delimiter can be any character except whitespace, or characters
|
|
||||||
# that have special meaning to the regexp library (traditionally
|
|
||||||
# the forward slash is used). The regular expression can contain
|
|
||||||
# whitespace.
|
|
||||||
#
|
|
||||||
# By default, matching is case-INsensitive, although following
|
|
||||||
# the second slash with an 'i' will reverse this. Other flags are
|
|
||||||
# supported, but the only other useful one is 'U', which makes
|
|
||||||
# matching ungreedy (see PCRE documentation and source for more
|
|
||||||
# info).
|
|
||||||
#
|
|
||||||
# The second field is the "replacement" string - the text
|
|
||||||
# returned by the match. When used for smtpd checks, this would
|
|
||||||
# be a helpful message to misguided users (or an offensive
|
|
||||||
# message to spammers), although it could also be a domain name
|
|
||||||
# or other data for use as a transport, virtual, or other map.
|
|
||||||
#
|
|
||||||
# Substitution of sub-strings from the matched expression is
|
|
||||||
# possible using the conventional perl syntax. The macros in the
|
|
||||||
# replacement string may need to be protected with curly braces
|
|
||||||
# if they aren't followed by whitespace (see the examples
|
|
||||||
# below).
|
|
||||||
#
|
|
||||||
# Lines starting with whitespace are continuation lines - they are
|
|
||||||
# appended to the previous line (there should be no whitespace
|
|
||||||
# before your regular expression!)
|
|
||||||
#
|
|
||||||
# This code was originally developed for SPAM control. However
|
|
||||||
# it seems that it can be used equally well for address rewriting
|
|
||||||
# by virtual or canonical lookups. Using this for aliases might
|
|
||||||
# be stretching things, though.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Protect your outgoing majordomo exploders
|
|
||||||
#
|
|
||||||
/^(?!owner-)(.*)-outgoing@(connect.com.au)$/ 550 Use ${1}@${2} instead
|
|
||||||
|
|
||||||
|
|
||||||
# Bounce friend@whatever, except when whatever is our domain (you would
|
|
||||||
# be better just bouncing all friend@ mail - this is just an example).
|
|
||||||
#
|
|
||||||
/^friend@(?!connect.com.au).*$/ 550 Stick this in your pipe $0
|
|
||||||
|
|
||||||
# A multi-line response
|
|
||||||
#
|
|
||||||
/^noddy@connect.com.au$/
|
|
||||||
550 This user is a funny one. You really don't want to send mail to them
|
|
||||||
as it only makes their head spin.
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Sample regexp lookup "table".
|
|
||||||
#
|
|
||||||
# Format is /regexp/flags or /regexp/flags!/regexp/flags
|
|
||||||
# where regexp is a regular expression as found in regexp(5), and flags are
|
|
||||||
# i: toggle ignore case (REG_ICASE - default is to ignore case)
|
|
||||||
# x: toggle extended expression (REG_EXTENDED - default is extended)
|
|
||||||
# m: toggle multiline mode (REG_NEWLINE - default is non-multiline mode)
|
|
||||||
#
|
|
||||||
# In order for a line to match, the first regexp must match, and the
|
|
||||||
# second (if present) must not match. The first matching line wins,
|
|
||||||
# terminating processing of the ruleset.
|
|
||||||
|
|
||||||
# Disallow sender-specified routing. This is a must if you relay mail
|
|
||||||
#for other domains.
|
|
||||||
/[%!@].*@/ 550 Sender-specified routing rejected
|
|
||||||
|
|
||||||
# Postmaster is OK, that way they can talk to us about how to fix their problem.
|
|
||||||
/^postmaster@.*$/ OK
|
|
||||||
|
|
||||||
# Protect your outgoing majordomo exploders
|
|
||||||
/^(.*)-outgoing@(.*)$/!/^owner-.*/ 550 Use ${1}@${2} instead
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* mail_command_read 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* single-command server
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <mail_proto.h>
|
|
||||||
/*
|
|
||||||
/* int mail_command_read(stream, format, ...)
|
|
||||||
/* VSTREAM *stream;
|
|
||||||
/* char *format;
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* This module implements the server interface for single-command
|
|
||||||
/* requests: a clients sends a single command and expects a single
|
|
||||||
/* completion status code.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
|
||||||
/* .IP stream
|
|
||||||
/* Server endpoint.
|
|
||||||
/* .IP format
|
|
||||||
/* Format string understood by mail_print(3) and mail_scan(3).
|
|
||||||
/* DIAGNOSTICS
|
|
||||||
/* Fatal: out of memory.
|
|
||||||
/* SEE ALSO
|
|
||||||
/* mail_scan(3)
|
|
||||||
/* mail_command_write(3) client interface
|
|
||||||
/* 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 <stdlib.h> /* 44BSD stdarg.h uses abort() */
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <vstring.h>
|
|
||||||
#include <vstream.h>
|
|
||||||
|
|
||||||
/* Global library. */
|
|
||||||
|
|
||||||
#include "mail_proto.h"
|
|
||||||
|
|
||||||
/* mail_command_read - read single-command request */
|
|
||||||
|
|
||||||
int mail_command_read(VSTREAM *stream, char *fmt,...)
|
|
||||||
{
|
|
||||||
VSTRING *eof = vstring_alloc(10);
|
|
||||||
va_list ap;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
count = mail_vscan(stream, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
if (mail_scan(stream, "%s", eof) != 1 || strcmp(vstring_str(eof), MAIL_EOF))
|
|
||||||
count = -1;
|
|
||||||
vstring_free(eof);
|
|
||||||
return (count);
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* mail_command_write 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* single-command client
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <mail_proto.h>
|
|
||||||
/*
|
|
||||||
/* int mail_command_write(class, name, format, ...)
|
|
||||||
/* const char *class;
|
|
||||||
/* const char *name;
|
|
||||||
/* const char *format;
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* This module implements a client interface for single-command
|
|
||||||
/* clients: a client that sends a single command and expects
|
|
||||||
/* a single completion status code.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
|
||||||
/* .IP class
|
|
||||||
/* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
|
|
||||||
/* .IP name
|
|
||||||
/* Service name (master.cf).
|
|
||||||
/* .IP format
|
|
||||||
/* Format string understood by mail_print(3).
|
|
||||||
/* DIAGNOSTICS
|
|
||||||
/* The result is -1 if the request could not be sent, otherwise
|
|
||||||
/* the result is the status reported by the server.
|
|
||||||
/* Warnings: problems connecting to the requested service.
|
|
||||||
/* Fatal: out of memory.
|
|
||||||
/* SEE ALSO
|
|
||||||
/* mail_command_read(3), server interface
|
|
||||||
/* mail_proto(5h), client-server protocol
|
|
||||||
/* 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 <stdlib.h> /* 44BSD stdarg.h uses abort() */
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <vstream.h>
|
|
||||||
|
|
||||||
/* Global library. */
|
|
||||||
|
|
||||||
#include "mail_proto.h"
|
|
||||||
|
|
||||||
/* mail_command_write - single-command transaction with completion status */
|
|
||||||
|
|
||||||
int mail_command_write(const char *class, const char *name,
|
|
||||||
const char *fmt,...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
VSTREAM *stream;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Talk a little protocol with the specified service.
|
|
||||||
*/
|
|
||||||
if ((stream = mail_connect(class, name, BLOCKING)) == 0)
|
|
||||||
return (-1);
|
|
||||||
va_start(ap, fmt);
|
|
||||||
status = mail_vprint(stream, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
if (status != 0
|
|
||||||
|| mail_print(stream, "%s", MAIL_EOF) != 0
|
|
||||||
|| vstream_fflush(stream) != 0
|
|
||||||
|| mail_scan(stream, "%d", &status) != 1)
|
|
||||||
status = -1;
|
|
||||||
(void) vstream_fclose(stream);
|
|
||||||
return (status);
|
|
||||||
}
|
|
|
@ -1,206 +0,0 @@
|
||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* mail_print 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* intra-mail system write routine
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <mail_proto.h>
|
|
||||||
/*
|
|
||||||
/* int mail_print(stream, format, ...)
|
|
||||||
/* VSTREAM *stream;
|
|
||||||
/* const char *format;
|
|
||||||
/*
|
|
||||||
/* int mail_vprint(stream, format, ap)
|
|
||||||
/* VSTREAM *stream;
|
|
||||||
/* const char *format;
|
|
||||||
/* va_list ap;
|
|
||||||
/*
|
|
||||||
/* void mail_print_register(letter, name, print_fn)
|
|
||||||
/* int letter;
|
|
||||||
/* const char *name;
|
|
||||||
/* void (*print_fn)(VSTREAM *stream, const char *data);
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* mail_print() prints one or more null-delimited strings to
|
|
||||||
/* the named stream, each string being converted according to the
|
|
||||||
/* contents of the \fIformat\fR argument.
|
|
||||||
/*
|
|
||||||
/* mail_vprint() provides an alternative interface.
|
|
||||||
/*
|
|
||||||
/* mail_print_register() registers the named print function for
|
|
||||||
/* the specified letter, for the named type.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
|
||||||
/* .IP stream
|
|
||||||
/* The stream to print to.
|
|
||||||
/* .IP format
|
|
||||||
/* Format string, which is interpreted as follows:
|
|
||||||
/* .RS
|
|
||||||
/* .IP "white space"
|
|
||||||
/* White space in the format string is ignored.
|
|
||||||
/* .IP %s
|
|
||||||
/* The corresponding argument has type (char *).
|
|
||||||
/* .IP %d
|
|
||||||
/* The corresponding argument has type (int).
|
|
||||||
/* .IP %ld
|
|
||||||
/* The corresponding argument has type (long).
|
|
||||||
/* .IP %letter
|
|
||||||
/* Call the print routine that was registered for the specified letter.
|
|
||||||
/* .PP
|
|
||||||
/* Anything else in a format string is a fatal error.
|
|
||||||
/* .RE
|
|
||||||
/* .IP letter
|
|
||||||
/* Format letter that is bound to the \fIprint_fn\fR print function.
|
|
||||||
/* .IP name
|
|
||||||
/* Descriptive string for verbose logging.
|
|
||||||
/* .IP print_fn
|
|
||||||
/* A print function. It takes as arguments:
|
|
||||||
/* .RS
|
|
||||||
/* .IP stream
|
|
||||||
/* The stream to print to.
|
|
||||||
/* .IP data
|
|
||||||
/* A generic data pointer. It is up to the function
|
|
||||||
/* to do any necessary casts to the data-specific type.
|
|
||||||
/* .RE
|
|
||||||
/* 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 <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <msg.h>
|
|
||||||
#include <mymalloc.h>
|
|
||||||
#include <vstream.h>
|
|
||||||
|
|
||||||
/* Global library. */
|
|
||||||
|
|
||||||
#include "mail_proto.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provision for the user to register type-specific scanners for
|
|
||||||
* applications with unusual requirements.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int letter;
|
|
||||||
char *name;
|
|
||||||
MAIL_PRINT_FN print_fn;
|
|
||||||
} MAIL_PRINT;
|
|
||||||
|
|
||||||
MAIL_PRINT *mail_print_tab = 0;
|
|
||||||
int mail_print_tablen = 0;
|
|
||||||
|
|
||||||
/* mail_print_register - register printer function */
|
|
||||||
|
|
||||||
void mail_print_register(int letter, const char *name, MAIL_PRINT_FN print_fn)
|
|
||||||
{
|
|
||||||
MAIL_PRINT *tp;
|
|
||||||
|
|
||||||
for (tp = 0; tp < mail_print_tab + mail_print_tablen; tp++)
|
|
||||||
if (tp->letter == letter)
|
|
||||||
msg_panic("mail_print_register: redefined letter: %c", letter);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tight fit allocation. We're not registering lots of characters.
|
|
||||||
*/
|
|
||||||
if (mail_print_tab == 0) {
|
|
||||||
mail_print_tablen = 1;
|
|
||||||
mail_print_tab = (MAIL_PRINT *)
|
|
||||||
mymalloc(sizeof(*mail_print_tab) * mail_print_tablen);
|
|
||||||
} else {
|
|
||||||
mail_print_tablen++;
|
|
||||||
mail_print_tab = (MAIL_PRINT *)
|
|
||||||
myrealloc((char *) mail_print_tab,
|
|
||||||
sizeof(*mail_print_tab) * mail_print_tablen);
|
|
||||||
}
|
|
||||||
tp = mail_print_tab + mail_print_tablen - 1;
|
|
||||||
tp->letter = letter;
|
|
||||||
tp->name = mystrdup(name);
|
|
||||||
tp->print_fn = print_fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_vprint - print null-delimited data to stream */
|
|
||||||
|
|
||||||
int mail_vprint(VSTREAM *stream, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
const char *cp;
|
|
||||||
int lflag;
|
|
||||||
char *sval;
|
|
||||||
int ival;
|
|
||||||
long lval;
|
|
||||||
int error;
|
|
||||||
MAIL_PRINT *tp;
|
|
||||||
|
|
||||||
for (cp = fmt; (error = vstream_ferror(stream)) == 0 && *cp != 0; cp++) {
|
|
||||||
if (ISSPACE(*cp))
|
|
||||||
continue;
|
|
||||||
if (*cp != '%')
|
|
||||||
msg_fatal("mail_vprint: bad format: %.*s>%c<%s",
|
|
||||||
(int) (cp - fmt), fmt, *cp, cp + 1);
|
|
||||||
if ((lflag = (*++cp == 'l')) != 0)
|
|
||||||
cp++;
|
|
||||||
|
|
||||||
switch (*cp) {
|
|
||||||
case 's':
|
|
||||||
sval = va_arg(ap, char *);
|
|
||||||
if (msg_verbose)
|
|
||||||
msg_info("print string: %s", sval);
|
|
||||||
vstream_fputs(sval, stream);
|
|
||||||
VSTREAM_PUTC(0, stream);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
if (lflag) {
|
|
||||||
lval = va_arg(ap, long);
|
|
||||||
if (msg_verbose)
|
|
||||||
msg_info("print long: %ld", lval);
|
|
||||||
vstream_fprintf(stream, "%ld", lval);
|
|
||||||
} else {
|
|
||||||
ival = va_arg(ap, int);
|
|
||||||
if (msg_verbose)
|
|
||||||
msg_info("print int: %d", ival);
|
|
||||||
vstream_fprintf(stream, "%d", ival);
|
|
||||||
}
|
|
||||||
VSTREAM_PUTC(0, stream);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
for (tp = mail_print_tab; tp < mail_print_tab + mail_print_tablen; tp++)
|
|
||||||
if (tp->letter == *cp) {
|
|
||||||
if (msg_verbose)
|
|
||||||
msg_info("print %s", tp->name);
|
|
||||||
tp->print_fn(stream, va_arg(ap, char *));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (tp >= mail_print_tab + mail_print_tablen)
|
|
||||||
msg_fatal("mail_vprint: bad format: %.*s>%c<%s",
|
|
||||||
(int) (cp - fmt), fmt, *cp, cp + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_print - print null-delimited data to stream */
|
|
||||||
|
|
||||||
int mail_print(VSTREAM *stream, const char *fmt,...)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
status = mail_vprint(stream, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return (status);
|
|
||||||
}
|
|
|
@ -1,272 +0,0 @@
|
||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* mail_scan 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* intra-mail read routine
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <mail_proto.h>
|
|
||||||
/*
|
|
||||||
/* int mail_scan(stream, format, ...)
|
|
||||||
/* VSTREAM *stream;
|
|
||||||
/* const char *format;
|
|
||||||
/*
|
|
||||||
/* void mail_scan_register(letter, name, scan_fn)
|
|
||||||
/* int letter;
|
|
||||||
/* const char *name;
|
|
||||||
/* int (*scan_fn)(const char *string, char *result);
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* mail_scan() reads one or more null-delimited strings from
|
|
||||||
/* the named stream, each string being converted according to the
|
|
||||||
/* contents of the \fIformat\fR argument.
|
|
||||||
/* The result value is the number of successful conversions.
|
|
||||||
/*
|
|
||||||
/* mail_scan_register() registers an input conversion function
|
|
||||||
/* for the specified letter.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
|
||||||
/* .IP stream
|
|
||||||
/* Stream to read from.
|
|
||||||
/* .IP format
|
|
||||||
/* Format string, which is interpreted as follows:
|
|
||||||
/* .RS
|
|
||||||
/* .IP "white space"
|
|
||||||
/* White space in the format string is ignored.
|
|
||||||
/* .IP %s
|
|
||||||
/* The corresponding argument has type (VSTRING *).
|
|
||||||
/* .IP %d
|
|
||||||
/* The corresponding argument has type (int *).
|
|
||||||
/* .IP %ld
|
|
||||||
/* The corresponding argument has type (long *).
|
|
||||||
/* .IP %letter
|
|
||||||
/* Call the input conversion routine that was registered for
|
|
||||||
/* the specified letter.
|
|
||||||
/* .PP
|
|
||||||
/* Anything else in a format string is a fatal error.
|
|
||||||
/* .RE
|
|
||||||
/* .IP letter
|
|
||||||
/* Format letter that is bound to the \fIscan_fn\fR input
|
|
||||||
/* conversion function.
|
|
||||||
/* .IP name
|
|
||||||
/* Descriptive string for verbose logging.
|
|
||||||
/* .IP scan_fn
|
|
||||||
/* An input conversion function. It takes as arguments:
|
|
||||||
/* .RS
|
|
||||||
/* .IP string
|
|
||||||
/* The null-terminated string to be converted.
|
|
||||||
/* .IP result
|
|
||||||
/* A character pointer to the result. It is up to the function
|
|
||||||
/* to do any necessary casts to the data-specific type.
|
|
||||||
/* .RE
|
|
||||||
/* .PP
|
|
||||||
/* The function result values are as follows:
|
|
||||||
/* .RS
|
|
||||||
/* .IP MAIL_SCAN_ERROR
|
|
||||||
/* The expected input could not be read.
|
|
||||||
/* .IP MAIL_SCAN_DONE
|
|
||||||
/* The operation completed successfully.
|
|
||||||
/* .IP MAIL_SCAN_MORE
|
|
||||||
/* More input is expected.
|
|
||||||
/* .RE
|
|
||||||
/* 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 <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <msg.h>
|
|
||||||
#include <vstring.h>
|
|
||||||
#include <vstream.h>
|
|
||||||
#include <vstring_vstream.h>
|
|
||||||
#include <mymalloc.h>
|
|
||||||
|
|
||||||
/* Global library. */
|
|
||||||
|
|
||||||
#include "mail_proto.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provision for the user to register type-specific input conversion
|
|
||||||
* routines for applications with unusual requirements.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int letter;
|
|
||||||
char *name;
|
|
||||||
MAIL_SCAN_FN scanner;
|
|
||||||
} MAIL_SCAN;
|
|
||||||
|
|
||||||
MAIL_SCAN *mail_scan_tab = 0;
|
|
||||||
int mail_scan_tablen = 0;
|
|
||||||
|
|
||||||
/* mail_scan_register - register scanner function */
|
|
||||||
|
|
||||||
void mail_scan_register(int letter, const char *name, MAIL_SCAN_FN scanner)
|
|
||||||
{
|
|
||||||
MAIL_SCAN *tp;
|
|
||||||
|
|
||||||
for (tp = 0; tp < mail_scan_tab + mail_scan_tablen; tp++)
|
|
||||||
if (tp->letter == letter)
|
|
||||||
msg_panic("mail_scan_register: redefined letter: %c", letter);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tight fit allocation (as in: Robin Hood and the men that wear tights).
|
|
||||||
*/
|
|
||||||
if (mail_scan_tab == 0) {
|
|
||||||
mail_scan_tablen = 1;
|
|
||||||
mail_scan_tab = (MAIL_SCAN *)
|
|
||||||
mymalloc(sizeof(*mail_scan_tab) * mail_scan_tablen);
|
|
||||||
} else {
|
|
||||||
mail_scan_tablen++;
|
|
||||||
mail_scan_tab = (MAIL_SCAN *)
|
|
||||||
myrealloc((char *) mail_scan_tab,
|
|
||||||
sizeof(*mail_scan_tab) * mail_scan_tablen);
|
|
||||||
}
|
|
||||||
tp = mail_scan_tab + mail_scan_tablen - 1;
|
|
||||||
tp->letter = letter;
|
|
||||||
tp->name = mystrdup(name);
|
|
||||||
tp->scanner = scanner;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_scan_any - read one null-delimited string from stream */
|
|
||||||
|
|
||||||
static int mail_scan_any(VSTREAM *stream, VSTRING *vp, char *what)
|
|
||||||
{
|
|
||||||
if (vstring_fgets_null(vp, stream) == 0) {
|
|
||||||
msg_warn("end of input while receiving %s data from service %s",
|
|
||||||
what, VSTREAM_PATH(stream));
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (msg_verbose)
|
|
||||||
msg_info("mail_scan_any: read %s: %s", what, vstring_str(vp));
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_scan_other - read user-defined type from stream */
|
|
||||||
|
|
||||||
static int mail_scan_other(VSTREAM *stream, VSTRING *vp,
|
|
||||||
MAIL_SCAN *tp, char *result)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
while ((ret = mail_scan_any(stream, vp, tp->name)) == 0) {
|
|
||||||
switch (tp->scanner(vstring_str(vp), result)) {
|
|
||||||
case MAIL_SCAN_MORE:
|
|
||||||
break;
|
|
||||||
case MAIL_SCAN_DONE:
|
|
||||||
return (0);
|
|
||||||
case MAIL_SCAN_ERROR:
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_scan_long - read long integer from stream */
|
|
||||||
|
|
||||||
static int mail_scan_long(VSTREAM *stream, VSTRING *vp, long *lp)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
char junk;
|
|
||||||
|
|
||||||
if ((ret = mail_scan_any(stream, vp, "long integer")) == 0) {
|
|
||||||
if (sscanf(vstring_str(vp), "%ld%c", lp, &junk) != 1) {
|
|
||||||
msg_warn("mail_scan_long: bad long long: %s", vstring_str(vp));
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_scan_int - read integer from stream */
|
|
||||||
|
|
||||||
static int mail_scan_int(VSTREAM *stream, VSTRING *vp, int *lp)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
char junk;
|
|
||||||
|
|
||||||
if ((ret = mail_scan_any(stream, vp, "integer")) == 0) {
|
|
||||||
if (sscanf(vstring_str(vp), "%d%c", lp, &junk) != 1) {
|
|
||||||
msg_warn("mail_scan_int: bad integer: %s", vstring_str(vp));
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_scan - read null-delimited data from stream */
|
|
||||||
|
|
||||||
int mail_scan(VSTREAM *stream, const char *fmt,...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
count = mail_vscan(stream, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return (count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mail_vscan - read null-delimited data from stream */
|
|
||||||
|
|
||||||
int mail_vscan(VSTREAM *stream, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
const char *cp;
|
|
||||||
int lflag;
|
|
||||||
int count;
|
|
||||||
int error;
|
|
||||||
static VSTRING *tmp;
|
|
||||||
MAIL_SCAN *tp;
|
|
||||||
|
|
||||||
if (tmp == 0)
|
|
||||||
tmp = vstring_alloc(100);
|
|
||||||
|
|
||||||
for (count = 0, error = 0, cp = fmt; error == 0 && *cp != 0; cp++) {
|
|
||||||
if (ISSPACE(*cp))
|
|
||||||
continue;
|
|
||||||
if (*cp != '%')
|
|
||||||
msg_fatal("mail_scan: bad format: %.*s>%c<%s",
|
|
||||||
(int) (cp - fmt), fmt, *cp, cp + 1);
|
|
||||||
if ((lflag = (*++cp == 'l')) != 0)
|
|
||||||
cp++;
|
|
||||||
|
|
||||||
switch (*cp) {
|
|
||||||
case 's':
|
|
||||||
error = mail_scan_any(stream, va_arg(ap, VSTRING *), "string");
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
if (lflag)
|
|
||||||
error = mail_scan_long(stream, tmp, va_arg(ap, long *));
|
|
||||||
else
|
|
||||||
error = mail_scan_int(stream, tmp, va_arg(ap, int *));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
for (tp = mail_scan_tab; tp < mail_scan_tab + mail_scan_tablen; tp++)
|
|
||||||
if (tp->letter == *cp) {
|
|
||||||
if (msg_verbose)
|
|
||||||
msg_info("mail_scan: %s", tp->name);
|
|
||||||
error = mail_scan_other(stream, tmp, tp, va_arg(ap, char *));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (tp >= mail_scan_tab + mail_scan_tablen)
|
|
||||||
msg_fatal("mail_scan: bad format: %.*s>%c<%s",
|
|
||||||
(int) (cp - fmt), fmt, *cp, cp + 1);
|
|
||||||
}
|
|
||||||
if (error == 0)
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return (count);
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* attr 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* attribute list manager
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <htable.h>
|
|
||||||
/* #include <attr.h>
|
|
||||||
/*
|
|
||||||
/* void attr_enter(attr, name, value)
|
|
||||||
/* HTABLE *attr;
|
|
||||||
/* const char *name;
|
|
||||||
/* const char *value;
|
|
||||||
/*
|
|
||||||
/* const char *attr_find(attr, name)
|
|
||||||
/* HTABLE *attr;
|
|
||||||
/* const char *name;
|
|
||||||
/*
|
|
||||||
/* void attr_free(attr)
|
|
||||||
/* HTABLE *attr;
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* This module maintains open attribute lists of string-valued
|
|
||||||
/* names and values. The module is built on top of the generic
|
|
||||||
/* htable(3) hash table manager.
|
|
||||||
/*
|
|
||||||
/* attr_enter() adds a new attribute or updates an existing one.
|
|
||||||
/* Both the name and the value are copied.
|
|
||||||
/*
|
|
||||||
/* attr_find() looks up the named attribute. It returns the
|
|
||||||
/* corresponding value if one is found, a null pointer otherwise.
|
|
||||||
/*
|
|
||||||
/* attr_free() destroys the named attribute list and makes its
|
|
||||||
/* memory available for reuse.
|
|
||||||
/* BUGS
|
|
||||||
/* This module cannot store null pointer values. If that is a
|
|
||||||
/* problem, use the raw hash table management routines instead.
|
|
||||||
/* 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 "mymalloc.h"
|
|
||||||
#include "htable.h"
|
|
||||||
#include "attr.h"
|
|
||||||
|
|
||||||
/* attr_enter - add or replace attribute */
|
|
||||||
|
|
||||||
void attr_enter(HTABLE *attr, const char *name, const char *value)
|
|
||||||
{
|
|
||||||
HTABLE_INFO *ht;
|
|
||||||
|
|
||||||
if ((ht = htable_locate(attr, name)) != 0) {/* replace attribute */
|
|
||||||
myfree(ht->value);
|
|
||||||
ht->value = mystrdup(value);
|
|
||||||
} else { /* add attribute */
|
|
||||||
(void) htable_enter(attr, name, mystrdup(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attr_free - destroy attribute list */
|
|
||||||
|
|
||||||
void attr_free(HTABLE *attr)
|
|
||||||
{
|
|
||||||
htable_free(attr, myfree);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue