not part of release 1.1.2

This commit is contained in:
perry 2002-02-02 23:27:32 +00:00
parent 1f31e11b0f
commit 5cf194aa6d
30 changed files with 0 additions and 3720 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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).

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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. :-)

View File

@ -1,2 +0,0 @@
See the files in auxiliary/MacOSX for hints and tips to set up
Postfix.

View File

@ -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.

View File

@ -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.]

View File

@ -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.

View File

@ -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.

160
gnu/dist/postfix/TODO vendored
View File

@ -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.

View File

@ -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]

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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";
};
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}