Import Postfix-2.2.5.

This commit is contained in:
rpaulo 2005-08-18 21:07:25 +00:00
parent dd3453b45c
commit 259d7fd128
239 changed files with 19004 additions and 1840 deletions

74
gnu/dist/postfix/src/anvil/Makefile.in vendored Normal file
View File

@ -0,0 +1,74 @@
SHELL = /bin/sh
SRCS = anvil.c
OBJS = anvil.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
PROG = anvil
INC_DIR = ../../include
LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
.c.o:; $(CC) $(CFLAGS) -c $*.c
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
tests: test
update: ../../libexec/$(PROG)
../../libexec/$(PROG): $(PROG)
cp $(PROG) ../../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
lint:
lint $(DEFS) $(SRCS) $(LINTFIX)
clean:
rm -f *.o *core $(PROG) $(TESTPROG) junk
rm -rf printfck
tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend'
anvil.o: anvil.c
anvil.o: ../../include/sys_defs.h
anvil.o: ../../include/msg.h
anvil.o: ../../include/mymalloc.h
anvil.o: ../../include/htable.h
anvil.o: ../../include/stringops.h
anvil.o: ../../include/vstring.h
anvil.o: ../../include/vbuf.h
anvil.o: ../../include/events.h
anvil.o: ../../include/mail_conf.h
anvil.o: ../../include/mail_params.h
anvil.o: ../../include/mail_proto.h
anvil.o: ../../include/vstream.h
anvil.o: ../../include/iostuff.h
anvil.o: ../../include/attr.h
anvil.o: ../../include/anvil_clnt.h
anvil.o: ../../include/attr_clnt.h
anvil.o: ../../include/mail_server.h

872
gnu/dist/postfix/src/anvil/anvil.c vendored Normal file
View File

@ -0,0 +1,872 @@
/* $NetBSD: anvil.c,v 1.1.1.1 2005/08/18 21:07:49 rpaulo Exp $ */
/*++
/* NAME
/* anvil 8
/* SUMMARY
/* Postfix session count and request rate control
/* SYNOPSIS
/* \fBanvil\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The Postfix \fBanvil\fR(8) server maintains short-term statistics
/* to defend against clients that hammer a server with either too
/* many simultaneous sessions, or with too many successive requests
/* within a configurable time interval.
/* This server is designed to run under control by the Postfix
/* \fBmaster\fR(8) server.
/*
/* The \fBanvil\fR(8) server maintains no persistent database. Standard
/* library utilities do not meet Postfix performance and robustness
/* requirements.
/* CONNECTION COUNT/RATE LIMITING
/* .ad
/* .fi
/* When a remote client connects, a connection count (or rate) limited
/* server should send the following request to the \fBanvil\fR(8) server:
/* .PP
/* .in +4
/* \fBrequest=connect\fR
/* .br
/* \fBident=\fIstring\fR
/* .in
/* .PP
/* This registers a new connection for the (service, client)
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
/* answers with the number of simultaneous connections and the
/* number of connections per unit time for that (service, client)
/* combination:
/* .PP
/* .in +4
/* \fBstatus=0\fR
/* .br
/* \fBcount=\fInumber\fR
/* .br
/* \fBrate=\fInumber\fR
/* .in
/* .PP
/* The \fBrate\fR is computed as the number of connections
/* that were registered in the current "time unit" interval.
/* It is left up to the server to decide if the remote client
/* exceeds the connection count (or rate) limit.
/* .PP
/* When a remote client disconnects, a connection count (or rate) limited
/* server should send the following request to the \fBanvil\fR(8) server:
/* .PP
/* .in +4
/* \fBrequest=disconnect\fR
/* .br
/* \fBident=\fIstring\fR
/* .in
/* .PP
/* This registers a disconnect event for the (service, client)
/* combination specified with \fBident\fR. The \fBanvil\fR(8)
/* server replies with:
/* .PP
/* .ti +4
/* \fBstatus=0\fR
/* MESSAGE RATE LIMITING
/* .ad
/* .fi
/* When a remote client sends a message delivery request, a
/* message rate limited server should send the following
/* request to the \fBanvil\fR(8) server:
/* .PP
/* .in +4
/* \fBrequest=message\fR
/* .br
/* \fBident=\fIstring\fR
/* .in
/* .PP
/* This registers a message delivery request for the (service, client)
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
/* answers with the number of message delivery requests per unit time
/* for that (service, client) combination:
/* .PP
/* .in +4
/* \fBstatus=0\fR
/* .br
/* \fBrate=\fInumber\fR
/* .in
/* .PP
/* In order to prevent the \fBanvil\fR(8) server from discarding client
/* request rates too early or too late, a message rate limited
/* service should also register connect/disconnect events.
/* RECIPIENT RATE LIMITING
/* .ad
/* .fi
/* When a remote client sends a recipient address, a recipient
/* rate limited server should send the following request to
/* the \fBanvil\fR(8) server:
/* .PP
/* .in +4
/* \fBrequest=recipient\fR
/* .br
/* \fBident=\fIstring\fR
/* .in
/* .PP
/* This registers a recipient request for the (service, client)
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
/* answers with the number of recipient addresses per unit time
/* for that (service, client) combination:
/* .PP
/* .in +4
/* \fBstatus=0\fR
/* .br
/* \fBrate=\fInumber\fR
/* .in
/* .PP
/* In order to prevent the \fBanvil\fR(8) server from discarding client
/* request rates too early or too late, a recipient rate limited
/* service should also register connect/disconnect events.
/* SECURITY
/* .ad
/* .fi
/* The \fBanvil\fR(8) server does not talk to the network or to local
/* users, and can run chrooted at fixed low privilege.
/*
/* The \fBanvil\fR(8) server maintains an in-memory table with information
/* about recent clients of a connection count (or rate) limited service.
/* Although state is kept only temporarily, this may require a lot of
/* memory on systems that handle connections from many remote clients.
/* To reduce memory usage, reduce the time unit over which state
/* is kept.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/*
/* Upon exit, and every \fBanvil_status_update_time\fR
/* seconds, the server logs the maximal count and rate values measured,
/* together with (service, client) information and the time of day
/* associated with those events.
/* In order to avoid unnecessary overhead, no measurements
/* are done for activity that isn't concurrency limited or
/* rate limited.
/* BUGS
/* Systems behind network address translating routers or proxies
/* appear to have the same client address and can run into connection
/* count and/or rate limits falsely.
/*
/* In this preliminary implementation, a count (or rate) limited server
/* can have only one remote client at a time. If a server reports
/* multiple simultaneous clients, all but the last reported client
/* are ignored.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically as \fBanvil\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBanvil_rate_time_unit (60s)\fR"
/* The time unit over which client connection rates and other rates
/* are calculated.
/* .IP "\fBanvil_status_update_time (600s)\fR"
/* How frequently the \fBanvil\fR(8) connection and rate limiting server
/* logs peak usage information.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBdaemon_timeout (18000s)\fR"
/* How much time a Postfix daemon process may take to handle a
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBipc_timeout (3600s)\fR"
/* The time limit for sending or receiving information over an internal
/* communication channel.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process
/* waits for the next service request before exiting.
/* .IP "\fBmax_use (100)\fR"
/* The maximal number of connection requests before a Postfix daemon
/* process terminates.
/* .IP "\fBprocess_id (read-only)\fR"
/* The process ID of a Postfix command or daemon process.
/* .IP "\fBprocess_name (read-only)\fR"
/* The process name of a Postfix command or daemon process.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (postfix)\fR"
/* The mail system name that is prepended to the process name in syslog
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* SEE ALSO
/* smtpd(8), Postfix SMTP server
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* README FILES
/* .ad
/* .fi
/* Use "\fBpostconf readme_directory\fR" or
/* "\fBpostconf html_directory\fR" to locate this information.
/* .na
/* .nf
/* TUNING_README, performance tuning
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* HISTORY
/* .ad
/* .fi
/* The anvil service is available in Postfix 2.2 and later.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/time.h>
#include <limits.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <htable.h>
#include <stringops.h>
#include <events.h>
/* Global library. */
#include <mail_conf.h>
#include <mail_params.h>
#include <mail_proto.h>
#include <anvil_clnt.h>
/* Server skeleton. */
#include <mail_server.h>
/* Application-specific. */
int var_anvil_time_unit;
int var_anvil_stat_time;
/*
* State.
*/
static HTABLE *anvil_remote_map; /* indexed by service+ remote client */
/*
* Absent a real-time query interface, these are logged at process exit time
* and at regular intervals.
*/
static int max_count;
static char *max_count_user;
static time_t max_count_time;
static int max_rate;
static char *max_rate_user;
static time_t max_rate_time;
static int max_mail;
static char *max_mail_user;
static time_t max_mail_time;
static int max_rcpt;
static char *max_rcpt_user;
static time_t max_rcpt_time;
static int max_cache;
static time_t max_cache_time;
/*
* Remote connection state, one instance for each (service, client) pair.
*/
typedef struct {
char *ident; /* lookup key */
int count; /* connection count */
int rate; /* connection rate */
int mail; /* message rate */
int rcpt; /* recipient rate */
time_t start; /* time of first rate sample */
} ANVIL_REMOTE;
/*
* Local server state, one per server instance. This allows us to clean up
* connection state when a local server goes away without cleaning up.
*/
typedef struct {
ANVIL_REMOTE *anvil_remote; /* XXX should be list */
} ANVIL_LOCAL;
/*
* Silly little macros.
*/
#define STR(x) vstring_str(x)
#define STREQ(x,y) (strcmp((x), (y)) == 0)
/*
* The following operations are implemented as macros with recognizable
* names so that we don't lose sight of what the code is trying to do.
*
* Related operations are defined side by side so that the code implementing
* them isn't pages apart.
*/
/* Create new (service, client) state. */
#define ANVIL_REMOTE_FIRST(remote, id) \
do { \
(remote)->ident = mystrdup(id); \
(remote)->count = 1; \
(remote)->rate = 1; \
(remote)->mail = 0; \
(remote)->rcpt = 0; \
(remote)->start = event_time(); \
} while(0)
/* Destroy unused (service, client) state. */
#define ANVIL_REMOTE_FREE(remote) \
do { \
myfree((remote)->ident); \
myfree((char *) (remote)); \
} while(0)
/* Add connection to (service, client) state. */
#define ANVIL_REMOTE_NEXT(remote) \
do { \
time_t _now = event_time(); \
if ((remote)->start + var_anvil_time_unit < _now) { \
(remote)->rate = 1; \
(remote)->mail = 0; \
(remote)->rcpt = 0; \
(remote)->start = _now; \
} else if ((remote)->rate < INT_MAX) { \
(remote)->rate += 1; \
} \
if ((remote)->count == 0) \
event_cancel_timer(anvil_remote_expire, (char *) remote); \
(remote)->count++; \
} while(0)
#define ANVIL_ADD_MAIL(remote) \
do { \
time_t _now = event_time(); \
if ((remote)->start + var_anvil_time_unit < _now) { \
(remote)->rate = 0; \
(remote)->mail = 1; \
(remote)->rcpt = 0; \
(remote)->start = _now; \
} else if ((remote)->mail < INT_MAX) { \
(remote)->mail += 1; \
} \
} while(0)
#define ANVIL_ADD_RCPT(remote) \
do { \
time_t _now = event_time(); \
if ((remote)->start + var_anvil_time_unit < _now) { \
(remote)->rate = 0; \
(remote)->mail = 0; \
(remote)->rcpt = 1; \
(remote)->start = _now; \
} else if ((remote)->rcpt < INT_MAX) { \
(remote)->rcpt += 1; \
} \
} while(0)
/* Drop connection from (service, client) state. */
#define ANVIL_REMOTE_DROP_ONE(remote) \
do { \
if ((remote) && (remote)->count > 0) { \
if (--(remote)->count == 0) \
event_request_timer(anvil_remote_expire, (char *) remote, \
var_anvil_time_unit); \
} \
} while(0)
/* Create local server state. */
#define ANVIL_LOCAL_INIT(local) \
do { \
(local)->anvil_remote = 0; \
} while(0)
/* Add connection to local server. */
#define ANVIL_LOCAL_ADD_ONE(local, remote) \
do { \
/* XXX allow multiple remote clients per local server. */ \
if ((local)->anvil_remote) \
ANVIL_REMOTE_DROP_ONE((local)->anvil_remote); \
(local)->anvil_remote = (remote); \
} while(0)
/* Test if this remote site is listed for this local client. */
#define ANVIL_LOCAL_REMOTE_LINKED(local, remote) \
((local)->anvil_remote == (remote))
/* Drop connection from local server. */
#define ANVIL_LOCAL_DROP_ONE(local, remote) \
do { \
/* XXX allow multiple remote clients per local server. */ \
if ((local)->anvil_remote == (remote)) \
(local)->anvil_remote = 0; \
} while(0)
/* Drop all connections from local server. */
#define ANVIL_LOCAL_DROP_ALL(stream, local) \
do { \
/* XXX allow multiple remote clients per local server. */ \
if ((local)->anvil_remote) \
anvil_remote_disconnect((stream), (local)->anvil_remote->ident); \
} while (0)
/* anvil_remote_expire - purge expired connection state */
static void anvil_remote_expire(int unused_event, char *context)
{
ANVIL_REMOTE *anvil_remote = (ANVIL_REMOTE *) context;
char *myname = "anvil_remote_expire";
if (msg_verbose)
msg_info("%s %s", myname, anvil_remote->ident);
if (anvil_remote->count != 0)
msg_panic("%s: bad connection count: %d",
myname, anvil_remote->count);
htable_delete(anvil_remote_map, anvil_remote->ident,
(void (*) (char *)) 0);
ANVIL_REMOTE_FREE(anvil_remote);
if (msg_verbose)
msg_info("%s: anvil_remote_map used=%d",
myname, anvil_remote_map->used);
}
/* anvil_remote_lookup - dump address status */
static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
char *myname = "anvil_remote_lookup";
HTABLE_INFO **ht_info;
HTABLE_INFO **ht;
if (msg_verbose)
msg_info("%s fd=%d stream=0x%lx ident=%s",
myname, vstream_fileno(client_stream),
(unsigned long) client_stream, ident);
/*
* Look up remote client information.
*/
if (STREQ(ident, "*")) {
attr_print_plain(client_stream, ATTR_FLAG_MORE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
ATTR_TYPE_END);
ht_info = htable_list(anvil_remote_map);
for (ht = ht_info; *ht; ht++) {
anvil_remote = (ANVIL_REMOTE *) ht[0]->value;
attr_print_plain(client_stream, ATTR_FLAG_MORE,
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ht[0]->key,
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
ATTR_TYPE_END);
}
attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_END);
myfree((char *) ht_info);
} else if ((anvil_remote =
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, 0,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, 0,
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, 0,
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, 0,
ATTR_TYPE_END);
} else {
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
ATTR_TYPE_END);
}
}
/* anvil_remote_conn_update - instantiate or update connection info */
static ANVIL_REMOTE *anvil_remote_conn_update(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
ANVIL_LOCAL *anvil_local;
char *myname = "anvil_remote_conn_update";
if (msg_verbose)
msg_info("%s fd=%d stream=0x%lx ident=%s",
myname, vstream_fileno(client_stream),
(unsigned long) client_stream, ident);
/*
* Look up remote connection count information. Update remote connection
* rate information. Simply reset the counter every var_anvil_time_unit
* seconds. This is easier than maintaining a moving average and it gives
* a quicker response to tresspassers.
*/
if ((anvil_remote =
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
anvil_remote = (ANVIL_REMOTE *) mymalloc(sizeof(*anvil_remote));
ANVIL_REMOTE_FIRST(anvil_remote, ident);
htable_enter(anvil_remote_map, ident, (char *) anvil_remote);
if (max_cache < anvil_remote_map->used) {
max_cache = anvil_remote_map->used;
max_cache_time = event_time();
}
} else {
ANVIL_REMOTE_NEXT(anvil_remote);
}
/*
* Record this connection under the local client information, so that we
* can clean up all its connection state when the local client goes away.
*/
if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) == 0) {
anvil_local = (ANVIL_LOCAL *) mymalloc(sizeof(*anvil_local));
ANVIL_LOCAL_INIT(anvil_local);
vstream_control(client_stream,
VSTREAM_CTL_CONTEXT, (void *) anvil_local,
VSTREAM_CTL_END);
}
ANVIL_LOCAL_ADD_ONE(anvil_local, anvil_remote);
if (msg_verbose)
msg_info("%s: anvil_local 0x%lx",
myname, (unsigned long) anvil_local);
return (anvil_remote);
}
/* anvil_remote_connect - report connection event, query address status */
static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
/*
* Update or instantiate connection info.
*/
anvil_remote = anvil_remote_conn_update(client_stream, ident);
/*
* Respond to the local client.
*/
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
ATTR_TYPE_END);
/*
* Update local statistics.
*/
if (anvil_remote->rate > max_rate) {
max_rate = anvil_remote->rate;
if (max_rate_user == 0) {
max_rate_user = mystrdup(anvil_remote->ident);
} else if (!STREQ(max_rate_user, anvil_remote->ident)) {
myfree(max_rate_user);
max_rate_user = mystrdup(anvil_remote->ident);
}
max_rate_time = event_time();
}
if (anvil_remote->count > max_count) {
max_count = anvil_remote->count;
if (max_count_user == 0) {
max_count_user = mystrdup(anvil_remote->ident);
} else if (!STREQ(max_count_user, anvil_remote->ident)) {
myfree(max_count_user);
max_count_user = mystrdup(anvil_remote->ident);
}
max_count_time = event_time();
}
}
/* anvil_remote_mail - register message delivery request */
static void anvil_remote_mail(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
/*
* Be prepared for "postfix reload" after "connect".
*/
if ((anvil_remote =
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0)
anvil_remote = anvil_remote_conn_update(client_stream, ident);
/*
* Update message delivery request rate and respond to local client.
*/
ANVIL_ADD_MAIL(anvil_remote);
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->mail,
ATTR_TYPE_END);
/*
* Update local statistics.
*/
if (anvil_remote->mail > max_mail) {
max_mail = anvil_remote->mail;
if (max_mail_user == 0) {
max_mail_user = mystrdup(anvil_remote->ident);
} else if (!STREQ(max_mail_user, anvil_remote->ident)) {
myfree(max_mail_user);
max_mail_user = mystrdup(anvil_remote->ident);
}
max_mail_time = event_time();
}
}
/* anvil_remote_rcpt - register recipient address event */
static void anvil_remote_rcpt(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
/*
* Be prepared for "postfix reload" after "connect".
*/
if ((anvil_remote =
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0)
anvil_remote = anvil_remote_conn_update(client_stream, ident);
/*
* Update recipient address rate and respond to local client.
*/
ANVIL_ADD_RCPT(anvil_remote);
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rcpt,
ATTR_TYPE_END);
/*
* Update local statistics.
*/
if (anvil_remote->rcpt > max_rcpt) {
max_rcpt = anvil_remote->rcpt;
if (max_rcpt_user == 0) {
max_rcpt_user = mystrdup(anvil_remote->ident);
} else if (!STREQ(max_rcpt_user, anvil_remote->ident)) {
myfree(max_rcpt_user);
max_rcpt_user = mystrdup(anvil_remote->ident);
}
max_rcpt_time = event_time();
}
}
/* anvil_remote_disconnect - report disconnect event */
static void anvil_remote_disconnect(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
ANVIL_LOCAL *anvil_local;
char *myname = "anvil_remote_disconnect";
if (msg_verbose)
msg_info("%s fd=%d stream=0x%lx ident=%s",
myname, vstream_fileno(client_stream),
(unsigned long) client_stream, ident);
/*
* Update local and remote info if this remote site is listed for this
* local client.
*/
if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) != 0
&& (anvil_remote =
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) != 0
&& ANVIL_LOCAL_REMOTE_LINKED(anvil_local, anvil_remote)) {
ANVIL_REMOTE_DROP_ONE(anvil_remote);
ANVIL_LOCAL_DROP_ONE(anvil_local, anvil_remote);
}
if (msg_verbose)
msg_info("%s: anvil_local 0x%lx",
myname, (unsigned long) anvil_local);
/*
* Respond to the local client.
*/
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
ATTR_TYPE_END);
}
/* anvil_service_done - clean up */
static void anvil_service_done(VSTREAM *client_stream, char *unused_service,
char **unused_argv)
{
ANVIL_LOCAL *anvil_local;
char *myname = "anvil_service_done";
if (msg_verbose)
msg_info("%s fd=%d stream=0x%lx",
myname, vstream_fileno(client_stream),
(unsigned long) client_stream);
/*
* Look up the local client, and get rid of open remote connection state
* that we still have for this local client. Do not destroy remote client
* status information before it expires.
*/
if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) != 0) {
if (msg_verbose)
msg_info("%s: anvil_local 0x%lx",
myname, (unsigned long) anvil_local);
ANVIL_LOCAL_DROP_ALL(client_stream, anvil_local);
myfree((char *) anvil_local);
} else if (msg_verbose)
msg_info("client socket not found for fd=%d",
vstream_fileno(client_stream));
}
/* anvil_service - perform service for client */
static void anvil_service(VSTREAM *client_stream, char *unused_service, char **argv)
{
VSTRING *request = vstring_alloc(10);
VSTRING *ident = vstring_alloc(10);
/*
* Sanity check. This service takes no command-line arguments.
*/
if (argv[0])
msg_fatal("unexpected command-line argument: %s", argv[0]);
/*
* This routine runs whenever a client connects to the socket dedicated
* to the client connection rate management service. All
* connection-management stuff is handled by the common code in
* multi_server.c.
*/
if (msg_verbose)
msg_info("--- start request ---");
if (attr_scan_plain(client_stream,
ATTR_FLAG_MISSING | ATTR_FLAG_STRICT,
ATTR_TYPE_STR, ANVIL_ATTR_REQ, request,
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
ATTR_TYPE_END) == 2) {
if (STREQ(STR(request), ANVIL_REQ_CONN)) {
anvil_remote_connect(client_stream, STR(ident));
} else if (STREQ(STR(request), ANVIL_REQ_MAIL)) {
anvil_remote_mail(client_stream, STR(ident));
} else if (STREQ(STR(request), ANVIL_REQ_RCPT)) {
anvil_remote_rcpt(client_stream, STR(ident));
} else if (STREQ(STR(request), ANVIL_REQ_DISC)) {
anvil_remote_disconnect(client_stream, STR(ident));
} else if (STREQ(STR(request), ANVIL_REQ_LOOKUP)) {
anvil_remote_lookup(client_stream, STR(ident));
} else {
msg_warn("unrecognized request: \"%s\", ignored", STR(request));
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
ATTR_TYPE_END);
}
vstream_fflush(client_stream);
} else {
/* Note: invokes anvil_service_done() */
multi_server_disconnect(client_stream);
}
if (msg_verbose)
msg_info("--- end request ---");
vstring_free(ident);
vstring_free(request);
}
/* post_jail_init - post-jail initialization */
static void anvil_status_update(int, char *);
static void post_jail_init(char *unused_name, char **unused_argv)
{
/*
* Dump and reset extreme usage every so often.
*/
event_request_timer(anvil_status_update, (char *) 0, var_anvil_stat_time);
/*
* Initial client state tables.
*/
anvil_remote_map = htable_create(1000);
/*
* Do not limit the number of client requests.
*/
var_use_limit = 0;
}
/* anvil_status_dump - log and reset extreme usage */
static void anvil_status_dump(char *unused_name, char **unused_argv)
{
if (max_rate > 0) {
msg_info("statistics: max connection rate %d/%ds for (%s) at %.15s",
max_rate, var_anvil_time_unit,
max_rate_user, ctime(&max_rate_time) + 4);
max_rate = 0;
}
if (max_count > 0) {
msg_info("statistics: max connection count %d for (%s) at %.15s",
max_count, max_count_user, ctime(&max_count_time) + 4);
max_count = 0;
}
if (max_mail > 0) {
msg_info("statistics: max message rate %d/%ds for (%s) at %.15s",
max_mail, var_anvil_time_unit,
max_mail_user, ctime(&max_mail_time) + 4);
max_mail = 0;
}
if (max_rcpt > 0) {
msg_info("statistics: max recipient rate %d/%ds for (%s) at %.15s",
max_rcpt, var_anvil_time_unit,
max_rcpt_user, ctime(&max_rcpt_time) + 4);
max_rcpt = 0;
}
if (max_cache > 0) {
msg_info("statistics: max cache size %d at %.15s",
max_cache, ctime(&max_cache_time) + 4);
max_cache = 0;
}
}
/* anvil_status_update - log and reset extreme usage periodically */
static void anvil_status_update(int unused_event, char *context)
{
anvil_status_dump((char *) 0, (char **) 0);
event_request_timer(anvil_status_update, context, var_anvil_stat_time);
}
/* main - pass control to the multi-threaded skeleton */
int main(int argc, char **argv)
{
static CONFIG_TIME_TABLE time_table[] = {
VAR_ANVIL_TIME_UNIT, DEF_ANVIL_TIME_UNIT, &var_anvil_time_unit, 1, 0,
VAR_ANVIL_STAT_TIME, DEF_ANVIL_STAT_TIME, &var_anvil_stat_time, 1, 0,
0,
};
multi_server_main(argc, argv, anvil_service,
MAIL_SERVER_TIME_TABLE, time_table,
MAIL_SERVER_POST_INIT, post_jail_init,
MAIL_SERVER_SOLITARY,
MAIL_SERVER_PRE_DISCONN, anvil_service_done,
MAIL_SERVER_EXIT, anvil_status_dump,
0);
}

View File

@ -0,0 +1,69 @@
SHELL = /bin/sh
SRCS = discard.c
OBJS = discard.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
PROG = discard
INC_DIR = ../../include
LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
.c.o:; $(CC) $(CFLAGS) -c $*.c
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
tests: test
update: ../../libexec/$(PROG)
../../libexec/$(PROG): $(PROG)
cp $(PROG) ../../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
lint:
lint $(DEFS) $(SRCS) $(LINTFIX)
clean:
rm -f *.o *core $(PROG) $(TESTPROG) junk
rm -rf printfck
tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend'
discard.o: discard.c
discard.o: ../../include/sys_defs.h
discard.o: ../../include/msg.h
discard.o: ../../include/vstream.h
discard.o: ../../include/vbuf.h
discard.o: ../../include/deliver_request.h
discard.o: ../../include/vstring.h
discard.o: ../../include/recipient_list.h
discard.o: ../../include/mail_queue.h
discard.o: ../../include/bounce.h
discard.o: ../../include/deliver_completed.h
discard.o: ../../include/flush_clnt.h
discard.o: ../../include/mail_server.h

229
gnu/dist/postfix/src/discard/discard.c vendored Normal file
View File

@ -0,0 +1,229 @@
/* $NetBSD: discard.c,v 1.1.1.1 2005/08/18 21:11:02 rpaulo Exp $ */
/*++
/* NAME
/* discard 8
/* SUMMARY
/* Postfix discard mail delivery agent
/* SYNOPSIS
/* \fBdiscard\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The Postfix \fBdiscard\fR(8) delivery agent processes
/* delivery requests from
/* the queue manager. Each request specifies a queue file, a sender
/* address, a domain or host name that is treated as the reason for
/* discarding the mail, and recipient information.
/* This program expects to be run from the \fBmaster\fR(8) process
/* manager.
/*
/* The \fBdiscard\fR(8) delivery agent pretends to deliver all recipients
/* in the delivery request, logs the "next-hop" domain or host
/* information as the reason for discarding the mail, updates the
/* queue file and marks recipients as finished or informs the
/* queue manager that delivery should be tried again at a later time.
/*
/* Delivery status reports are sent to the \fBtrace\fR(8)
/* daemon as appropriate.
/* SECURITY
/* .ad
/* .fi
/* The \fBdiscard\fR(8) mailer is not security-sensitive. It does not talk
/* to the network, and can be run chrooted at fixed low privilege.
/* STANDARDS
/* None.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/*
/* Depending on the setting of the \fBnotify_classes\fR parameter,
/* the postmaster is notified of bounces and of other trouble.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically as \fBdiscard\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBdaemon_timeout (18000s)\fR"
/* How much time a Postfix daemon process may take to handle a
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBdouble_bounce_sender (double-bounce)\fR"
/* The sender address of postmaster notifications that are generated
/* by the mail system.
/* .IP "\fBipc_timeout (3600s)\fR"
/* The time limit for sending or receiving information over an internal
/* communication channel.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process
/* waits for the next service request before exiting.
/* .IP "\fBmax_use (100)\fR"
/* The maximal number of connection requests before a Postfix daemon
/* process terminates.
/* .IP "\fBprocess_id (read-only)\fR"
/* The process ID of a Postfix command or daemon process.
/* .IP "\fBprocess_name (read-only)\fR"
/* The process name of a Postfix command or daemon process.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/* The location of the Postfix top-level queue directory.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (postfix)\fR"
/* The mail system name that is prepended to the process name in syslog
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* SEE ALSO
/* qmgr(8), queue manager
/* bounce(8), delivery status reports
/* error(8), Postfix error delivery agent
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* master(8), process manager
/* syslogd(8), system logging
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* HISTORY
/* This service was introduced with Postfix version 2.2.
/* AUTHOR(S)
/* Victor Duchovni
/* Morgan Stanley
/*
/* Based on code by:
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <unistd.h>
#include <stdlib.h>
/* Utility library. */
#include <msg.h>
#include <vstream.h>
/* Global library. */
#include <deliver_request.h>
#include <mail_queue.h>
#include <bounce.h>
#include <deliver_completed.h>
#include <flush_clnt.h>
#include <sent.h>
/* Single server skeleton. */
#include <mail_server.h>
/* deliver_message - deliver message with extreme prejudice */
static int deliver_message(DELIVER_REQUEST *request)
{
char *myname = "deliver_message";
VSTREAM *src;
int result = 0;
int status;
RECIPIENT *rcpt;
int nrcpt;
if (msg_verbose)
msg_info("deliver_message: from %s", request->sender);
/*
* Sanity checks.
*/
if (request->nexthop[0] == 0)
msg_fatal("empty nexthop hostname");
if (request->rcpt_list.len <= 0)
msg_fatal("recipient count: %d", request->rcpt_list.len);
/*
* Open the queue file. Opening the file can fail for a variety of
* reasons, such as the system running out of resources. Instead of
* throwing away mail, we're raising a fatal error which forces the mail
* system to back off, and retry later.
*/
src = mail_queue_open(request->queue_name, request->queue_id,
O_RDWR, 0);
if (src == 0)
msg_fatal("%s: open %s %s: %m", myname,
request->queue_name, request->queue_id);
if (msg_verbose)
msg_info("%s: file %s", myname, VSTREAM_PATH(src));
/*
* Discard all recipients.
*/
#define BOUNCE_FLAGS(request) DEL_REQ_TRACE_FLAGS(request->flags)
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset >= 0) {
status = sent(BOUNCE_FLAGS(request), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset, "none",
request->arrival_time, "%s", request->nexthop);
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
deliver_completed(src, rcpt->offset);
result |= status;
}
}
/*
* Clean up.
*/
if (vstream_fclose(src))
msg_warn("close %s %s: %m", request->queue_name, request->queue_id);
return (result);
}
/* discard_service - perform service for client */
static void discard_service(VSTREAM *client_stream, char *unused_service, char **argv)
{
DELIVER_REQUEST *request;
int status;
/*
* Sanity check. This service takes no command-line arguments.
*/
if (argv[0])
msg_fatal("unexpected command-line argument: %s", argv[0]);
/*
* This routine runs whenever a client connects to the UNIX-domain socket
* dedicated to the discard mailer. What we see below is a little
* protocol to (1) tell the queue manager that we are ready, (2) read a
* request from the queue manager, and (3) report the completion status
* of that request. All connection-management stuff is handled by the
* common code in single_server.c.
*/
if ((request = deliver_request_read(client_stream)) != 0) {
status = deliver_message(request);
deliver_request_done(client_stream, request, status);
}
}
/* pre_init - pre-jail initialization */
static void pre_init(char *unused_name, char **unused_argv)
{
flush_init();
}
/* main - pass control to the single-threaded skeleton */
int main(int argc, char **argv)
{
single_server_main(argc, argv, discard_service,
MAIL_SERVER_PRE_INIT, pre_init,
0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: forward.c,v 1.1.1.5 2004/05/31 00:24:37 heas Exp $ */
/* $NetBSD: forward.c,v 1.1.1.6 2005/08/18 21:07:25 rpaulo Exp $ */
/*++
/* NAME
@ -113,7 +113,7 @@ int forward_init(void)
/* forward_open - open connection to cleanup service */
static FORWARD_INFO *forward_open(char *sender)
static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, char *sender)
{
VSTRING *buffer = vstring_alloc(100);
FORWARD_INFO *info;
@ -156,6 +156,25 @@ static FORWARD_INFO *forward_open(char *sender)
rec_fprintf(cleanup, REC_TYPE_TIME, "%ld", (long) info->posting_time);
rec_fputs(cleanup, REC_TYPE_FROM, sender);
/*
* Zero-length attribute values are place holders for unavailable
* attribute values. See qmgr_message.c. They are not meant to be
* propagated to queue files.
*/
#define PASS_ATTR(fp, name, value) do { \
if ((value) && *(value)) \
rec_fprintf((fp), REC_TYPE_ATTR, "%s=%s", (name), (value)); \
} while (0)
PASS_ATTR(cleanup, MAIL_ATTR_CLIENT_NAME, request->client_name);
PASS_ATTR(cleanup, MAIL_ATTR_CLIENT_ADDR, request->client_addr);
PASS_ATTR(cleanup, MAIL_ATTR_PROTO_NAME, request->client_proto);
PASS_ATTR(cleanup, MAIL_ATTR_HELO_NAME, request->client_helo);
PASS_ATTR(cleanup, MAIL_ATTR_SASL_METHOD, request->sasl_method);
PASS_ATTR(cleanup, MAIL_ATTR_SASL_USERNAME, request->sasl_username);
PASS_ATTR(cleanup, MAIL_ATTR_SASL_SENDER, request->sasl_sender);
PASS_ATTR(cleanup, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context);
vstring_free(buffer);
return (info);
}
@ -185,7 +204,7 @@ int forward_append(DELIVER_ATTR attr)
htable_enter(forward_dt, attr.delivered, (char *) table_snd);
}
if ((info = (FORWARD_INFO *) htable_find(table_snd, attr.sender)) == 0) {
if ((info = forward_open(attr.sender)) == 0)
if ((info = forward_open(attr.request, attr.sender)) == 0)
return (-1);
htable_enter(table_snd, attr.sender, (char *) info);
}
@ -234,8 +253,11 @@ static int forward_send(FORWARD_INFO *info, DELIVER_REQUEST *request,
break;
status = (REC_PUT_BUF(info->cleanup, rec_type, buffer) != rec_type);
}
if (status == 0 && rec_type != REC_TYPE_XTRA)
if (status == 0 && rec_type != REC_TYPE_XTRA) {
msg_warn("%s: bad record type: %d in message content",
info->queue_id, rec_type);
status |= mark_corrupt(attr.fp);
}
/*
* Send the end-of-data marker only when there were no errors.

View File

@ -1,4 +1,4 @@
/* $NetBSD: local.c,v 1.1.1.6 2004/05/31 00:24:37 heas Exp $ */
/* $NetBSD: local.c,v 1.1.1.7 2005/08/18 21:07:29 rpaulo Exp $ */
/*++
/* NAME
@ -8,14 +8,14 @@
/* SYNOPSIS
/* \fBlocal\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBlocal\fR daemon processes delivery requests from the
/* The \fBlocal\fR(8) daemon processes delivery requests from the
/* Postfix queue manager to deliver mail to local recipients.
/* Each delivery request specifies a queue file, a sender address,
/* a domain or host to deliver to, and one or more recipients.
/* This program expects to be run from the \fBmaster\fR(8) process
/* manager.
/*
/* The \fBlocal\fR daemon updates queue files and marks recipients
/* The \fBlocal\fR(8) daemon updates queue files and marks recipients
/* as finished, or it informs the queue manager that delivery should
/* be tried again at a later time. Delivery status reports are sent
/* to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as
@ -33,12 +33,19 @@
/* The system administrator can specify a comma/space separated list
/* of ~\fR/.\fBforward\fR like files through the \fBforward_path\fR
/* configuration parameter. Upon delivery, the local delivery agent
/* tries each pathname in the list until a file is found.
/* tries each pathname in the list until a file is found.
/*
/* Delivery via ~/.\fB.forward\fR files is done with the privileges
/* of the recipient.
/* Thus, ~/.\fBforward\fR like files must be readable by the
/* recipient, and their parent directory needs to have "execute"
/* permission for the recipient.
/*
/* The \fBforward_path\fR parameter is subject to interpolation of
/* \fB$user\fR (recipient username), \fB$home\fR (recipient home
/* directory), \fB$shell\fR (recipient shell), \fB$recipient\fR
/* (complete recipient address), \fB$extension\fR (recipient address
/* extension), \fB$domain\fR (recipient domain), \fBlocal\fR
/* extension), \fB$domain\fR (recipient domain), \fB$local\fR
/* (entire recipient address localpart) and
/* \fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and
/* \fI${name:value}\fR expand conditionally to \fIvalue\fR when
@ -97,9 +104,9 @@
/*
/* Mailbox delivery can be delegated to an external command specified
/* with the \fBmailbox_command\fR configuration parameter. The command
/* executes with the privileges of the recipient user (exception: in
/* case of delivery as root, the command executes with the privileges
/* of \fBdefault_privs\fR).
/* executes with the privileges of the recipient user (exceptions:
/* secondary groups are not enabled; in case of delivery as root,
/* the command executes with the privileges of \fBdefault_privs\fR).
/*
/* Mailbox delivery can be delegated to alternative message transports
/* specified in the \fBmaster.cf\fR file.
@ -110,7 +117,7 @@
/* for recipients that are not found in the UNIX passwd database.
/*
/* In the case of UNIX-style mailbox delivery,
/* the \fBlocal\fR daemon prepends a "\fBFrom \fIsender time_stamp\fR"
/* the \fBlocal\fR(8) daemon prepends a "\fBFrom \fIsender time_stamp\fR"
/* envelope header to each message, prepends an
/* \fBX-Original-To:\fR header with the recipient address as given to
/* Postfix, prepends an
@ -137,6 +144,25 @@
/* delivery to external commands. The default setting (\fBalias,
/* forward\fR) forbids command destinations in \fB:include:\fR files.
/*
/* Optionally, the process working directory is changed to the path
/* specified with \fBcommand_execution_directory\fR (Postfix 2.2 and
/* later). Failure to change directory causes mail to be deferred.
/*
/* The \fBcommand_execution_directory\fR parameter value is subject
/* to interpolation of \fB$user\fR (recipient username),
/* \fB$home\fR (recipient home directory), \fB$shell\fR
/* (recipient shell), \fB$recipient\fR (complete recipient
/* address), \fB$extension\fR (recipient address extension),
/* \fB$domain\fR (recipient domain), \fB$local\fR (entire
/* recipient address localpart) and \fB$recipient_delimiter.\fR
/* The forms \fI${name?value}\fR and \fI${name:value}\fR expand
/* conditionally to \fIvalue\fR when \fI$name\fR is (is not)
/* defined. Characters that may have special meaning to the
/* shell or file system are replaced by underscores. The list
/* of acceptable characters is specified with the
/* \fBexecution_directory_expansion_filter\fR configuration
/* parameter.
/*
/* The command is executed directly where possible. Assistance by the
/* shell (\fB/bin/sh\fR on UNIX systems) is used only when the command
/* contains shell magic characters, or when the command invokes a shell
@ -173,6 +199,26 @@
/* .IP \fBSENDER\fR
/* The entire sender address.
/* .PP
/* Additional remote client information is made available via
/* the following environment variables:
/* .IP \fBCLIENT_ADDRESS\fR
/* Remote client network address. Available as of Postfix 2.2.
/* .IP \fBCLIENT_HELO\fR
/* Remote client EHLO command parameter. Available as of Postfix 2.2.
/* .IP \fBCLIENT_HOSTNAME\fR
/* Remote client hostname. Available as of Postfix 2.2.
/* .IP \fBCLIENT_PROTOCOL\fR
/* Remote client protocol. Available as of Postfix 2.2.
/* .IP \fBSASL_METHOD\fR
/* SASL authentication method specified in the
/* remote client AUTH command. Available as of Postfix 2.2.
/* .IP \fBSASL_SENDER\fR
/* SASL sender address specified in the remote client MAIL
/* FROM command. Available as of Postfix 2.2.
/* .IP \fBSASL_USERNAME\fR
/* SASL username specified in the remote client AUTH command.
/* Available as of Postfix 2.2.
/* .PP
/* The \fBPATH\fR environment variable is always reset to a
/* system-dependent default path, and environment variables
/* whose names are blessed by the \fBexport_environment\fR
@ -180,7 +226,7 @@
/*
/* The current working directory is the mail queue directory.
/*
/* The \fBlocal\fR daemon prepends a "\fBFrom \fIsender time_stamp\fR"
/* The \fBlocal\fR(8) daemon prepends a "\fBFrom \fIsender time_stamp\fR"
/* envelope header to each message, prepends an
/* \fBX-Original-To:\fR header with the recipient address as given to
/* Postfix, prepends an
@ -200,7 +246,7 @@
/* forward\fR) forbids file destinations in \fB:include:\fR files.
/*
/* In the case of UNIX-style mailbox delivery,
/* the \fBlocal\fR daemon prepends a "\fBFrom \fIsender time_stamp\fR"
/* the \fBlocal\fR(8) daemon prepends a "\fBFrom \fIsender time_stamp\fR"
/* envelope header to each message, prepends an
/* \fBX-Original-To:\fR header with the recipient address as given to
/* Postfix, prepends an
@ -236,7 +282,7 @@
/* to the mailbox owned by the user \fIname\fR, or it is sent back as
/* undeliverable.
/*
/* In all cases the \fBlocal\fR daemon prepends an optional
/* In all cases the \fBlocal\fR(8) daemon prepends an optional
/* `\fBDelivered-To:\fR header line with the final recipient
/* address.
/* DELIVERY RIGHTS
@ -244,7 +290,7 @@
/* .fi
/* Deliveries to external files and external commands are made with
/* the rights of the receiving user on whose behalf the delivery is made.
/* In the absence of a user context, the \fBlocal\fR daemon uses the
/* In the absence of a user context, the \fBlocal\fR(8) daemon uses the
/* owner rights of the \fB:include:\fR file or alias database.
/* When those files are owned by the superuser, delivery is made with
/* the rights specified with the \fBdefault_privs\fR configuration
@ -258,6 +304,23 @@
/*
/* Depending on the setting of the \fBnotify_classes\fR parameter,
/* the postmaster is notified of bounces and of other trouble.
/* SECURITY
/* .ad
/* .fi
/* The \fBlocal\fR(8) delivery agent needs a dual personality
/* 1) to access the private Postfix queue and IPC mechanisms,
/* 2) to impersonate the recipient and deliver to recipient-specified
/* files or commands. It is therefore security sensitive.
/*
/* The \fBlocal\fR(8) delivery agent disallows regular expression
/* substitution of $1 etc. in \fBalias_maps\fR, because that
/* would open a security hole.
/*
/* The \fBlocal\fR(8) delivery agent will silently ignore
/* requests to use the \fBproxymap\fR(8) server within
/* \fBalias_maps\fR. Instead it will open the table directly.
/* Before Postfix version 2.2, the \fBlocal\fR(8) delivery
/* agent will terminate with a fatal error.
/* BUGS
/* For security reasons, the message delivery status of external commands
/* or of external files is never checkpointed to file. As a result,
@ -270,12 +333,12 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically, as local(8)
/* Changes to \fBmain.cf\fR are picked up automatically, as \fBlocal\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* COMPATIBILITY CONTROLS
/* .ad
/* .fi
@ -287,56 +350,61 @@
/* of the "owner-aliasname" alias.
/* .IP "\fBowner_request_special (yes)\fR"
/* Give special treatment to owner-listname and listname-request
/* address localparts: don't don't split such addresses when the
/* address localparts: don't split such addresses when the
/* recipient_delimiter is set to "-".
/* .IP "\fBsun_mailtool_compatibility (no)\fR"
/* Obsolete SUN mailtool compatibility feature.
/* DELIVERY METHOD CONTROLS
/* .ad
/* .fi
/* The precedence of local(8) delivery methods from high to low is:
/* The precedence of \fBlocal\fR(8) delivery methods from high to low is:
/* aliases, .forward files, mailbox_transport, mailbox_command_maps,
/* mailbox_command, home_mailbox, mail_spool_directory, fallback_transport
/* and luser_relay.
/* .IP "\fBalias_maps (see 'postconf -d' output)\fR"
/* The alias databases that are used for local(8) delivery.
/* The alias databases that are used for \fBlocal\fR(8) delivery.
/* .IP "\fBforward_path (see 'postconf -d' output)\fR"
/* The local(8) delivery agent search list for finding a .forward
/* The \fBlocal\fR(8) delivery agent search list for finding a .forward
/* file with user-specified delivery methods.
/* .IP "\fBmailbox_transport (empty)\fR"
/* Optional message delivery transport that the local(8) delivery
/* Optional message delivery transport that the \fBlocal\fR(8) delivery
/* agent should use for mailbox delivery to all local recipients,
/* whether or not they are found in the UNIX passwd database.
/* .IP "\fBmailbox_command_maps (empty)\fR"
/* Optional lookup tables with per-recipient external commands to use
/* for local(8) mailbox delivery.
/* for \fBlocal\fR(8) mailbox delivery.
/* .IP "\fBmailbox_command (empty)\fR"
/* Optional external command that the local(8) delivery agent should
/* Optional external command that the \fBlocal\fR(8) delivery agent should
/* use for mailbox delivery.
/* .IP "\fBhome_mailbox (empty)\fR"
/* Optional pathname of a mailbox file relative to a local(8) user's
/* Optional pathname of a mailbox file relative to a \fBlocal\fR(8) user's
/* home directory.
/* .IP "\fBmail_spool_directory (see 'postconf -d' output)\fR"
/* The directory where local(8) UNIX-style mailboxes are kept.
/* The directory where \fBlocal\fR(8) UNIX-style mailboxes are kept.
/* .IP "\fBfallback_transport (empty)\fR"
/* Optional message delivery transport that the local(8) delivery
/* agent should use for names that are not found in the aliases(5)
/* Optional message delivery transport that the \fBlocal\fR(8) delivery
/* agent should use for names that are not found in the \fBaliases\fR(5)
/* database or in the UNIX passwd database.
/* .IP "\fBluser_relay (empty)\fR"
/* Optional catch-all destination for unknown local(8) recipients.
/* Optional catch-all destination for unknown \fBlocal\fR(8) recipients.
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBcommand_execution_directory (empty)\fR"
/* The \fBlocal\fR(8) delivery agent working directory for delivery to
/* external command.
/* MAILBOX LOCKING CONTROLS
/* .ad
/* .fi
/* .IP "\fBdeliver_lock_attempts (20)\fR"
/* The maximal number of attempts to acquire an exclusive lock on a
/* mailbox file or bounce(8) logfile.
/* mailbox file or \fBbounce\fR(8) logfile.
/* .IP "\fBdeliver_lock_delay (1s)\fR"
/* The time between attempts to acquire an exclusive lock on a mailbox
/* file or bounce(8) logfile.
/* file or \fBbounce\fR(8) logfile.
/* .IP "\fBstale_lock_time (500s)\fR"
/* The time after which a stale exclusive mailbox lockfile is removed.
/* .IP "\fBmailbox_delivery_lock (see 'postconf -d' output)\fR"
/* How to lock a UNIX-style local(8) mailbox before attempting delivery.
/* How to lock a UNIX-style \fBlocal\fR(8) mailbox before attempting delivery.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@ -344,8 +412,8 @@
/* Time limit for delivery to external commands.
/* .IP "\fBduplicate_filter_limit (1000)\fR"
/* The maximal number of addresses remembered by the address
/* duplicate filter for aliases(5) or virtual(5) alias expansion, or
/* for showq(8) queue displays.
/* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
/* for \fBshowq\fR(8) queue displays.
/* .IP "\fBlocal_destination_concurrency_limit (2)\fR"
/* The maximal number of parallel deliveries via the local mail
/* delivery transport to the same recipient (when
@ -356,24 +424,29 @@
/* The maximal number of recipients per message delivery via the
/* local mail delivery transport.
/* .IP "\fBmailbox_size_limit (51200000)\fR"
/* The maximal size of any local(8) individual mailbox or maildir
/* The maximal size of any \fBlocal\fR(8) individual mailbox or maildir
/* file, or zero (no limit).
/* SECURITY CONTROLS
/* .ad
/* .fi
/* .IP "\fBallow_mail_to_commands (alias, forward)\fR"
/* Restrict local(8) mail delivery to external commands.
/* Restrict \fBlocal\fR(8) mail delivery to external commands.
/* .IP "\fBallow_mail_to_files (alias, forward)\fR"
/* Restrict local(8) mail delivery to external files.
/* Restrict \fBlocal\fR(8) mail delivery to external files.
/* .IP "\fBcommand_expansion_filter (see 'postconf -d' output)\fR"
/* Restrict the characters that the local(8) delivery agent allows in
/* Restrict the characters that the \fBlocal\fR(8) delivery agent allows in
/* $name expansions of $mailbox_command.
/* .IP "\fBdefault_privs (nobody)\fR"
/* The default rights used by the local(8) delivery agent for delivery
/* The default rights used by the \fBlocal\fR(8) delivery agent for delivery
/* to external file or command.
/* .IP "\fBforward_expansion_filter (see 'postconf -d' output)\fR"
/* Restrict the characters that the local(8) delivery agent allows in
/* Restrict the characters that the \fBlocal\fR(8) delivery agent allows in
/* $name expansions of $forward_path.
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBexecution_directory_expansion_filter (see 'postconf -d' output)\fR"
/* Restrict the characters that the \fBlocal\fR(8) delivery agent allows
/* in $name expansions of $command_execution_directory.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
@ -390,7 +463,7 @@
/* The time limit for sending or receiving information over an internal
/* communication channel.
/* .IP "\fBlocal_command_shell (empty)\fR"
/* Optional shell program for local(8) delivery to non-Postfix command.
/* Optional shell program for \fBlocal\fR(8) delivery to non-Postfix command.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process
/* waits for the next service request before exiting.
@ -398,7 +471,7 @@
/* The maximal number of connection requests before a Postfix daemon
/* process terminates.
/* .IP "\fBprepend_delivered_header (command, file, forward)\fR"
/* The message delivery contexts where the Postfix local(8) delivery
/* The message delivery contexts where the Postfix \fBlocal\fR(8) delivery
/* agent prepends a Delivered-To: message header.
/* .IP "\fBprocess_id (read-only)\fR"
/* The process ID of a Postfix command or daemon process.
@ -412,7 +485,7 @@
/* .IP "\fBrecipient_delimiter (empty)\fR"
/* The separator between user names and address extensions (user+foo).
/* .IP "\fBrequire_home_directory (no)\fR"
/* Whether or not a local(8) recipient's home directory must exist
/* Whether or not a \fBlocal\fR(8) recipient's home directory must exist
/* before mail delivery is attempted.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
@ -422,7 +495,7 @@
/* FILES
/* The following are examples; details differ between systems.
/* $HOME/.forward, per-user aliasing
/* /etc/aliases, sytem-wide alias database
/* /etc/aliases, system-wide alias database
/* /var/spool/mail, system mailboxes
/* SEE ALSO
/* qmgr(8), queue manager
@ -431,6 +504,7 @@
/* postalias(1), create/update alias database
/* aliases(5), format of alias database
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* syslogd(8), system logging
/* LICENSE
/* .ad
@ -514,6 +588,8 @@ int var_biff;
char *var_mail_spool_dir;
char *var_mailbox_transport;
char *var_fallback_transport;
char *var_exec_directory;
char *var_exec_exp_filter;
char *var_forward_path;
char *var_cmd_exp_filter;
char *var_fwd_exp_filter;
@ -571,6 +647,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service)
state.msg_attr.sender = rqst->sender;
state.msg_attr.relay = service;
state.msg_attr.arrival_time = rqst->arrival_time;
state.msg_attr.request = rqst;
RESET_OWNER_ATTR(state.msg_attr, state.level);
RESET_USER_ATTR(usr_attr, state.level);
state.loop_info = delivered_init(state.msg_attr); /* delivered-to */
@ -715,7 +792,7 @@ static void pre_init(char *unused_name, char **unused_argv)
* file.
*/
if (var_mailbox_limit) {
if (var_mailbox_limit < var_message_limit)
if (var_mailbox_limit < var_message_limit || var_message_limit == 0)
msg_fatal("main.cf configuration error: %s is smaller than %s",
VAR_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT);
set_file_limit(var_mailbox_limit);
@ -750,6 +827,7 @@ int main(int argc, char **argv)
VAR_FALLBACK_TRANSP, DEF_FALLBACK_TRANSP, &var_fallback_transport, 0, 0,
VAR_CMD_EXP_FILTER, DEF_CMD_EXP_FILTER, &var_cmd_exp_filter, 1, 0,
VAR_FWD_EXP_FILTER, DEF_FWD_EXP_FILTER, &var_fwd_exp_filter, 1, 0,
VAR_EXEC_EXP_FILTER, DEF_EXEC_EXP_FILTER, &var_exec_exp_filter, 1, 0,
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
VAR_DELIVER_HDR, DEF_DELIVER_HDR, &var_deliver_hdr, 0, 0,
VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, &var_mailbox_lock, 1, 0,
@ -765,6 +843,7 @@ int main(int argc, char **argv)
/* Suppress $name expansion upon loading. */
static CONFIG_RAW_TABLE raw_table[] = {
VAR_EXEC_DIRECTORY, DEF_EXEC_DIRECTORY, &var_exec_directory, 0, 0,
VAR_FORWARD_PATH, DEF_FORWARD_PATH, &var_forward_path, 0, 0,
VAR_MAILBOX_COMMAND, DEF_MAILBOX_COMMAND, &var_mailbox_command, 0, 0,
VAR_MAILBOX_CMD_MAPS, DEF_MAILBOX_CMD_MAPS, &var_mailbox_cmd_maps, 0, 0,
@ -781,5 +860,6 @@ int main(int argc, char **argv)
MAIL_SERVER_PRE_INIT, pre_init,
MAIL_SERVER_POST_INIT, post_init,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
MAIL_SERVER_PRIVILEGED,
0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: local.h,v 1.1.1.5 2004/05/31 00:24:37 heas Exp $ */
/* $NetBSD: local.h,v 1.1.1.6 2005/08/18 21:07:29 rpaulo Exp $ */
/*++
/* NAME
@ -74,7 +74,7 @@ typedef struct DELIVER_ATTR {
char *sender; /* taken from envelope */
char *orig_rcpt; /* from submission */
char *recipient; /* taken from resolver */
long rcpt_offset; /* taken from resolver */
long rcpt_offset; /* taken from resolver */
char *domain; /* recipient domain */
char *local; /* recipient full localpart */
char *user; /* recipient localpart, base name */
@ -86,6 +86,7 @@ typedef struct DELIVER_ATTR {
long arrival_time; /* arrival time */
int exp_type; /* expansion type. see below */
char *exp_from; /* expanded_from */
DELIVER_REQUEST *request; /* the kitchen sink */
} DELIVER_ATTR;
extern void deliver_attr_init(DELIVER_ATTR *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: local_expand.c,v 1.1.1.2 2004/05/31 00:24:37 heas Exp $ */
/* $NetBSD: local_expand.c,v 1.1.1.3 2005/08/18 21:07:30 rpaulo Exp $ */
/*++
/* NAME
@ -24,6 +24,14 @@
/* See mac_parse(3).
/* .PP
/* Attributes:
/* .IP client_address
/* The client network address.
/* .IP client_helo
/* The client HELO command parameter.
/* .IP client_hostname
/* The client hostname.
/* .IP client_protocol
/* The client protocol.
/* .IP domain
/* The recipient address domain.
/* .IP extension
@ -38,6 +46,12 @@
/* The recipient delimiter.
/* .IP shell
/* The recipient shell program.
/* .IP sasl_method
/* The SASL authentication method.
/* .IP sasl_sender
/* The SASL MAIL FROM address.
/* .IP sasl_username
/* The SASL login name.
/* .IP user
/* The recipient user name.
/* .PP
@ -124,6 +138,22 @@ static const char *local_expand_lookup(const char *name, int mode, char *ptr)
return (local->state->msg_attr.extension);
} else if (STREQ(name, "recipient_delimiter")) {
return (*var_rcpt_delim ? var_rcpt_delim : 0);
#if 0
} else if (STREQ(name, "client_hostname")) {
return (local->state->msg_attr.request->client_name);
} else if (STREQ(name, "client_address")) {
return (local->state->msg_attr.request->client_addr);
} else if (STREQ(name, "client_protocol")) {
return (local->state->msg_attr.request->client_proto);
} else if (STREQ(name, "client_helo")) {
return (local->state->msg_attr.request->client_helo);
} else if (STREQ(name, "sasl_method")) {
return (local->state->msg_attr.request->sasl_method);
} else if (STREQ(name, "sasl_sender")) {
return (local->state->msg_attr.request->sasl_sender);
} else if (STREQ(name, "sasl_username")) {
return (local->state->msg_attr.request->sasl_username);
#endif
} else {
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: maildir.c,v 1.1.1.6 2004/05/31 00:24:37 heas Exp $ */
/* $NetBSD: maildir.c,v 1.1.1.7 2005/08/18 21:07:31 rpaulo Exp $ */
/*++
/* NAME
@ -43,6 +43,7 @@
#include "sys_defs.h"
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
@ -88,7 +89,9 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
int deliver_status;
int copy_flags;
struct stat st;
time_t starttime = time((time_t *) 0);
struct timeval starttime;
GETTIMEOFDAY(&starttime);
/*
* Make verbose logging easier to understand.
@ -168,7 +171,8 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
* filesystem: a maildir has to be within a single UNIX device for link()
* and rename() to work.)
*
* [...]
* Mn, where n is (in decimal) the microsecond counter from the same
* gettimeofday() used for the left part of the unique name.
*
* Pn, where n is (in decimal) the process ID.
*
@ -178,7 +182,7 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
set_eugid(usr_attr.uid, usr_attr.gid);
vstring_sprintf(buf, "%lu.P%d.%s",
(unsigned long) starttime, var_pid, get_hostname());
(unsigned long) starttime.tv_sec, var_pid, get_hostname());
tmpfile = concatenate(tmpdir, STR(buf), (char *) 0);
newfile = 0;
if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0
@ -189,9 +193,12 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
} else if (fstat(vstream_fileno(dst), &st) < 0) {
vstring_sprintf(why, "create %s: %m", tmpfile);
} else {
vstring_sprintf(buf, "%lu.V%lxI%lx.%s",
(unsigned long) starttime, (unsigned long) st.st_dev,
(unsigned long) st.st_ino, get_hostname());
vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s",
(unsigned long) starttime.tv_sec,
(unsigned long) st.st_dev,
(unsigned long) st.st_ino,
(unsigned long) starttime.tv_usec,
get_hostname());
newfile = concatenate(newdir, STR(buf), (char *) 0);
if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr),
dst, copy_flags, "\n", why)) == 0) {

View File

@ -24,8 +24,10 @@ BIN_DIR = ../../libexec
all: $(PROG) $(LIB)
$(OBJS) $(LIB_OBJ): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
@ -72,7 +74,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -106,6 +108,7 @@ master.o: ../../include/debug_process.h
master.o: ../../include/mail_task.h
master.o: ../../include/mail_conf.h
master.o: ../../include/open_lock.h
master.o: ../../include/inet_proto.h
master.o: master.h
master_avail.o: master_avail.c
master_avail.o: ../../include/sys_defs.h
@ -129,13 +132,15 @@ master_ent.o: ../../include/argv.h
master_ent.o: ../../include/stringops.h
master_ent.o: ../../include/readlline.h
master_ent.o: ../../include/inet_addr_list.h
master_ent.o: ../../include/inet_util.h
master_ent.o: ../../include/myaddrinfo.h
master_ent.o: ../../include/host_port.h
master_ent.o: ../../include/inet_addr_host.h
master_ent.o: ../../include/mail_proto.h
master_ent.o: ../../include/iostuff.h
master_ent.o: ../../include/attr.h
master_ent.o: ../../include/mail_params.h
master_ent.o: ../../include/own_inet_addr.h
master_ent.o: ../../include/wildcard_inet_addr.h
master_ent.o: master_proto.h
master_ent.o: master.h
master_flow.o: master_flow.c
@ -154,8 +159,10 @@ master_listen.o: ../../include/stringops.h
master_listen.o: ../../include/vstring.h
master_listen.o: ../../include/vbuf.h
master_listen.o: ../../include/inet_addr_list.h
master_listen.o: ../../include/myaddrinfo.h
master_listen.o: ../../include/set_eugid.h
master_listen.o: ../../include/set_ugid.h
master_listen.o: ../../include/sock_addr.h
master_listen.o: ../../include/mail_params.h
master_listen.o: master.h
master_proto.o: master_proto.c
@ -180,6 +187,8 @@ master_spawn.o: ../../include/msg.h
master_spawn.o: ../../include/binhash.h
master_spawn.o: ../../include/mymalloc.h
master_spawn.o: ../../include/events.h
master_spawn.o: ../../include/vstring.h
master_spawn.o: ../../include/vbuf.h
master_spawn.o: ../../include/argv.h
master_spawn.o: master_proto.h
master_spawn.o: master.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: mail_server.h,v 1.1.1.5 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: mail_server.h,v 1.1.1.6 2005/08/18 21:07:35 rpaulo Exp $ */
/*++
/* NAME
@ -32,6 +32,7 @@
#define MAIL_SERVER_SOLITARY 15
#define MAIL_SERVER_UNLIMITED 16
#define MAIL_SERVER_PRE_DISCONN 17
#define MAIL_SERVER_PRIVILEGED 18
#define MAIL_SERVER_IN_FLOW_DELAY 20
@ -53,6 +54,7 @@ extern NORETURN single_server_main(int, char **, SINGLE_SERVER_FN, ...);
typedef void (*MULTI_SERVER_FN) (VSTREAM *, char *, char **);
extern NORETURN multi_server_main(int, char **, MULTI_SERVER_FN,...);
extern void multi_server_disconnect(VSTREAM *);
extern int multi_server_drain(void);
/*
* trigger_server.c

View File

@ -1,4 +1,4 @@
/* $NetBSD: master.c,v 1.1.1.6 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: master.c,v 1.1.1.7 2005/08/18 21:07:37 rpaulo Exp $ */
/*++
/* NAME
@ -6,11 +6,9 @@
/* SUMMARY
/* Postfix master process
/* SYNOPSIS
/* .fi
/* \fBmaster\fR [\fB-Dtv\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-e \fIexit_time\fR]
/* \fBmaster\fR [\fB-Dtv\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR]
/* DESCRIPTION
/* The \fBmaster\fR daemon is the resident process that runs Postfix
/* The \fBmaster\fR(8) daemon is the resident process that runs Postfix
/* daemons on demand: daemons to send or receive messages via the
/* network, daemons to deliver mail locally, etc. These daemons are
/* created on demand up to a configurable maximum number per service.
@ -18,19 +16,18 @@
/* Postfix daemons terminate voluntarily, either after being idle for
/* a configurable amount of time, or after having serviced a
/* configurable number of requests. Exceptions to this rule are the
/* resident queue manager and the resident address verification server.
/* resident queue manager, address verification server, and the TLS
/* session cache and pseudo-random number server.
/*
/* The behavior of the \fBmaster\fR daemon is controlled by the
/* \fBmaster.cf\fR configuration file. The table specifies zero or
/* more servers in the \fBUNIX\fR or \fBINET\fR domain, or servers
/* that take requests from a FIFO. Precise configuration details are
/* given in the \fBmaster.cf\fR file, and in the manual pages of the
/* respective daemons.
/* The behavior of the \fBmaster\fR(8) daemon is controlled by the
/* \fBmaster.cf\fR configuration file, as described in \fBmaster\fR(5).
/*
/* Options:
/* .IP "\fB-c \fIconfig_dir\fR"
/* Read the \fBmain.cf\fR and \fBmaster.cf\fR configuration files in
/* the named directory instead of the default configuration directory.
/* This also overrides the configuration files for other Postfix
/* daemon processes.
/* .IP "\fB-e \fIexit_time\fR"
/* Terminate the master process after \fIexit_time\fR seconds. Child
/* processes terminate at their convenience.
@ -41,7 +38,7 @@
/* .IP \fB-t\fR
/* Test mode. Return a zero exit status when the \fBmaster.pid\fR lock
/* file does not exist or when that file is not locked. This is evidence
/* that the \fBmaster\fR daemon is not running.
/* that the \fBmaster\fR(8) daemon is not running.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. This option
/* is passed on to child processes. Multiple \fB-v\fR options
@ -49,7 +46,7 @@
/* .PP
/* Signals:
/* .IP \fBSIGHUP\fR
/* Upon receipt of a \fBHUP\fR signal (e.g., after \fBpostfix reload\fR),
/* Upon receipt of a \fBHUP\fR signal (e.g., after "\fBpostfix reload\fR"),
/* the master process re-reads its configuration files. If a service has
/* been removed from the \fBmaster.cf\fR file, its running processes
/* are terminated immediately.
@ -57,11 +54,11 @@
/* as is convenient, so that changes in configuration settings
/* affect only new service requests.
/* .IP \fBSIGTERM\fR
/* Upon receipt of a \fBTERM\fR signal (e.g., after \fBpostfix abort\fR),
/* Upon receipt of a \fBTERM\fR signal (e.g., after "\fBpostfix abort\fR"),
/* the master process passes the signal on to its child processes and
/* terminates.
/* This is useful for an emergency shutdown. Normally one would
/* terminate only the master (\fBpostfix stop\fR) and allow running
/* terminate only the master ("\fBpostfix stop\fR") and allow running
/* processes to finish what they are doing.
/* DIAGNOSTICS
/* Problems are reported to \fBsyslogd\fR(8).
@ -77,16 +74,13 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Unlike most Postfix daemon processes, the master(8) server does
/* Unlike most Postfix daemon processes, the \fBmaster\fR(8) server does
/* not automatically pick up changes to \fBmain.cf\fR. Changes
/* to \fBmaster.cf\fR are never picked up automatically.
/* Use the \fBpostfix reload\fR command after a configuration change.
/* Use the "\fBpostfix reload\fR" command after a configuration change.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
/* .IP "\fBdaemon_timeout (18000s)\fR"
/* How much time a Postfix daemon process may take to handle a
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBdefault_process_limit (100)\fR"
/* The default maximal number of Postfix child processes that provide
/* a given service.
@ -97,7 +91,7 @@
/* The maximal number of connection requests before a Postfix daemon
/* process terminates.
/* .IP "\fBservice_throttle_time (60s)\fR"
/* How long the Postfix master(8) waits before forking a server that
/* How long the Postfix \fBmaster\fR(8) waits before forking a server that
/* appears to be malfunctioning.
/* MISCELLANEOUS CONTROLS
/* .ad
@ -111,8 +105,11 @@
/* The external command to execute when a Postfix daemon program is
/* invoked with the -D option.
/* .IP "\fBinet_interfaces (all)\fR"
/* The network interface addresses that this mail system receives mail
/* on.
/* The network interface addresses that this mail system receives
/* mail on.
/* .IP "\fBinet_protocols (ipv4)\fR"
/* The Internet protocols Postfix will attempt to use when making
/* or accepting connections.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
/* The list of environment parameters that a Postfix process will
/* import from a non-Postfix parent process.
@ -137,7 +134,8 @@
/* SEE ALSO
/* qmgr(8), queue manager
/* verify(8), address verification
/* postconf(5), configuration parameters
/* master(5), master.cf configuration file syntax
/* postconf(5), main.cf configuration parameter syntax
/* syslogd(8), system logging
/* LICENSE
/* .ad
@ -186,6 +184,7 @@
#include <mail_task.h>
#include <mail_conf.h>
#include <open_lock.h>
#include <inet_proto.h>
/* Application-specific. */
@ -199,6 +198,13 @@ static void master_exit_event(int unused_event, char *unused_context)
exit(0);
}
/* usage - show hint and terminate */
static NORETURN usage(const char *me)
{
msg_fatal("usage: %s [-c config_dir] [-e exit_time] [-D (debug)] [-t (test)] [-v]", me);
}
/* main - main program */
int main(int argc, char **argv)
@ -211,7 +217,6 @@ int main(int argc, char **argv)
int fd;
int n;
int test_lock = 0;
int fd_limit = open_limit(0);
VSTRING *why;
WATCHDOG *watchdog;
ARGV *import_env;
@ -254,10 +259,7 @@ int main(int argc, char **argv)
* of this we have to close descriptors > 2, and pray that doing so does
* not break things.
*/
if (fd_limit > 500)
fd_limit = 500;
for (fd = 3; fd < fd_limit; fd++)
(void) close(fd);
closefrom(3);
/*
* Initialize logging and exit handler.
@ -289,7 +291,7 @@ int main(int argc, char **argv)
* all MTA processes cleanly. Give up if we can't separate from our
* parent process. We're not supposed to blow away the parent.
*/
if (setsid() == -1)
if (debug_me == 0 && setsid() == -1)
msg_fatal("unable to set session and process group ID: %m");
/*
@ -328,11 +330,17 @@ int main(int argc, char **argv)
msg_verbose++;
break;
default:
msg_fatal("usage: %s [-c config_dir] [-e exit_time] [-D (debug)] [-t (test)] [-v]", argv[0]);
usage(argv[0]);
/* NOTREACHED */
}
}
/*
* This program takes no other arguments.
*/
if (argc > optind)
usage(argv[0]);
/*
* Final initializations. Unfortunately, we must read the global Postfix
* configuration file after doing command-line processing, so that we get
@ -341,6 +349,13 @@ int main(int argc, char **argv)
*/
master_vars_init();
/*
* In case of multi-protocol support. This needs to be done because
* master does not invoke mail_params_init() (it was written before that
* code existed).
*/
(void) inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
/*
* Environment import filter, to enforce consistent behavior whether
* Postfix is started by hand, or at system boot time.
@ -394,7 +409,8 @@ int main(int argc, char **argv)
master_config();
master_sigsetup();
master_flow_init();
msg_info("daemon started -- version %s", var_mail_version);
msg_info("daemon started -- version %s, configuration %s",
var_mail_version, var_config_dir);
/*
* Process events. The event handler will execute the read/write/timer
@ -413,7 +429,7 @@ int main(int argc, char **argv)
watchdog_start(watchdog); /* same as trigger servers */
event_loop(-1);
if (master_gotsighup) {
msg_info("reload configuration");
msg_info("reload configuration %s", var_config_dir);
master_gotsighup = 0; /* this first */
master_vars_init(); /* then this */
master_refresh(); /* then this */

View File

@ -1,4 +1,4 @@
/* $NetBSD: master_proto.c,v 1.1.1.2 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: master_proto.c,v 1.1.1.3 2005/08/18 21:07:41 rpaulo Exp $ */
/*++
/* NAME
@ -8,8 +8,9 @@
/* SYNOPSIS
/* #include <master_proto.h>
/*
/* int master_notify(pid, status)
/* int master_notify(pid, generation, status)
/* int pid;
/* unsigned generation;
/* int status;
/* DESCRIPTION
/* The master process provides a standard environment for its
@ -63,7 +64,7 @@
#include "master_proto.h"
int master_notify(int pid, int status)
int master_notify(int pid, unsigned generation, int status)
{
char *myname = "master_notify";
MASTER_STATUS stat;
@ -75,6 +76,7 @@ int master_notify(int pid, int status)
* bad status code will only have amusement value.
*/
stat.pid = pid;
stat.gen = generation;
stat.avail = status;
if (write(MASTER_STATUS_FD, (char *) &stat, sizeof(stat)) != sizeof(stat)) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: master_proto.h,v 1.1.1.3 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: master_proto.h,v 1.1.1.4 2005/08/18 21:07:41 rpaulo Exp $ */
/*++
/* NAME
@ -17,6 +17,7 @@
#define MASTER_XPORT_NAME_UNIX "unix" /* local IPC */
#define MASTER_XPORT_NAME_FIFO "fifo" /* local IPC */
#define MASTER_XPORT_NAME_INET "inet" /* non-local IPC */
/*#define MASTER_XPORT_NAME_PASS "pass" /* local IPC */
/*
* Format of a status message sent by a child process to the process
@ -25,13 +26,16 @@
*/
typedef struct MASTER_STATUS {
int pid; /* process ID */
unsigned gen; /* child generation number */
int avail; /* availability */
} MASTER_STATUS;
#define MASTER_GEN_NAME "GENERATION" /* passed via environment */
#define MASTER_STAT_TAKEN 0 /* this one is occupied */
#define MASTER_STAT_AVAIL 1 /* this process is idle */
extern int master_notify(int, int); /* encapsulate status msg */
extern int master_notify(int, unsigned, int); /* encapsulate status msg */
/*
* File descriptors inherited from the master process. The flow control pipe

View File

@ -1,4 +1,4 @@
/* $NetBSD: master_spawn.c,v 1.1.1.3 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: master_spawn.c,v 1.1.1.4 2005/08/18 21:07:42 rpaulo Exp $ */
/*++
/* NAME
@ -61,6 +61,7 @@
#include <syslog.h> /* closelog() */
#include <signal.h>
#include <stdarg.h>
#include <syslog.h>
/* Utility libraries. */
@ -68,8 +69,8 @@
#include <binhash.h>
#include <mymalloc.h>
#include <events.h>
#include <vstring.h>
#include <argv.h>
#include <syslog.h>
/* Application-specific. */
@ -138,9 +139,13 @@ void master_spawn(MASTER_SERV *serv)
MASTER_PROC *proc;
MASTER_PID pid;
int n;
static unsigned master_generation = 0;
static VSTRING *env_gen = 0;
if (master_child_table == 0)
master_child_table = binhash_create(0);
if (env_gen == 0)
env_gen = vstring_alloc(100);
/*
* Sanity checks. The master_avail module is supposed to know what it is
@ -157,6 +162,7 @@ void master_spawn(MASTER_SERV *serv)
* Create a child process and connect parent and child via the status
* pipe.
*/
master_generation += 1;
switch (pid = fork()) {
/*
@ -209,6 +215,10 @@ void master_spawn(MASTER_SERV *serv)
myname, serv->listen_fd[n]);
(void) close(serv->listen_fd[n]);
}
vstring_sprintf(env_gen, "%s=%o", MASTER_GEN_NAME, master_generation);
if (putenv(vstring_str(env_gen)) < 0)
msg_fatal("%s: putenv: %m", myname);
execvp(serv->path, serv->args->argv);
msg_fatal("%s: exec %s: %m", myname, serv->path);
exit(1);
@ -226,6 +236,7 @@ void master_spawn(MASTER_SERV *serv)
proc = (MASTER_PROC *) mymalloc(sizeof(MASTER_PROC));
proc->serv = serv;
proc->pid = pid;
proc->gen = master_generation;
proc->use_count = 0;
proc->avail = 0;
binhash_enter(master_child_table, (char *) &pid,

View File

@ -1,4 +1,4 @@
/* $NetBSD: master_status.c,v 1.1.1.3 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: master_status.c,v 1.1.1.4 2005/08/18 21:07:42 rpaulo Exp $ */
/*++
/* NAME
@ -91,13 +91,15 @@ static void master_status_event(int event, char *context)
/* NOTREACHED */
default:
msg_warn("%s: partial status (%d bytes)", myname, n);
msg_warn("service %s: child (pid %d) sent partial status update (%d bytes)",
serv->name, stat.pid, n);
return;
case sizeof(stat):
pid = stat.pid;
if (msg_verbose)
msg_info("%s: pid %d avail %d", myname, stat.pid, stat.avail);
msg_info("%s: pid %d gen %u avail %d",
myname, stat.pid, stat.gen, stat.avail);
}
/*
@ -113,6 +115,11 @@ static void master_status_event(int event, char *context)
msg_info("%s: process id not found: %d", myname, stat.pid);
return;
}
if (proc->gen != stat.gen) {
msg_info("ignoring status update from child pid %d generation %u",
pid, stat.gen);
return;
}
if (proc->serv != serv)
msg_panic("%s: pointer corruption: %p != %p",
myname, (void *) proc->serv, (void *) serv);

View File

@ -1,4 +1,4 @@
/* $NetBSD: master_vars.c,v 1.1.1.3 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: master_vars.c,v 1.1.1.4 2005/08/18 21:07:42 rpaulo Exp $ */
/*++
/* NAME
@ -27,6 +27,7 @@
/* System library. */
#include <sys_defs.h>
#include <string.h>
#include <unistd.h>
/* Utility library. */
@ -47,6 +48,7 @@
/*
* Tunable parameters.
*/
char *var_inet_protocols;
int var_proc_limit;
int var_throttle_time;
@ -55,6 +57,10 @@ int var_throttle_time;
void master_vars_init(void)
{
char *path;
static CONFIG_STR_TABLE str_table[] = {
VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 1, 0,
0,
};
static CONFIG_INT_TABLE int_table[] = {
VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
0,
@ -63,11 +69,20 @@ void master_vars_init(void)
VAR_THROTTLE_TIME, DEF_THROTTLE_TIME, &var_throttle_time, 1, 0,
0,
};
static char *saved_inet_protocols;
if (var_inet_protocols && !saved_inet_protocols)
saved_inet_protocols = mystrdup(var_inet_protocols);
mail_conf_read();
get_mail_conf_str_table(str_table);
get_mail_conf_int_table(int_table);
get_mail_conf_time_table(time_table);
path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
fset_master_ent(path);
myfree(path);
if (saved_inet_protocols && strcmp(var_inet_protocols, saved_inet_protocols)) {
msg_warn("ignoring %s change", VAR_INET_PROTOCOLS);
msg_warn("to change %s, stop and start Postfix", VAR_INET_PROTOCOLS);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: master_wakeup.c,v 1.1.1.3 2004/05/31 00:24:39 heas Exp $ */
/* $NetBSD: master_wakeup.c,v 1.1.1.4 2005/08/18 21:07:44 rpaulo Exp $ */
/*++
/* NAME
@ -106,6 +106,12 @@ static void master_wakeup_timer_event(int unused_event, char *context)
case MASTER_SERV_TYPE_UNIX:
status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
#ifdef MASTER_SERV_TYPE_PASS
case MASTER_SERV_TYPE_PASS:
/* Can't send data to a service that expects descriptors. */
status = 0;
break;
#endif
/*
* If someone compromises the postfix account then this must not

View File

@ -1,4 +1,4 @@
/* $NetBSD: multi_server.c,v 1.1.1.6 2004/05/31 00:24:39 heas Exp $ */
/* $NetBSD: multi_server.c,v 1.1.1.7 2005/08/18 21:07:45 rpaulo Exp $ */
/*++
/* NAME
@ -17,6 +17,8 @@
/* void multi_server_disconnect(stream, argv)
/* VSTREAM *stream;
/* char **argv;
/*
/* void multi_server_drain()
/* DESCRIPTION
/* This module implements a skeleton for multi-threaded
/* mail subsystems: mail subsystem programs that service multiple
@ -109,10 +111,17 @@
/* This service must be configured with process limit of 1.
/* .IP MAIL_SERVER_UNLIMITED
/* This service must be configured with process limit of 0.
/* .IP MAIL_SERVER_PRIVILEGED
/* This service must be configured as privileged.
/* .PP
/* multi_server_disconnect() should be called by the application
/* when a client disconnects.
/*
/* multi_server_drain() should be called when the application
/* no longer wishes to accept new client connections. Existing
/* clients are handled in a background process. A non-zero
/* result means this call should be tried again later.
/*
/* The var_use_limit variable limits the number of clients that
/* a server can service before it commits suicide.
/* This value is taken from the global \fBmain.cf\fR configuration
@ -146,6 +155,7 @@
#include <signal.h>
#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
@ -153,6 +163,7 @@
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <time.h>
/* Utility library. */
@ -198,6 +209,7 @@
*/
static int client_count;
static int use_count;
static int socket_count = 1;
static void (*multi_server_service) (VSTREAM *, char *, char **);
static char *multi_server_name;
@ -207,6 +219,7 @@ static void (*multi_server_onexit) (char *, char **);
static void (*multi_server_pre_accept) (char *, char **);
static VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay;
static unsigned multi_server_generation;
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
/* multi_server_exit - normal termination */
@ -236,6 +249,28 @@ static void multi_server_timeout(int unused_event, char *unused_context)
multi_server_exit();
}
/* multi_server_drain - stop accepting new clients */
int multi_server_drain(void)
{
int fd;
switch (fork()) {
/* Try again later. */
case -1:
return (-1);
/* Finish existing clients in the background, then terminate. */
case 0:
for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++)
event_disable_readwrite(fd);
var_use_limit = 1;
return (0);
/* Let the master start a new process. */
default:
exit(0);
}
}
/* multi_server_disconnect - terminate client session */
void multi_server_disconnect(VSTREAM *stream)
@ -265,10 +300,10 @@ static void multi_server_execute(int unused_event, char *context)
* Do not bother the application when the client disconnected.
*/
if (peekfd(vstream_fileno(stream)) > 0) {
if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0)
if (master_notify(var_pid, multi_server_generation, MASTER_STAT_TAKEN) < 0)
multi_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
multi_server_service(stream, multi_server_name, multi_server_argv);
if (master_notify(var_pid, MASTER_STAT_AVAIL) < 0)
if (master_notify(var_pid, multi_server_generation, MASTER_STAT_AVAIL) < 0)
multi_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
} else {
multi_server_disconnect(stream);
@ -345,6 +380,45 @@ static void multi_server_accept_local(int unused_event, char *context)
multi_server_wakeup(fd);
}
#ifdef MASTER_XPORT_NAME_PASS
/* multi_server_accept_pass - accept descriptor */
static void multi_server_accept_pass(int unused_event, char *context)
{
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
int time_left = -1;
int fd;
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
* kept small, so this is not a "thundering herd" problem). If the
* accept() succeeds, be sure to disable non-blocking I/O, in order to
* minimize confusion.
*/
if (client_count == 0 && var_idle_limit > 0)
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv);
fd = PASS_ACCEPT(listen_fd);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(multi_server_timeout, (char *) 0, time_left);
return;
}
multi_server_wakeup(fd);
}
#endif
/* multi_server_accept_inet - accept client connection request */
static void multi_server_accept_inet(int unused_event, char *context)
@ -392,7 +466,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
char *service_name = basename(argv[0]);
int delay;
int c;
int socket_count = 1;
int fd;
va_list ap;
MAIL_SERVER_INIT_FN pre_init = 0;
@ -408,6 +481,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
int zerolimit = 0;
WATCHDOG *watchdog;
char *oval;
char *generation;
/*
* Process environment options as early as we can.
@ -566,6 +640,11 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
msg_fatal("service %s requires a process limit of 0",
service_name);
break;
case MAIL_SERVER_PRIVILEGED:
if (user_name)
msg_fatal("service %s requires privileged operation",
service_name);
break;
default:
msg_panic("%s: unknown argument type: %d", myname, key);
}
@ -595,10 +674,26 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
multi_server_accept = multi_server_accept_inet;
else if (strcasecmp(transport, MASTER_XPORT_NAME_UNIX) == 0)
multi_server_accept = multi_server_accept_local;
#ifdef MASTER_XPORT_NAME_PASS
else if (strcasecmp(transport, MASTER_XPORT_NAME_PASS) == 0)
multi_server_accept = multi_server_accept_pass;
#endif
else
msg_fatal("unsupported transport type: %s", transport);
}
/*
* Retrieve process generation from environment.
*/
if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
if (!alldig(generation))
msg_fatal("bad generation: %s", generation);
OCTAL_TO_UNSIGNED(multi_server_generation, generation);
if (msg_verbose)
msg_info("process generation: %s (%o)",
generation, multi_server_generation);
}
/*
* Optionally start the debugger on ourself.
*/
@ -649,6 +744,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
* Optionally, restrict the damage that this process can do.
*/
resolve_local_init();
#ifdef SNAPSHOT
tzset();
#endif
chroot_uid(root_dir, user_name);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: single_server.c,v 1.1.1.5 2004/05/31 00:24:39 heas Exp $ */
/* $NetBSD: single_server.c,v 1.1.1.6 2005/08/18 21:07:47 rpaulo Exp $ */
/*++
/* NAME
@ -101,6 +101,8 @@
/* This service must be configured with process limit of 1.
/* .IP MAIL_SERVER_UNLIMITED
/* This service must be configured with process limit of 0.
/* .IP MAIL_SERVER_PRIVILEGED
/* This service must be configured as privileged.
/* .PP
/* The var_use_limit variable limits the number of clients that
/* a server can service before it commits suicide.
@ -136,6 +138,7 @@
#include <signal.h>
#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
@ -143,6 +146,7 @@
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <time.h>
/* Utility library. */
@ -195,6 +199,7 @@ static void (*single_server_onexit) (char *, char **);
static void (*single_server_pre_accept) (char *, char **);
static VSTREAM *single_server_lock;
static int single_server_in_flow_delay;
static unsigned single_server_generation;
/* single_server_exit - normal termination */
@ -245,13 +250,13 @@ static void single_server_wakeup(int fd)
vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
myfree(tmp);
timed_ipc_setup(stream);
if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0)
if (master_notify(var_pid, single_server_generation, MASTER_STAT_TAKEN) < 0)
single_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
if (single_server_in_flow_delay && mail_flow_get(1) < 0)
doze(var_in_flow_delay * 1000000);
single_server_service(stream, single_server_name, single_server_argv);
(void) vstream_fclose(stream);
if (master_notify(var_pid, MASTER_STAT_AVAIL) < 0)
if (master_notify(var_pid, single_server_generation, MASTER_STAT_AVAIL) < 0)
single_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
if (msg_verbose)
msg_info("connection closed");
@ -294,6 +299,44 @@ static void single_server_accept_local(int unused_event, char *context)
single_server_wakeup(fd);
}
#ifdef MASTER_XPORT_NAME_PASS
/* single_server_accept_pass - accept descriptor */
static void single_server_accept_pass(int unused_event, char *context)
{
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
int time_left = -1;
int fd;
/*
* Be prepared for accept() to fail because some other process already
* got the connection. We use select() + accept(), instead of simply
* blocking in accept(), because we must be able to detect that the
* master process has gone away unexpectedly.
*/
if (var_idle_limit > 0)
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
if (single_server_pre_accept)
single_server_pre_accept(single_server_name, single_server_argv);
fd = PASS_ACCEPT(listen_fd);
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK,
MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(single_server_timeout, (char *) 0, time_left);
return;
}
single_server_wakeup(fd);
}
#endif
/* single_server_accept_inet - accept client connection request */
static void single_server_accept_inet(int unused_event, char *context)
@ -354,6 +397,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
int zerolimit = 0;
WATCHDOG *watchdog;
char *oval;
char *generation;
/*
* Process environment options as early as we can.
@ -509,6 +553,11 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
msg_fatal("service %s requires a process limit of 0",
service_name);
break;
case MAIL_SERVER_PRIVILEGED:
if (user_name)
msg_fatal("service %s requires privileged operation",
service_name);
break;
default:
msg_panic("%s: unknown argument type: %d", myname, key);
}
@ -538,10 +587,26 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
single_server_accept = single_server_accept_inet;
else if (strcasecmp(transport, MASTER_XPORT_NAME_UNIX) == 0)
single_server_accept = single_server_accept_local;
#ifdef MASTER_XPORT_NAME_PASS
else if (strcasecmp(transport, MASTER_XPORT_NAME_PASS) == 0)
single_server_accept = single_server_accept_pass;
#endif
else
msg_fatal("unsupported transport type: %s", transport);
}
/*
* Retrieve process generation from environment.
*/
if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
if (!alldig(generation))
msg_fatal("bad generation: %s", generation);
OCTAL_TO_UNSIGNED(single_server_generation, generation);
if (msg_verbose)
msg_info("process generation: %s (%o)",
generation, single_server_generation);
}
/*
* Optionally start the debugger on ourself.
*/
@ -585,6 +650,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
* Optionally, restrict the damage that this process can do.
*/
resolve_local_init();
#ifdef SNAPSHOT
tzset();
#endif
chroot_uid(root_dir, user_name);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: trigger_server.c,v 1.1.1.5 2004/05/31 00:24:38 heas Exp $ */
/* $NetBSD: trigger_server.c,v 1.1.1.6 2005/08/18 21:07:47 rpaulo Exp $ */
/*++
/* NAME
@ -108,6 +108,8 @@
/* This service must be configured with process limit of 1.
/* .IP MAIL_SERVER_UNLIMITED
/* This service must be configured with process limit of 0.
/* .IP MAIL_SERVER_PRIVILEGED
/* This service must be configured as privileged.
/* .PP
/* The var_use_limit variable limits the number of clients that
/* a server can service before it commits suicide.
@ -144,6 +146,7 @@
#include <signal.h>
#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
@ -151,6 +154,7 @@
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <time.h>
/* Utility library. */
@ -202,6 +206,7 @@ static void (*trigger_server_onexit) (char *, char **);
static void (*trigger_server_pre_accept) (char *, char **);
static VSTREAM *trigger_server_lock;
static int trigger_server_in_flow_delay;
static unsigned trigger_server_generation;
/* trigger_server_exit - normal termination */
@ -240,14 +245,14 @@ static void trigger_server_wakeup(int fd)
/*
* Commit suicide when the master process disconnected from us.
*/
if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0)
if (master_notify(var_pid, trigger_server_generation, MASTER_STAT_TAKEN) < 0)
trigger_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
if (trigger_server_in_flow_delay && mail_flow_get(1) < 0)
doze(var_in_flow_delay * 1000000);
if ((len = read(fd, buf, sizeof(buf))) >= 0)
trigger_server_service(buf, len, trigger_server_name,
trigger_server_argv);
if (master_notify(var_pid, MASTER_STAT_AVAIL) < 0)
if (master_notify(var_pid, trigger_server_generation, MASTER_STAT_AVAIL) < 0)
trigger_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
if (var_idle_limit > 0)
event_request_timer(trigger_server_timeout, (char *) 0, var_idle_limit);
@ -322,6 +327,54 @@ static void trigger_server_accept_local(int unused_event, char *context)
close(fd);
}
#ifdef MASTER_XPORT_NAME_PASS
/* trigger_server_accept_pass - accept descriptor */
static void trigger_server_accept_pass(int unused_event, char *context)
{
char *myname = "trigger_server_accept_pass";
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
int time_left = 0;
int fd;
if (msg_verbose)
msg_info("%s: trigger arrived", myname);
/*
* Read a message from a socket. Be prepared for accept() to fail because
* some other process already got the connection. The socket is
* non-blocking so we won't get stuck when multiple processes wake up.
* Don't get stuck when the client connects but sends no data. Restart
* the idle timer if this was a false alarm.
*/
if (var_idle_limit > 0)
time_left = event_cancel_timer(trigger_server_timeout, (char *) 0);
if (trigger_server_pre_accept)
trigger_server_pre_accept(trigger_server_name, trigger_server_argv);
fd = PASS_ACCEPT(listen_fd);
if (trigger_server_lock != 0
&& myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK,
MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(trigger_server_timeout, (char *) 0, time_left);
return;
}
close_on_exec(fd, CLOSE_ON_EXEC);
if (read_wait(fd, 10) == 0)
trigger_server_wakeup(fd);
else if (time_left >= 0)
event_request_timer(trigger_server_timeout, (char *) 0, time_left);
close(fd);
}
#endif
/* trigger_server_main - the real main program */
NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,...)
@ -350,6 +403,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
int zerolimit = 0;
WATCHDOG *watchdog;
char *oval;
char *generation;
/*
* Process environment options as early as we can.
@ -505,6 +559,11 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
msg_fatal("service %s requires a process limit of 0",
service_name);
break;
case MAIL_SERVER_PRIVILEGED:
if (user_name)
msg_fatal("service %s requires privileged operation",
service_name);
break;
default:
msg_panic("%s: unknown argument type: %d", myname, key);
}
@ -548,10 +607,26 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
trigger_server_accept = trigger_server_accept_local;
else if (strcasecmp(transport, MASTER_XPORT_NAME_FIFO) == 0)
trigger_server_accept = trigger_server_accept_fifo;
#ifdef MASTER_XPORT_NAME_PASS
else if (strcasecmp(transport, MASTER_XPORT_NAME_PASS) == 0)
trigger_server_accept = trigger_server_accept_pass;
#endif
else
msg_fatal("unsupported transport type: %s", transport);
}
/*
* Retrieve process generation from environment.
*/
if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
if (!alldig(generation))
msg_fatal("bad generation: %s", generation);
OCTAL_TO_UNSIGNED(trigger_server_generation, generation);
if (msg_verbose)
msg_info("process generation: %s (%o)",
generation, trigger_server_generation);
}
/*
* Optionally start the debugger on ourself.
*/
@ -595,6 +670,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
* Optionally, restrict the damage that this process can do.
*/
resolve_local_init();
#ifdef SNAPSHOT
tzset();
#endif
chroot_uid(root_dir, user_name);
/*

View File

@ -19,8 +19,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -51,7 +53,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -155,6 +157,9 @@ qmgr_entry.o: ../../include/events.h
qmgr_entry.o: ../../include/vstream.h
qmgr_entry.o: ../../include/vbuf.h
qmgr_entry.o: ../../include/mail_params.h
qmgr_entry.o: ../../include/deliver_request.h
qmgr_entry.o: ../../include/vstring.h
qmgr_entry.o: ../../include/recipient_list.h
qmgr_entry.o: qmgr.h
qmgr_entry.o: ../../include/scan_dir.h
qmgr_message.o: qmgr_message.c
@ -185,6 +190,7 @@ qmgr_message.o: ../../include/mail_proto.h
qmgr_message.o: ../../include/iostuff.h
qmgr_message.o: ../../include/attr.h
qmgr_message.o: ../../include/qmgr_user.h
qmgr_message.o: ../../include/split_addr.h
qmgr_message.o: ../../include/rewrite_clnt.h
qmgr_message.o: ../../include/resolve_clnt.h
qmgr_message.o: qmgr.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr.c,v 1.1.1.2 2004/05/31 00:24:39 heas Exp $ */
/* $NetBSD: qmgr.c,v 1.1.1.3 2005/08/18 21:07:50 rpaulo Exp $ */
/*++
/* NAME
@ -8,7 +8,7 @@
/* SYNOPSIS
/* \fBqmgr\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBqmgr\fR daemon awaits the arrival of incoming mail
/* The \fBqmgr\fR(8) daemon awaits the arrival of incoming mail
/* and arranges for its delivery via Postfix delivery processes.
/* The actual mail routing strategy is delegated to the
/* \fBtrivial-rewrite\fR(8) daemon.
@ -21,10 +21,10 @@
/* MAIL QUEUES
/* .ad
/* .fi
/* The \fBqmgr\fR daemon maintains the following queues:
/* The \fBqmgr\fR(8) daemon maintains the following queues:
/* .IP \fBincoming\fR
/* Inbound mail from the network, or mail picked up by the
/* local \fBpickup\fR agent from the \fBmaildrop\fR directory.
/* local \fBpickup\fR(8) agent from the \fBmaildrop\fR directory.
/* .IP \fBactive\fR
/* Messages that the queue manager has opened for delivery. Only
/* a limited number of messages is allowed to enter the \fBactive\fR
@ -41,7 +41,7 @@
/* DELIVERY STATUS REPORTS
/* .ad
/* .fi
/* The \fBqmgr\fR daemon keeps an eye on per-message delivery status
/* The \fBqmgr\fR(8) daemon keeps an eye on per-message delivery status
/* reports in the following directories. Each status report file has
/* the same name as the corresponding message file:
/* .IP \fBbounce\fR
@ -55,7 +55,7 @@
/* Postfix "\fBsendmail -v\fR" or "\fBsendmail -bv\fR" command.
/* These files are maintained by the \fBtrace\fR(8) daemon.
/* .PP
/* The \fBqmgr\fR daemon is responsible for asking the
/* The \fBqmgr\fR(8) daemon is responsible for asking the
/* \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemons to
/* send delivery reports.
/* STRATEGIES
@ -111,7 +111,7 @@
/* servers that should not go away forever. The action is to start
/* an incoming queue scan.
/* .PP
/* The \fBqmgr\fR daemon reads an entire buffer worth of triggers.
/* The \fBqmgr\fR(8) daemon reads an entire buffer worth of triggers.
/* Multiple identical trigger requests are collapsed into one, and
/* trigger requests are sorted so that \fBA\fR and \fBF\fR precede
/* \fBD\fR and \fBI\fR. Thus, in order to force a deferred queue run,
@ -120,17 +120,17 @@
/* STANDARDS
/* .ad
/* .fi
/* None. The \fBqmgr\fR daemon does not interact with the outside world.
/* None. The \fBqmgr\fR(8) daemon does not interact with the outside world.
/* SECURITY
/* .ad
/* .fi
/* The \fBqmgr\fR daemon is not security sensitive. It reads
/* The \fBqmgr\fR(8) daemon is not security sensitive. It reads
/* single-character messages from untrusted local users, and thus may
/* be susceptible to denial of service attacks. The \fBqmgr\fR daemon
/* be susceptible to denial of service attacks. The \fBqmgr\fR(8) daemon
/* does not talk to the outside world, and it can be run at fixed low
/* privilege in a chrooted environment.
/* DIAGNOSTICS
/* Problems and transactions are logged to the syslog daemon.
/* Problems and transactions are logged to the \fBsyslog\fR(8) daemon.
/* Corrupted message files are saved to the \fBcorrupt\fR queue
/* for further inspection.
/*
@ -138,17 +138,18 @@
/* the postmaster is notified of bounces and of other trouble.
/* BUGS
/* A single queue manager process has to compete for disk access with
/* multiple front-end processes such as \fBsmtpd\fR. A sudden burst of
/* multiple front-end processes such as \fBcleanup\fR(8). A sudden burst of
/* inbound mail can negatively impact outbound delivery rates.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are not picked up automatically, as qmgr(8)
/* processes are persistent. Use the command "\fBpostfix reload\fR" after
/* Changes to \fBmain.cf\fR are not picked up automatically,
/* as \fBqmgr\fR(8)
/* is a persistent process. Use the command "\fBpostfix reload\fR" after
/* a configuration change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/*
/* In the text below, \fItransport\fR is the first field in a
/* \fBmaster.cf\fR entry.
@ -251,8 +252,9 @@
/* trivial-rewrite(8), address routing
/* bounce(8), delivery status reports
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* master(8), process manager
/* syslogd(8) system logging
/* syslogd(8), system logging
/* README FILES
/* .ad
/* .fi
@ -493,10 +495,15 @@ static void qmgr_post_init(char *unused_name, char **unused_argv)
* Sanity check.
*/
if (var_qmgr_rcpt_limit < var_qmgr_active_limit) {
msg_warn("%s is smaller than %s",
VAR_QMGR_RCPT_LIMIT, VAR_QMGR_ACT_LIMIT);
msg_warn("%s is smaller than %s - adjusting %s",
VAR_QMGR_RCPT_LIMIT, VAR_QMGR_ACT_LIMIT, VAR_QMGR_RCPT_LIMIT);
var_qmgr_rcpt_limit = var_qmgr_active_limit;
}
if (var_dsn_queue_time > var_max_queue_time) {
msg_warn("%s is larger than %s - adjusting %s",
VAR_DSN_QUEUE_TIME, VAR_MAX_QUEUE_TIME, VAR_DSN_QUEUE_TIME);
var_dsn_queue_time = var_max_queue_time;
}
/*
* This routine runs after the skeleton code has entered the chroot jail.

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr.h,v 1.1.1.2 2004/05/31 00:24:39 heas Exp $ */
/* $NetBSD: qmgr.h,v 1.1.1.3 2005/08/18 21:07:51 rpaulo Exp $ */
/*++
/* NAME
@ -142,6 +142,8 @@ struct QMGR_ENTRY_LIST {
};
struct QMGR_QUEUE {
int dflags; /* delivery request options */
time_t last_done; /* last delivery completion */
char *name; /* domain name or address */
char *nexthop; /* domain name */
int todo_refcount; /* queue entries (todo list) */
@ -243,6 +245,10 @@ struct QMGR_MESSAGE {
char *client_addr; /* client address */
char *client_proto; /* client protocol */
char *client_helo; /* helo parameter */
char *sasl_method; /* SASL method */
char *sasl_username; /* SASL user name */
char *sasl_sender; /* SASL sender */
char *rewrite_context; /* address qualification */
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_deliver.c,v 1.1.1.2 2004/05/31 00:24:40 heas Exp $ */
/* $NetBSD: qmgr_deliver.c,v 1.1.1.3 2005/08/18 21:07:53 rpaulo Exp $ */
/*++
/* NAME
@ -145,6 +145,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
}
flags = message->tflags
| entry->queue->dflags
| (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT);
attr_print(stream, ATTR_FLAG_MORE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
@ -162,6 +163,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_entry.c,v 1.1.1.2 2004/05/31 00:24:40 heas Exp $ */
/* $NetBSD: qmgr_entry.c,v 1.1.1.3 2005/08/18 21:07:54 rpaulo Exp $ */
/*++
/* NAME
@ -86,6 +86,7 @@
/* Global library. */
#include <mail_params.h>
#include <deliver_request.h> /* opportunistic session caching */
/* Application-specific. */
@ -95,6 +96,7 @@
QMGR_ENTRY *qmgr_entry_select(QMGR_QUEUE *queue)
{
char *myname = "qmgr_entry_select";
QMGR_ENTRY *entry;
if ((entry = queue->todo.prev) != 0) {
@ -102,6 +104,59 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_QUEUE *queue)
queue->todo_refcount--;
QMGR_LIST_APPEND(queue->busy, entry);
queue->busy_refcount++;
/*
* With opportunistic session caching, the delivery agent must not
* only 1) save a session upon completion, but also 2) reuse a cached
* session upon the next delivery request. In order to not miss out
* on 2), we have to make caching sticky or else we get silly
* behavior when the in-memory queue drains. Specifically, new
* connections must not be made as long as cached connections exist.
*
* Safety: don't enable opportunistic session caching unless the queue
* manager is able to schedule concurrent or back-to-back deliveries
* (we need to recognize back-to-back deliveries for transports with
* concurrency 1).
*
* XXX It would be nice if we could say "try to reuse a cached
* connection, but don't bother saving it when you're done". As long
* as we can't, we must not turn off session caching too early.
*/
#define CONCURRENT_OR_BACK_TO_BACK_DELIVERY() \
(queue->busy_refcount > 1 || BACK_TO_BACK_DELIVERY())
#define BACK_TO_BACK_DELIVERY() \
(queue->last_done + 1 >= event_time())
/*
* Turn on session caching after we get up to speed. Don't enable
* session caching just because we have concurrent deliveries. This
* prevents unnecessary session caching when we have a burst of mail
* <= the initial concurrency limit.
*/
if ((queue->dflags & DEL_REQ_FLAG_SCACHE) == 0) {
if (BACK_TO_BACK_DELIVERY()) {
if (msg_verbose)
msg_info("%s: allowing on-demand session caching for %s",
myname, queue->name);
queue->dflags |= DEL_REQ_FLAG_SCACHE;
}
}
/*
* Turn off session caching when concurrency drops and we're running
* out of steam. This is what prevents from turning off session
* caching too early, and from making new connections while old ones
* are still cached.
*/
else {
if (!CONCURRENT_OR_BACK_TO_BACK_DELIVERY()) {
if (msg_verbose)
msg_info("%s: disallowing on-demand session caching for %s",
myname, queue->name);
queue->dflags &= ~DEL_REQ_FLAG_SCACHE;
}
}
}
return (entry);
}
@ -147,6 +202,11 @@ void qmgr_entry_done(QMGR_ENTRY *entry, int which)
myfree((char *) entry);
/*
* Maintain back-to-back delivery status.
*/
queue->last_done = event_time();
/*
* When the in-core queue for this site is empty and when this site is
* not dead, discard the in-core queue. When this site is dead, but the

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_message.c,v 1.1.1.3 2004/07/28 22:49:23 heas Exp $ */
/* $NetBSD: qmgr_message.c,v 1.1.1.4 2005/08/18 21:07:58 rpaulo Exp $ */
/*++
/* NAME
@ -124,6 +124,7 @@
#include <verp_sender.h>
#include <mail_proto.h>
#include <qmgr_user.h>
#include <split_addr.h>
/* Client stubs. */
@ -174,6 +175,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
message->client_addr = 0;
message->client_proto = 0;
message->client_helo = 0;
message->sasl_method = 0;
message->sasl_username = 0;
message->sasl_sender = 0;
message->rewrite_context = 0;
qmgr_rcpt_list_init(&message->rcpt_list);
return (message);
}
@ -217,8 +222,7 @@ static int qmgr_message_open(QMGR_MESSAGE *message)
static void qmgr_message_oldstyle_scan(QMGR_MESSAGE *message)
{
VSTRING *buf;
long orig_offset,
extra_offset;
long orig_offset, extra_offset;
int rec_type;
char *start;
@ -527,6 +531,34 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
myfree(message->client_helo);
message->client_helo = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_SASL_METHOD) == 0) {
if (message->sasl_method == 0)
message->sasl_method = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
message->queue_id, MAIL_ATTR_SASL_METHOD, value);
}
if (strcmp(name, MAIL_ATTR_SASL_USERNAME) == 0) {
if (message->sasl_username == 0)
message->sasl_username = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
}
if (strcmp(name, MAIL_ATTR_SASL_SENDER) == 0) {
if (message->sasl_sender == 0)
message->sasl_sender = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
message->queue_id, MAIL_ATTR_SASL_SENDER, value);
}
if (strcmp(name, MAIL_ATTR_RWR_CONTEXT) == 0) {
if (message->rewrite_context == 0)
message->rewrite_context = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@ -600,6 +632,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
message->client_proto = mystrdup("");
if (message->client_helo == 0)
message->client_helo = mystrdup("");
if (message->sasl_method == 0)
message->sasl_method = mystrdup("");
if (message->sasl_username == 0)
message->sasl_username = mystrdup("");
if (message->sasl_sender == 0)
message->sasl_sender = mystrdup("");
if (message->rewrite_context == 0)
message->rewrite_context = mystrdup(MAIL_ATTR_RWR_LOCAL);
/*
* Clean up.
@ -1074,6 +1114,14 @@ void qmgr_message_free(QMGR_MESSAGE *message)
myfree(message->client_proto);
if (message->client_helo)
myfree(message->client_helo);
if (message->sasl_method)
myfree(message->sasl_method);
if (message->sasl_username)
myfree(message->sasl_username);
if (message->sasl_sender)
myfree(message->sasl_sender);
if (message->rewrite_context)
myfree(message->rewrite_context);
qmgr_rcpt_list_free(&message->rcpt_list);
qmgr_message_count--;
myfree((char *) message);
@ -1123,10 +1171,17 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
* queue file and *before* resolving new recipients. Since all those
* operations are encapsulated so nicely by this routine, the defer
* log reset has to be done here as well.
*
* Likewise remove a trace file with results from address verification,
* "what if" testing, or verbose delivery.
*/
if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
msg_fatal("%s: %s: remove %s %s: %m", myname,
queue_id, MAIL_QUEUE_DEFER, queue_id);
if (message->tflags != 0
&& mail_queue_remove(MAIL_QUEUE_TRACE, queue_id) && errno != ENOENT)
msg_fatal("%s: %s: remove %s %s: %m", myname,
queue_id, MAIL_QUEUE_TRACE, queue_id);
qmgr_message_sort(message);
qmgr_message_resolve(message);
qmgr_message_sort(message);

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_queue.c,v 1.1.1.2 2004/05/31 00:24:41 heas Exp $ */
/* $NetBSD: qmgr_queue.c,v 1.1.1.3 2005/08/18 21:07:58 rpaulo Exp $ */
/*++
/* NAME
@ -185,6 +185,7 @@ void qmgr_queue_throttle(QMGR_QUEUE *queue, const char *reason)
queue->reason = mystrdup(reason);
event_request_timer(qmgr_queue_unthrottle_wrapper,
(char *) queue, var_min_backoff_time);
queue->dflags = 0;
}
}
@ -256,6 +257,8 @@ QMGR_QUEUE *qmgr_queue_create(QMGR_TRANSPORT *transport, const char *name,
queue = (QMGR_QUEUE *) mymalloc(sizeof(QMGR_QUEUE));
qmgr_queue_count++;
queue->dflags = 0;
queue->last_done = 0;
queue->name = mystrdup(name);
queue->nexthop = mystrdup(nexthop);
queue->todo_refcount = 0;

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: pickup.c,v 1.1.1.9 2004/07/28 22:49:23 heas Exp $ */
/* $NetBSD: pickup.c,v 1.1.1.10 2005/08/18 21:08:01 rpaulo Exp $ */
/*++
/* NAME
@ -8,7 +8,7 @@
/* SYNOPSIS
/* \fBpickup\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBpickup\fR daemon waits for hints that new mail has been
/* The \fBpickup\fR(8) daemon waits for hints that new mail has been
/* dropped into the \fBmaildrop\fR directory, and feeds it into the
/* \fBcleanup\fR(8) daemon.
/* Ill-formatted files are deleted without notifying the originator.
@ -17,32 +17,33 @@
/* STANDARDS
/* .ad
/* .fi
/* None. The \fBpickup\fR daemon does not interact with the outside world.
/* None. The \fBpickup\fR(8) daemon does not interact with
/* the outside world.
/* SECURITY
/* .ad
/* .fi
/* The \fBpickup\fR daemon is moderately security sensitive. It runs
/* The \fBpickup\fR(8) daemon is moderately security sensitive. It runs
/* with fixed low privilege and can run in a chrooted environment.
/* However, the program reads files from potentially hostile users.
/* The \fBpickup\fR daemon opens no files for writing, is careful about
/* The \fBpickup\fR(8) daemon opens no files for writing, is careful about
/* what files it opens for reading, and does not actually touch any data
/* that is sent to its public service endpoint.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
/* The \fBpickup\fR daemon copies mail from file to the \fBcleanup\fR(8)
/* The \fBpickup\fR(8) daemon copies mail from file to the \fBcleanup\fR(8)
/* daemon. It could avoid message copying overhead by sending a file
/* descriptor instead of file data, but then the already complex
/* \fBcleanup\fR(8) daemon would have to deal with unfiltered user data.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* As the pickup(8) daemon is a relatively long-running process, up
/* As the \fBpickup\fR(8) daemon is a relatively long-running process, up
/* to an hour may pass before a \fBmain.cf\fR change takes effect.
/* Use the command "\fBpostfix reload\fR" command to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* CONTENT INSPECTION CONTROLS
/* .ad
/* .fi
@ -51,7 +52,7 @@
/* it is queued.
/* .IP "\fBreceive_override_options (empty)\fR"
/* Enable or disable recipient validation, built-in content
/* filtering, or address rewriting.
/* filtering, or address mapping.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
@ -89,6 +90,7 @@
/* sendmail(1), Sendmail-compatible interface
/* postdrop(1), mail posting agent
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* master(8), process manager
/* syslogd(8), system logging
/* LICENSE
@ -289,12 +291,6 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup,
if (*var_filter_xport)
rec_fprintf(cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
/*
* Origin is local.
*/
rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ORIGIN, MAIL_ATTR_ORG_LOCAL);
/*
* Copy the message envelope segment. Allow only those records that we
* expect to see in the envelope section. The envelope segment must
@ -413,11 +409,9 @@ static int pickup_file(PICKUP_INFO *info)
* easier to implement the many possible error exits without forgetting
* to close files, or to release memory.
*/
cleanup_flags = (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL);
if (pickup_input_transp_mask & INPUT_TRANSP_ADDRESS_MAPPING)
cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK);
if (pickup_input_transp_mask & INPUT_TRANSP_HEADER_BODY)
cleanup_flags &= ~CLEANUP_FLAG_FILTER;
cleanup_flags =
input_transp_cleanup(CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL,
pickup_input_transp_mask);
cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: pipe.c,v 1.1.1.7 2004/05/31 00:24:41 heas Exp $ */
/* $NetBSD: pipe.c,v 1.1.1.8 2005/08/18 21:08:03 rpaulo Exp $ */
/*++
/* NAME
@ -8,7 +8,7 @@
/* SYNOPSIS
/* \fBpipe\fR [generic Postfix daemon options] command_attributes...
/* DESCRIPTION
/* The \fBpipe\fR daemon processes requests from the Postfix queue
/* The \fBpipe\fR(8) daemon processes requests from the Postfix queue
/* manager to deliver messages to external commands.
/* This program expects to be run from the \fBmaster\fR(8) process
/* manager.
@ -17,7 +17,7 @@
/* next-hop host name can be specified as command-line macros that are
/* expanded before the external command is executed.
/*
/* The \fBpipe\fR daemon updates queue files and marks recipients
/* The \fBpipe\fR(8) daemon updates queue files and marks recipients
/* as finished, or it informs the queue manager that delivery should
/* be tried again at a later time. Delivery status reports are sent
/* to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as
@ -43,6 +43,16 @@
/* .fi
/* The external command attributes are given in the \fBmaster.cf\fR
/* file at the end of a service definition. The syntax is as follows:
/* .IP "\fBdirectory=\fIpathname\fR (optional, default: \fB$queue_directory\fR)"
/* Change to the named directory before executing the external command.
/* Delivery is deferred in case of failure.
/* .sp
/* This feature is available as of Postfix 2.2.
/* .IP "\fBeol=string\fR (optional, default: \fB\en\fR)"
/* The output record delimiter. Typically one would use either
/* \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
/* sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
/* \e\fIddd\fR (up to three octal digits) and \fB\e\e\fR.
/* .IP "\fBflags=BDFORhqu.>\fR (optional)"
/* Optional message processing flags. By default, a message is
/* copied unchanged.
@ -55,6 +65,8 @@
/* Prepend a "\fBDelivered-To: \fIrecipient\fR" message header with the
/* envelope recipient address. Note: for this to work, the
/* \fItransport\fB_destination_recipient_limit\fR must be 1.
/* .sp
/* This feature is available as of Postfix 2.0.
/* .IP \fBF\fR
/* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
/* the message content.
@ -63,6 +75,8 @@
/* Prepend an "\fBX-Original-To: \fIrecipient\fR" message header
/* with the recipient address as given to Postfix. Note: for this to
/* work, the \fItransport\fB_destination_recipient_limit\fR must be 1.
/* .sp
/* This feature is available as of Postfix 2.0.
/* .IP \fBR\fR
/* Prepend a \fBReturn-Path:\fR message header with the envelope sender
/* address.
@ -78,7 +92,7 @@
/* This is recommended for delivery via \fBUUCP\fR or \fBBSMTP\fR.
/* .sp
/* The result is compatible with the address parsing of command-line
/* recipients by the Postfix \fBsendmail\fR mail submission command.
/* recipients by the Postfix \fBsendmail\fR(1) mail submission command.
/* .sp
/* The \fBq\fR flag affects only entire addresses, not the partial
/* address information from the \fB$user\fR, \fB$extension\fR or
@ -88,12 +102,15 @@
/* the left of the right-most \fB@\fR character) to lower case.
/* This is recommended for delivery via \fBUUCP\fR.
/* .IP \fB.\fR
/* Prepend \fB.\fR to lines starting with "\fB.\fR". This is needed
/* Prepend "\fB.\fR" to lines starting with "\fB.\fR". This is needed
/* by, for example, \fBBSMTP\fR software.
/* .IP \fB>\fR
/* Prepend \fB>\fR to lines starting with "\fBFrom \fR". This is expected
/* Prepend "\fB>\fR" to lines starting with "\fBFrom \fR". This is expected
/* by, for example, \fBUUCP\fR software.
/* .RE
/* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
/* Messages greater in size than this limit (in bytes) will be bounced
/* back to the sender.
/* .IP "\fBuser\fR=\fIusername\fR (required)"
/* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
/* The external command is executed with the rights of the
@ -102,14 +119,6 @@
/* mail system owner. If \fIgroupname\fR is specified, the
/* corresponding group ID is used instead of the group ID of
/* \fIusername\fR.
/* .IP "\fBeol=string\fR (optional, default: \fB\en\fR)"
/* The output record delimiter. Typically one would use either
/* \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
/* sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
/* \e\fIoctal\fR and \fB\e\e\fR.
/* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
/* Messages greater in size than this limit (in bytes) will be bounced
/* back to the sender.
/* .IP "\fBargv\fR=\fIcommand\fR... (required)"
/* The command to be executed. This must be specified as the
/* last command attribute.
@ -118,8 +127,28 @@
/* .sp
/* In the command argument vector, the following macros are recognized
/* and replaced with corresponding information from the Postfix queue
/* manager delivery request:
/* manager delivery request.
/* .sp
/* In addition to the form ${\fIname\fR}, the forms $\fIname\fR and
/* $(\fIname\fR) are also recognized. Specify \fB$$\fR where a single
/* \fB$\fR is wanted.
/* .RS
/* .IP \fB${\fBclient_address\fR}\fR
/* This macro expands to the remote client network address.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBclient_helo\fR}\fR
/* This macro expands to the remote client HELO command parameter.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBclient_hostname\fR}\fR
/* This macro expands to the remote client hostname.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBclient_protocol\fR}\fR
/* This macro expands to the remote client protocol.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBextension\fR}\fR
/* This macro expands to the extension part of a recipient address.
/* For example, with an address \fIuser+foo@domain\fR the extension is
@ -150,6 +179,23 @@
/* .sp
/* This information is modified by the \fBhqu\fR flags for quoting
/* and case folding.
/* .IP \fB${\fBsasl_method\fR}\fR
/* This macro expands to the SASL authentication mechanism used
/* during the reception of the message. An empty string is passed
/* if the message has been received without SASL authentication.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBsasl_sender\fR}\fR
/* This macro expands to the SASL sender name (i.e. the original
/* submitter as per RFC 2554) used during the reception of the message.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBsasl_username\fR}\fR
/* This macro expands to the SASL user name used during the reception
/* of the message. An empty string is passed if the message has been
/* received without SASL authentication.
/* .sp
/* This is available in Postfix 2.2 and later.
/* .IP \fB${\fBsender\fR}\fR
/* This macro expands to the envelope sender address.
/* .sp
@ -167,10 +213,6 @@
/* .sp
/* This information is modified by the \fBu\fR flag for case folding.
/* .RE
/* .PP
/* In addition to the form ${\fIname\fR}, the forms $\fIname\fR and
/* $(\fIname\fR) are also recognized. Specify \fB$$\fR where a single
/* \fB$\fR is wanted.
/* DIAGNOSTICS
/* Command exit status codes are expected to
/* follow the conventions defined in <\fBsysexits.h\fR>.
@ -187,12 +229,12 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically as pipe(8)
/* Changes to \fBmain.cf\fR are picked up automatically as \fBpipe\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@ -251,6 +293,7 @@
/* qmgr(8), queue manager
/* bounce(8), delivery status reports
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* master(8), process manager
/* syslogd(8), system logging
/* LICENSE
@ -334,6 +377,13 @@
#define PIPE_DICT_EXTENSION "extension" /* key */
#define PIPE_DICT_MAILBOX "mailbox" /* key */
#define PIPE_DICT_SIZE "size" /* key */
#define PIPE_DICT_CLIENT_ADDR "client_address" /* key */
#define PIPE_DICT_CLIENT_NAME "client_hostname" /* key */
#define PIPE_DICT_CLIENT_PROTO "client_protocol" /* key */
#define PIPE_DICT_CLIENT_HELO "client_helo" /* key */
#define PIPE_DICT_SASL_METHOD "sasl_method" /* key */
#define PIPE_DICT_SASL_USERNAME "sasl_username" /* key */
#define PIPE_DICT_SASL_SENDER "sasl_sender" /* key */
/*
* Flags used to pass back the type of special parameter found by
@ -380,6 +430,7 @@ typedef struct {
uid_t uid; /* command privileges */
gid_t gid; /* command privileges */
int flags; /* mail_copy() flags */
char *exec_dir; /* working directory */
VSTRING *eol; /* output record delimiter */
off_t size_limit; /* max size in bytes we will accept */
} PIPE_ATTR;
@ -414,6 +465,13 @@ static int parse_callback(int type, VSTRING *buf, char *context)
PIPE_DICT_EXTENSION, PIPE_FLAG_EXTENSION,
PIPE_DICT_MAILBOX, PIPE_FLAG_MAILBOX,
PIPE_DICT_SIZE, 0,
PIPE_DICT_CLIENT_ADDR, 0,
PIPE_DICT_CLIENT_NAME, 0,
PIPE_DICT_CLIENT_PROTO, 0,
PIPE_DICT_CLIENT_HELO, 0,
PIPE_DICT_SASL_METHOD, 0,
PIPE_DICT_SASL_USERNAME, 0,
PIPE_DICT_SASL_SENDER, 0,
0, 0,
};
struct cmd_flags *p;
@ -624,6 +682,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
group = 0;
attr->command = 0;
attr->flags = 0;
attr->exec_dir = 0;
attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
attr->size_limit = 0;
@ -695,6 +754,13 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
}
}
/*
* directory=string
*/
else if (strncasecmp("directory=", *argv, sizeof("directory=") - 1) == 0) {
attr->exec_dir = mystrdup(*argv + sizeof("directory=") - 1);
}
/*
* eol=string
*/
@ -954,6 +1020,20 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
dict_update(PIPE_DICT_TABLE, PIPE_DICT_NEXTHOP, request->nexthop);
vstring_sprintf(buf, "%ld", (long) request->data_size);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SIZE, STR(buf));
dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_ADDR,
request->client_addr);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_HELO,
request->client_helo);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_NAME,
request->client_name);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_PROTO,
request->client_proto);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_METHOD,
request->sasl_method);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_USERNAME,
request->sasl_username);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_SENDER,
request->sasl_sender);
vstring_free(buf);
if ((expanded_argv = expand_argv(service, attr.command,
@ -975,6 +1055,7 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
PIPE_CMD_TIME_LIMIT, conf.time_limit,
PIPE_CMD_EOL, STR(attr.eol),
PIPE_CMD_EXPORT, export_env->argv,
PIPE_CMD_CWD, attr.exec_dir,
PIPE_CMD_ORIG_RCPT, rcpt_list->info[0].orig_addr,
PIPE_CMD_DELIVERED, rcpt_list->info[0].address,
PIPE_CMD_END);
@ -1052,5 +1133,6 @@ int main(int argc, char **argv)
MAIL_SERVER_PRE_INIT, pre_init,
MAIL_SERVER_POST_INIT, drop_privileges,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
MAIL_SERVER_PRIVILEGED,
0);
}

View File

@ -15,14 +15,16 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
update: ../../bin/$(PROG)
tests: test1 test2
test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-ABC1.ref
test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-uABC1.ref
./$(PROG) map.in
for key in abc ghi; \
do \
@ -31,11 +33,11 @@ test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-ABC1.ref
./$(PROG) -f map.in
for key in ABC; \
do \
./$(PROG) -fq $${key} map.in | diff map-$${key}1.ref -; \
./$(PROG) -fq $${key} map.in | diff map-u$${key}1.ref -; \
done
rm -f map.in.db
test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-ABC2.ref
test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-uABC2.ref
./$(PROG) map.in
for key in abc ghi; \
do \
@ -44,7 +46,7 @@ test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-ABC2.ref
./$(PROG) -f map.in
for key in ABC; \
do \
echo $${key} | ./$(PROG) -fq - map.in | diff map-$${key}2.ref -; \
echo $${key} | ./$(PROG) -fq - map.in | diff map-u$${key}2.ref -; \
done
rm -f map.in.db
@ -70,7 +72,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -0,0 +1 @@
DEF

View File

@ -0,0 +1 @@
ABC: DEF

View File

@ -1,4 +1,4 @@
/* $NetBSD: postalias.c,v 1.1.1.7 2004/05/31 00:24:41 heas Exp $ */
/* $NetBSD: postalias.c,v 1.1.1.8 2005/08/18 21:08:05 rpaulo Exp $ */
/*++
/* NAME
@ -7,11 +7,11 @@
/* Postfix alias database maintenance
/* SYNOPSIS
/* .fi
/* \fBpostalias\fR [\fB-Nfinoprvw\fR] [\fB-c \fIconfig_dir\fR]
/* \fBpostalias\fR [\fB-Nfinoprsvw\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
/* [\fIfile_type\fR:]\fIfile_name\fR ...
/* DESCRIPTION
/* The \fBpostalias\fR command creates or queries one or more Postfix
/* The \fBpostalias\fR(1) command creates or queries one or more Postfix
/* alias databases, or updates an existing one. The input and output
/* file formats are expected to be compatible with Sendmail version 8,
/* and are expected to be suitable for the use as NIS alias maps.
@ -43,19 +43,21 @@
/* a map.
/* .IP \fB-i\fR
/* Incremental mode. Read entries from standard input and do not
/* truncate an existing database. By default, \fBpostalias\fR creates
/* truncate an existing database. By default, \fBpostalias\fR(1) creates
/* a new database from the entries in \fIfile_name\fR.
/* .IP \fB-N\fR
/* Include the terminating null character that terminates lookup keys
/* and values. By default, Postfix does whatever is the default for
/* and values. By default, \fBpostalias\fR(1) does whatever
/* is the default for
/* the host operating system.
/* .IP \fB-n\fR
/* Don't include the terminating null character that terminates lookup
/* keys and values. By default, Postfix does whatever is the default for
/* keys and values. By default, \fBpostalias\fR(1) does whatever
/* is the default for
/* the host operating system.
/* .IP \fB-o\fR
/* Do not release root privileges when processing a non-root
/* input file. By default, \fBpostalias\fR drops root privileges
/* input file. By default, \fBpostalias\fR(1) drops root privileges
/* and runs as the source file owner instead.
/* .IP \fB-p\fR
/* Do not inherit the file access permissions from the input file
@ -71,37 +73,48 @@
/* \fIkey: value\fR output for each key that was found. The exit
/* status is zero when at least one of the requested keys was found.
/* .IP \fB-r\fR
/* When updating a table, do not warn about duplicate entries; silently
/* replace them.
/* When updating a table, do not complain about attempts to update
/* existing entries, and make those updates anyway.
/* .IP \fB-s\fR
/* Retrieve all database elements, and write one line of
/* \fIkey: value\fR output for each element. The elements are
/* printed in database order, which is not necessarily the same
/* as the original input order.
/* This feature is available in Postfix version 2.2 and later,
/* and is not available for all database types.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
/* .IP \fB-w\fR
/* When updating a table, do not warn about duplicate entries; silently
/* ignore them.
/* When updating a table, do not complain about attempts to update
/* existing entries, and ignore those attempts.
/* .PP
/* Arguments:
/* .IP \fIfile_type\fR
/* The database type. To find out what types are supported, use
/* the "\fBpostconf -m" command.
/* the "\fBpostconf -m\fR" command.
/*
/* The \fBpostalias\fR command can query any supported file type,
/* The \fBpostalias\fR(1) command can query any supported file type,
/* but it can create only the following file types:
/* .RS
/* .IP \fBbtree\fR
/* The output is a btree file, named \fIfile_name\fB.db\fR.
/* This is available only on systems with support for \fBdb\fR databases.
/* This is available on systems with support for \fBdb\fR databases.
/* .IP \fBcdb\fR
/* The output is one file named \fIfile_name\fB.cdb\fR.
/* This is available on systems with support for \fBcdb\fR databases.
/* .IP \fBdbm\fR
/* The output consists of two files, named \fIfile_name\fB.pag\fR and
/* \fIfile_name\fB.dir\fR.
/* This is available only on systems with support for \fBdbm\fR databases.
/* This is available on systems with support for \fBdbm\fR databases.
/* .IP \fBhash\fR
/* The output is a hashed file, named \fIfile_name\fB.db\fR.
/* This is available only on systems with support for \fBdb\fR databases.
/* This is available on systems with support for \fBdb\fR databases.
/* .IP \fBsdbm\fR
/* The output consists of two files, named \fIfile_name\fB.pag\fR and
/* \fIfile_name\fB.dir\fR.
/* This is available on systems with support for \fBsdbm\fR databases.
/* .PP
/* Use the command \fBpostconf -m\fR to find out what types of database
/* your Postfix installation can support.
/*
/* When no \fIfile_type\fR is specified, the software uses the database
/* type specified via the \fBdefault_database_type\fR configuration
/* parameter.
@ -115,8 +128,8 @@
/* no problems were detected. Duplicate entries are skipped and are
/* flagged with a warning.
/*
/* \fBpostalias\fR terminates with zero exit status in case of success
/* (including successful \fBpostalias -q\fR lookup) and terminates
/* \fBpostalias\fR(1) terminates with zero exit status in case of success
/* (including successful "\fBpostalias -q\fR" lookup) and terminates
/* with non-zero exit status in case of failure.
/* ENVIRONMENT
/* .ad
@ -132,9 +145,9 @@
/* this program.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBalias_database (see 'postconf -d' output)\fR"
/* The alias databases for local(8) delivery that are updated with
/* The alias databases for \fBlocal\fR(8) delivery that are updated with
/* "\fBnewaliases\fR" or with "\fBsendmail -bi\fR".
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
@ -146,8 +159,8 @@
/* The per-table I/O buffer size for programs that read Berkeley DB
/* hash or btree tables.
/* .IP "\fBdefault_database_type (see 'postconf -d' output)\fR"
/* The default database type for use in newaliases(1), postalias(1)
/* and postmap(1) commands.
/* The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1)
/* and \fBpostmap\fR(1) commands.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (postfix)\fR"
@ -475,8 +488,8 @@ static int postalias_query(const char *map_type, const char *map_name,
map_type, map_name);
}
vstream_printf("%s\n", value);
vstream_fflush(VSTREAM_OUT);
}
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
return (value != 0);
}
@ -539,11 +552,39 @@ static int postalias_delete(const char *map_type, const char *map_name,
return (status == 0);
}
/* postalias_seq - print all map entries to stdout */
static void postalias_seq(const char *map_type, const char *map_name)
{
DICT *dict;
const char *key;
const char *value;
int func;
dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK);
for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) {
if (dict_seq(dict, func, &key, &value) != 0)
break;
if (*key == 0) {
msg_warn("table %s:%s: empty lookup key value is not allowed",
map_type, map_name);
} else if (*value == 0) {
msg_warn("table %s:%s: key %s: empty string result is not allowed",
map_type, map_name, key);
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
map_type, map_name);
}
vstream_printf("%s: %s\n", key, value);
}
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
}
/* usage - explain */
static NORETURN usage(char *myname)
{
msg_fatal("usage: %s [-Nfinorvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
msg_fatal("usage: %s [-Nfinoprsvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
myname);
}
@ -559,6 +600,7 @@ int main(int argc, char **argv)
int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_KEY;
char *query = 0;
char *delkey = 0;
int sequence = 0;
int found;
/*
@ -595,7 +637,7 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "Nc:d:finopq:rvw")) > 0) {
while ((ch = GETOPT(argc, argv, "Nc:d:finopq:rsvw")) > 0) {
switch (ch) {
default:
usage(argv[0]);
@ -609,8 +651,8 @@ int main(int argc, char **argv)
msg_fatal("out of memory");
break;
case 'd':
if (query || delkey)
msg_fatal("specify only one of -q or -d");
if (sequence || query || delkey)
msg_fatal("specify only one of -s -q or -d");
delkey = optarg;
break;
case 'f':
@ -630,14 +672,19 @@ int main(int argc, char **argv)
postalias_flags &= ~POSTALIAS_FLAG_SAVE_PERM;
break;
case 'q':
if (query || delkey)
msg_fatal("specify only one of -q or -d");
if (sequence || query || delkey)
msg_fatal("specify only one of -s -q or -d");
query = optarg;
break;
case 'r':
dict_flags &= ~(DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE);
dict_flags |= DICT_FLAG_DUP_REPLACE;
break;
case 's':
if (query || delkey)
msg_fatal("specify only one of -s or -q or -d");
sequence = 1;
break;
case 'v':
msg_verbose++;
break;
@ -688,6 +735,16 @@ int main(int argc, char **argv)
optind++;
}
exit(1);
} else if (sequence) {
while (optind < argc) {
if ((path_name = split_at(argv[optind], ':')) != 0) {
postalias_seq(argv[optind], path_name);
} else {
postalias_seq(var_db_type, argv[optind]);
}
exit(0);
}
exit(1);
} else { /* create/update map(s) */
if (optind + 1 > argc)
usage(argv[0]);

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: postcat.c,v 1.1.1.5 2004/05/31 00:24:41 heas Exp $ */
/* $NetBSD: postcat.c,v 1.1.1.6 2005/08/18 21:08:05 rpaulo Exp $ */
/*++
/* NAME
@ -6,9 +6,9 @@
/* SUMMARY
/* show Postfix queue file contents
/* SYNOPSIS
/* \fBpostcat\fR [\fB-vq\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
/* \fBpostcat\fR [\fB-oqv\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
/* DESCRIPTION
/* The \fBpostcat\fR command prints the contents of the named
/* The \fBpostcat\fR(1) command prints the contents of the named
/* \fIfiles\fR in human-readable form. The files are expected
/* to be in Postfix queue file format. If no
/* \fIfiles\fR are specified on the command line, the program
@ -18,6 +18,8 @@
/* .IP "\fB-c \fIconfig_dir\fR"
/* The \fBmain.cf\fR configuration file is in the named directory
/* instead of the default configuration directory.
/* .IP \fB-o\fR
/* Print the queue file offset of each record.
/* .IP \fB-q\fR
/* Search the Postfix queue for the named \fIfiles\fR instead
/* of taking the names literally.
@ -40,7 +42,7 @@
/* this program.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
@ -90,19 +92,22 @@
/* Application-specific. */
#define PC_FLAG_QUEUE (1<<0) /* search queue */
#define PC_FLAG_OFFSET (1<<1) /* print record offsets */
#define STR vstring_str
#define LEN VSTRING_LEN
/* postcat - visualize Postfix queue file contents */
static void postcat(VSTREAM *fp, VSTRING *buffer)
static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
{
int prev_type = 0;
int rec_type;
time_t time;
int first = 1;
int ch;
off_t offset;
int in_message = 0;
#define TEXT_RECORD(rec_type) \
(rec_type == REC_TYPE_CONT || rec_type == REC_TYPE_NORM)
@ -122,6 +127,8 @@ static void postcat(VSTREAM *fp, VSTRING *buffer)
* Now look at the rest.
*/
for (;;) {
if (flags & PC_FLAG_OFFSET)
offset = vstream_ftell(fp);
rec_type = rec_get(fp, buffer, 0);
if (rec_type == REC_TYPE_ERROR)
msg_fatal("record read error");
@ -133,6 +140,8 @@ static void postcat(VSTREAM *fp, VSTRING *buffer)
}
if (prev_type == REC_TYPE_CONT && !TEXT_RECORD(rec_type))
VSTREAM_PUTCHAR('\n');
if (flags & PC_FLAG_OFFSET)
vstream_printf("%9lu ", (unsigned long) offset);
switch (rec_type) {
case REC_TYPE_TIME:
case REC_TYPE_WARN:
@ -140,12 +149,16 @@ static void postcat(VSTREAM *fp, VSTRING *buffer)
vstream_printf("%s: %s", rec_type_name(rec_type),
asctime(localtime(&time)));
break;
case REC_TYPE_CONT:
if (msg_verbose)
case REC_TYPE_CONT: /* REC_TYPE_FILT collision */
if (!in_message)
vstream_printf("%s: ", rec_type_name(rec_type));
else if (msg_verbose)
vstream_printf("unterminated_text: ");
vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
if (msg_verbose)
if (!in_message || msg_verbose || (flags & PC_FLAG_OFFSET) != 0) {
rec_type = 0;
VSTREAM_PUTCHAR('\n');
}
break;
case REC_TYPE_NORM:
if (msg_verbose)
@ -155,9 +168,11 @@ static void postcat(VSTREAM *fp, VSTRING *buffer)
break;
case REC_TYPE_MESG:
vstream_printf("*** MESSAGE CONTENTS %s ***\n", VSTREAM_PATH(fp));
in_message = 1;
break;
case REC_TYPE_XTRA:
vstream_printf("*** HEADER EXTRACTED %s ***\n", VSTREAM_PATH(fp));
in_message = 0;
break;
case REC_TYPE_END:
vstream_printf("*** MESSAGE FILE END %s ***\n", VSTREAM_PATH(fp));
@ -220,12 +235,15 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "c:qv")) > 0) {
while ((ch = GETOPT(argc, argv, "c:oqv")) > 0) {
switch (ch) {
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
msg_fatal("out of memory");
break;
case 'o':
flags |= PC_FLAG_OFFSET;
break;
case 'q':
flags |= PC_FLAG_QUEUE;
break;
@ -254,7 +272,7 @@ int main(int argc, char **argv)
vstream_control(VSTREAM_IN,
VSTREAM_CTL_PATH, "stdin",
VSTREAM_CTL_END);
postcat(VSTREAM_IN, buffer);
postcat(VSTREAM_IN, buffer, flags);
}
/*
@ -271,7 +289,7 @@ int main(int argc, char **argv)
fp = mail_queue_open(*cpp, argv[optind], O_RDONLY, 0);
if (fp == 0)
msg_fatal("open queue file %s: %m", argv[optind]);
postcat(fp, buffer);
postcat(fp, buffer, flags);
if (vstream_fclose(fp))
msg_warn("close %s: %m", argv[optind]);
optind++;
@ -285,7 +303,7 @@ int main(int argc, char **argv)
while (optind < argc) {
if ((fp = vstream_fopen(argv[optind], O_RDONLY, 0)) == 0)
msg_fatal("open %s: %m", argv[optind]);
postcat(fp, buffer);
postcat(fp, buffer, flags);
if (vstream_fclose(fp))
msg_warn("close %s: %m", argv[optind]);
optind++;

View File

@ -25,8 +25,10 @@ $(PROG): $(OBJS) $(LIBS)
echo "#"; \
./$(PROG) -d) |egrep -v '^(myhostname|mydomain|mynetworks) ' >$@
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -60,7 +62,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -83,6 +85,7 @@ postconf.o: ../../include/mymalloc.h
postconf.o: ../../include/split_at.h
postconf.o: ../../include/vstring_vstream.h
postconf.o: ../../include/myflock.h
postconf.o: ../../include/inet_proto.h
postconf.o: ../../include/mynetworks.h
postconf.o: ../../include/mail_conf.h
postconf.o: ../../include/mail_dict.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: postconf.c,v 1.1.1.6 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postconf.c,v 1.1.1.7 2005/08/18 21:08:08 rpaulo Exp $ */
/*++
/* NAME
@ -13,7 +13,7 @@
/* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIparameter=value ...\fR]
/* DESCRIPTION
/* The \fBpostconf\fR command prints the actual value of
/* The \fBpostconf\fR(1) command prints the actual value of
/* \fIparameter\fR (all known parameters by default) one
/* parameter per line, changes its value, or prints other
/* information about the Postfix mail system.
@ -38,7 +38,7 @@
/* .RS
/* .IP \fBflock\fR
/* A kernel-based advisory locking method for local files only.
/* This locking method is available only on systems with a BSD
/* This locking method is available on systems with a BSD
/* compatible library.
/* .IP \fBfcntl\fR
/* A kernel-based advisory locking method for local and remote files.
@ -49,28 +49,33 @@
/* stale lock files that were left behind after abnormal termination.
/* .RE
/* .IP \fB-m\fR
/* List the names of all supported lookup table types. Postfix
/* List the names of all supported lookup table types. In Postfix
/* configuration files,
/* lookup tables are specified as \fItype\fB:\fIname\fR, where
/* \fItype\fR is one of the types listed below. The table \fIname\fR
/* syntax depends on the lookup table type.
/* syntax depends on the lookup table type as described in the
/* DATABASE_README document.
/* .RS
/* .IP \fBbtree\fR
/* A sorted, balanced tree structure.
/* This is available only on systems with support for Berkeley DB
/* This is available on systems with support for Berkeley DB
/* databases.
/* .IP \fBcdb\fR
/* A read-optimized structure with no support for incremental updates.
/* This is available on systems with support for CDB databases.
/* .IP \fBcidr\fR
/* A table that associates values with Classless Inter-Domain Routing
/* (CIDR) patterns. This is described in \fBcidr_table\fR(5).
/* .IP \fBdbm\fR
/* An indexed file type based on hashing.
/* This is available only on systems with support for DBM databases.
/* This is available on systems with support for DBM databases.
/* .IP \fBenviron\fR
/* The UNIX process environment array. The lookup key is the variable
/* name. Originally implemented for testing, someone may find this
/* useful someday.
/* .IP \fBhash\fR
/* An indexed file type based on hashing.
/* This is available only on systems with support for Berkeley DB
/* This is available on systems with support for Berkeley DB
/* databases.
/* .IP "\fBldap\fR (read-only)"
/* Perform lookups using the LDAP protocol. This is described
@ -91,24 +96,27 @@
/* .IP "\fBregexp\fR (read-only)"
/* A lookup table based on regular expressions. The file format is
/* described in \fBregexp_table\fR(5).
/* .IP \fBsdbm\fR
/* An indexed file type based on hashing.
/* This is available on systems with support for SDBM databases.
/* .IP "\fBstatic\fR (read-only)"
/* A table that always returns its name as lookup result. For example,
/* \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup
/* result.
/* .IP "\fBtcp\fR (read-only)"
/* Perform lookups using a simple request-reply protocol that is
/* described in tcp_table(5).
/* This feature is not included with Postfix 2.1.
/* described in \fBtcp_table\fR(5).
/* This feature is not included with Postfix 2.2.
/* .IP "\fBunix\fR (read-only)"
/* A limited way to query the UNIX authentication database. The
/* following tables are implemented:
/* .RS
/*. IP \fBunix:passwd.byname\fR
/* The table is the UNIX password database. The key is a login name.
/* The result is a password file entry in passwd(5) format.
/* The result is a password file entry in \fBpasswd\fR(5) format.
/* .IP \fBunix:group.byname\fR
/* The table is the UNIX group database. The key is a group name.
/* The result is a group file entry in group(5) format.
/* The result is a group file entry in \fBgroup\fR(5) format.
/* .RE
/* .RE
/* .sp
@ -133,7 +141,7 @@
/* this program.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
@ -194,6 +202,7 @@
#include <split_at.h>
#include <vstring_vstream.h>
#include <myflock.h>
#include <inet_proto.h>
/* Global library. */
@ -362,6 +371,7 @@ static const char *check_mydomainname(void)
static const char *check_mynetworks(void)
{
INET_PROTO_INFO *proto_info;
const char *junk;
if (var_inet_interfaces == 0) {
@ -376,6 +386,13 @@ static const char *check_mynetworks(void)
junk = DEF_MYNETWORKS_STYLE;
var_mynetworks_style = mystrdup(junk);
}
if (var_inet_protocols == 0) {
if ((mode & SHOW_DEFS)
|| !(junk = mail_conf_lookup_eval(VAR_INET_PROTOCOLS)))
junk = DEF_INET_PROTOCOLS;
var_inet_protocols = mystrdup(junk);
proto_info = inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
}
return (mynetworks());
}

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -75,3 +77,4 @@ postdrop.o: ../../include/mail_stream.h
postdrop.o: ../../include/cleanup_user.h
postdrop.o: ../../include/record.h
postdrop.o: ../../include/rec_type.h
postdrop.o: ../../include/user_acl.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: postdrop.c,v 1.1.1.6 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postdrop.c,v 1.1.1.7 2005/08/18 21:08:08 rpaulo Exp $ */
/*++
/* NAME
@ -8,7 +8,7 @@
/* SYNOPSIS
/* \fBpostdrop\fR [\fB-rv\fR] [\fB-c \fIconfig_dir\fR]
/* DESCRIPTION
/* The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR
/* The \fBpostdrop\fR(1) command creates a file in the \fBmaildrop\fR
/* directory and copies its standard input to the file.
/*
/* Options:
@ -54,7 +54,7 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBalternate_config_directories (empty)\fR"
/* A list of non-default Postfix configuration directories that may
/* be specified with "-c config_directory" on the command line, or
@ -74,7 +74,12 @@
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* .IP "\fBtrigger_timeout (10s)\fR"
/* The time limit for sending a trigger to a Postfix daemon (for
/* example, the pickup(8) or qmgr(8) daemon).
/* example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon).
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBauthorized_submit_users (static:anyone)\fR"
/* List of users who are authorized to submit mail with the \fBsendmail\fR(1)
/* command (and with the privileged \fBpostdrop\fR(1) helper command).
/* FILES
/* /var/spool/postfix/maildrop, maildrop queue
/* SEE ALSO
@ -129,6 +134,7 @@
#include <cleanup_user.h>
#include <record.h>
#include <rec_type.h>
#include <user_acl.h>
/* Application-specific. */
@ -145,46 +151,61 @@
* and so on.
*/
/*
* Local mail submission access list.
*/
char *var_submit_acl;
static CONFIG_STR_TABLE str_table[] = {
VAR_SUBMIT_ACL, DEF_SUBMIT_ACL, &var_submit_acl, 0, 0,
0,
};
/*
* Queue file name. Global, so that the cleanup routine can find it when
* called by the run-time error handler.
*/
static char *postdrop_path;
/* postdrop_cleanup - callback for the runtime error handler */
static void postdrop_cleanup(void)
{
/*
* This is the fatal error handler. Don't try to do anything fancy.
*/
if (postdrop_path) {
if (remove(postdrop_path))
msg_warn("uid=%ld: remove %s: %m", (long) getuid(), postdrop_path);
else if (msg_verbose)
msg_info("remove %s", postdrop_path);
postdrop_path = 0;
}
}
/* postdrop_sig - catch signal and clean up */
static void postdrop_sig(int sig)
{
/*
* Assume atomic signal() updates, even when emulated with sigaction().
* This is the fatal error handler. Don't try to do anything fancy.
*
* msg_vstream does not allocate memory, but msg_syslog may indirectly in
* syslog(), so it should not be called from a user-triggered signal
* handler.
*
* Assume atomic signal() updates, even when emulated with sigaction(). We
* use the in-kernel SIGINT handler address as an atomic variable to
* prevent nested postdrop_sig() calls. For this reason, main() must
* configure postdrop_sig() as SIGINT handler before other signal
* handlers are allowed to invoke postdrop_sig().
*/
if (signal(SIGHUP, SIG_IGN) != SIG_IGN
&& signal(SIGINT, SIG_IGN) != SIG_IGN
&& signal(SIGQUIT, SIG_IGN) != SIG_IGN
&& signal(SIGTERM, SIG_IGN) != SIG_IGN) {
postdrop_cleanup();
exit(sig);
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGTERM, SIG_IGN);
(void) signal(SIGHUP, SIG_IGN);
if (postdrop_path) {
(void) remove(postdrop_path);
postdrop_path = 0;
}
/* Future proofing. If you need exit() here then you broke Postfix. */
if (sig)
_exit(sig);
}
}
/* postdrop_cleanup - callback for the runtime error handler */
static void postdrop_cleanup(void)
{
postdrop_sig(0);
}
/* main - the main program */
int main(int argc, char **argv)
@ -205,6 +226,8 @@ int main(int argc, char **argv)
const char *error_text;
char *attr_name;
char *attr_value;
const char *errstr;
char *junk;
/*
* Be consistent with file permissions.
@ -261,6 +284,15 @@ int main(int argc, char **argv)
* perform some sanity checks on the input.
*/
mail_conf_read();
get_mail_conf_str_table(str_table);
/*
* Mail submission access control. Should this be in the user-land gate,
* or in the daemon process?
*/
if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0)
msg_fatal("User %s(%ld) is not allowed to submit mail",
errstr, (long) uid);
/*
* Stop run-away process accidents by limiting the queue file size. This
@ -284,15 +316,20 @@ int main(int argc, char **argv)
/*
* Set up signal handlers and a runtime error handler so that we can
* clean up incomplete output.
*
* postdrop_sig() uses the in-kernel SIGINT handler address as an atomic
* variable to prevent nested postdrop_sig() calls. For this reason, the
* SIGINT handler must be configured before other signal handlers are
* allowed to invoke postdrop_sig().
*/
signal(SIGPIPE, SIG_IGN);
signal(SIGXFSZ, SIG_IGN);
if (signal(SIGHUP, SIG_IGN) == SIG_DFL)
signal(SIGHUP, postdrop_sig);
signal(SIGINT, postdrop_sig);
signal(SIGQUIT, postdrop_sig);
signal(SIGTERM, postdrop_sig);
if (signal(SIGHUP, SIG_IGN) == SIG_DFL)
signal(SIGHUP, postdrop_sig);
msg_cleanup(postdrop_cleanup);
/* End of initializations. */
@ -332,7 +369,7 @@ int main(int argc, char **argv)
if (rec_type == REC_TYPE_EOF) { /* request cancelled */
mail_stream_cleanup(dst);
if (remove(postdrop_path))
msg_warn("uid=%ld: remove %s: %m", (long) getuid(), postdrop_path);
msg_warn("uid=%ld: remove %s: %m", (long) uid, postdrop_path);
else if (msg_verbose)
msg_info("remove %s", postdrop_path);
myfree(postdrop_path);
@ -391,8 +428,9 @@ int main(int argc, char **argv)
* will not be deleted after we have taken responsibility for delivery.
*/
if (postdrop_path) {
myfree(postdrop_path);
junk = postdrop_path;
postdrop_path = 0;
myfree(junk);
}
/*

View File

@ -16,8 +16,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -50,7 +52,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: postfix.c,v 1.1.1.5 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postfix.c,v 1.1.1.6 2005/08/18 21:08:15 rpaulo Exp $ */
/*++
/* NAME
@ -10,26 +10,26 @@
/* \fBpostfix\fR [\fB-Dv\fR] [\fB-c \fIconfig_dir\fR] \fIcommand\fR
/* DESCRIPTION
/* This command is reserved for the superuser. To submit mail,
/* use the Postfix \fBsendmail\fR command.
/* use the Postfix \fBsendmail\fR(1) command.
/*
/* The \fBpostfix\fR command controls the operation of the Postfix
/* mail system: start or stop the \fBmaster\fR daemon, do a health
/* The \fBpostfix\fR(1) command controls the operation of the Postfix
/* mail system: start or stop the \fBmaster\fR(8) daemon, do a health
/* check, and other maintenance.
/*
/* The \fBpostfix\fR command sets up a standardized environment and
/* The \fBpostfix\fR(1) command sets up a standardized environment and
/* runs the \fBpostfix-script\fR shell script to do the actual work.
/*
/* The following commands are implemented:
/* .IP \fBcheck\fR
/* Validate the Postfix mail system configuration. Warn about bad
/* directory/file ownership or permissions, and create missing
/* directories.
/* Warn about bad directory/file ownership or permissions,
/* and create missing directories.
/* .IP \fBstart\fR
/* Start the Postfix mail system. This also runs the configuration
/* check described above.
/* .IP \fBstop\fR
/* Stop the Postfix mail system in an orderly fashion. Running processes
/* are allowed to terminate at their earliest convenience.
/* Stop the Postfix mail system in an orderly fashion. If
/* possible, running processes are allowed to terminate at
/* their earliest convenience.
/* .sp
/* Note: in order to refresh the Postfix mail system after a
/* configuration change, do not use the \fBstart\fR and \fBstop\fR
@ -56,7 +56,9 @@
/* change the \fBmail_owner\fR or \fBsetgid_group\fR setting for an
/* already installed Postfix system.
/* .sp
/* This feature is available in Postfix 2.1 and later.
/* This feature is available in Postfix 2.1 and later. With
/* Postfix 2.0 and earlier, use "\fB/etc/postfix/post-install
/* set-permissions\fR".
/* .IP "\fBupgrade-configuration\fR \fB[\fIname\fR=\fIvalue ...\fB]\fR
/* Update the \fBmain.cf\fR and \fBmaster.cf\fR files with information
/* that Postfix needs in order to run: add or update services, and add
@ -65,7 +67,9 @@
/* Specify \fIname\fR=\fIvalue\fR to override and update specific
/* main.cf configuration parameters.
/* .sp
/* This feature is available in Postfix 2.1 and later.
/* This feature is available in Postfix 2.1 and later. With
/* Postfix 2.0 and earlier, use "\fB/etc/postfix/post-install
/* upgrade-configuration\fR".
/* .PP
/* The following options are implemented:
/* .IP "\fB-c \fIconfig_dir\fR"
@ -82,7 +86,7 @@
/* ENVIRONMENT
/* .ad
/* .fi
/* The \fBpostfix\fR command exports the following environment
/* The \fBpostfix\fR(1) command exports the following environment
/* variables before executing the \fBpostfix-script\fR file:
/* .IP \fBMAIL_CONFIG\fR
/* This is set when the -c command-line option is present.
@ -112,13 +116,13 @@
/* Postfix directories.
/* .IP "\fBsendmail_path (see 'postconf -d' output)\fR"
/* A Sendmail compatibility feature that specifies the location of
/* the Postfix sendmail(1) command.
/* the Postfix \fBsendmail\fR(1) command.
/* .IP "\fBnewaliases_path (see 'postconf -d' output)\fR"
/* Sendmail compatibility feature that specifies the location of the
/* newaliases(1) command.
/* \fBnewaliases\fR(1) command.
/* .IP "\fBmailq_path (see 'postconf -d' output)\fR"
/* Sendmail compatibility feature that specifies where the Postfix
/* mailq(1) command is installed.
/* \fBmailq\fR(1) command is installed.
/* .IP "\fBhtml_directory (see 'postconf -d' output)\fR"
/* The location of Postfix HTML files that describe how to build,
/* configure or operate a specific Postfix subsystem or feature.
@ -150,22 +154,28 @@
/* Commands:
/* postalias(1), create/update/query alias database
/* postcat(1), examine Postfix queue file
/* postconf(1), Postfix configuration utility
/* postfix(1), Postfix control program
/* postkick(1), trigger Postfix daemon
/* postlock(1), Postfix-compatible locking
/* postlog(1), Postfix-compatible logging
/* postmap(1), Postfix lookup table manager
/* postqueue(1), Postfix mail queue control
/* postsuper(1), Postfix housekeeping
/* mailq(1), Sendmail compatibility interface
/* newaliases(1), Sendmail compatibility interface
/* sendmail(1), Sendmail compatibility interface
/*
/* Postfix configuration:
/* postconf(5), Postfix configuration parameters
/* master(5), Postfix master.cf file syntax
/* postconf(5), Postfix main.cf file syntax
/*
/* Table-driven mechanisms:
/* access(5), Postfix SMTP access control table
/* aliases(5), Postfix alias database
/* header_checks(5), body_checks(5), content inspection
/* canonical(5), Postfix address rewriting
/* canonical(5), Postfix input address rewriting
/* generic(5), Postfix output address rewriting
/* header_checks(5), body_checks(5), Postfix content inspection
/* relocated(5), Users that have moved
/* transport(5), Postfix routing table
/* virtual(5), Postfix virtual aliasing
@ -174,15 +184,16 @@
/* cidr_table(5), Associate CIDR pattern with value
/* ldap_table(5), Postfix LDAP client
/* mysql_table(5), Postfix MYSQL client
/* nisplus_table(5), Postfix NIS+ client
/* pcre_table(5), Associate PCRE pattern with value
/* pgsql_table(5), Postfix PostgreSQL client
/* regexp_table(5), Associate POSIX regexp pattern with value
/* tcp_table(5), Postfix client-server table lookup
/*
/* Daemon processes:
/* anvil(8), Postfix connection/rate limiting
/* bounce(8), defer(8), trace(8), Delivery status reports
/* cleanup(8), canonicalize and enqueue message
/* discard(8), Postfix discard delivery agent
/* error(8), Postfix error delivery agent
/* flush(8), Postfix fast ETRN service
/* lmtp(8), Postfix LMTP client
@ -194,10 +205,12 @@
/* proxymap(8), Postfix lookup table proxy server
/* qmgr(8), Postfix queue manager
/* qmqpd(8), Postfix QMQP server
/* scache(8), Postfix connection cache manager
/* showq(8), list Postfix mail queue
/* smtp(8), Postfix SMTP client
/* smtpd(8), Postfix SMTP server
/* spawn(8), run non-Postfix server
/* tlsmgr(8), Postfix TLS cache and randomness manager
/* trivial-rewrite(8), Postfix address rewriting
/* verify(8), Postfix address verification
/* virtual(8), Postfix virtual delivery agent

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: postkick.c,v 1.1.1.4 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postkick.c,v 1.1.1.5 2005/08/18 21:08:15 rpaulo Exp $ */
/*++
/* NAME
@ -10,7 +10,7 @@
/* \fBpostkick\fR [\fB-c \fIconfig_dir\fR] [\fB-v\fR]
/* \fIclass service request\fR
/* DESCRIPTION
/* The \fBpostkick\fR command sends \fIrequest\fR to the
/* The \fBpostkick\fR(1) command sends \fIrequest\fR to the
/* specified \fIservice\fR over a local transport channel.
/* This command makes Postfix private IPC accessible
/* for use in, for example, shell scripts.
@ -48,12 +48,12 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBapplication_event_drain_time (100s)\fR"
/* How long the postkick(1) command waits for a request to enter the
/* How long the \fBpostkick\fR(1) command waits for a request to enter the
/* server's input buffer before giving up.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/* The location of the Postfix top-level queue directory.

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: postlock.c,v 1.1.1.3 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postlock.c,v 1.1.1.4 2005/08/18 21:08:16 rpaulo Exp $ */
/*++
/* NAME
@ -10,7 +10,7 @@
/* \fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-l \fIlock_style\fB]
/* [\fB-v\fR] \fIfile command...\fR
/* DESCRIPTION
/* The \fBpostlock\fR command locks \fIfile\fR for exclusive
/* The \fBpostlock\fR(1) command locks \fIfile\fR for exclusive
/* access, and executes \fIcommand\fR. The locking method is
/* compatible with the Postfix UNIX-style local delivery agent.
/*
@ -33,7 +33,7 @@
/* access. The command is executed directly, i.e. without
/* interpretation by a shell command interpreter.
/* DIAGNOSTICS
/* The result status is 75 (EX_TEMPFAIL) when \fBpostlock\fR
/* The result status is 75 (EX_TEMPFAIL) when \fBpostlock\fR(1)
/* could not perform the requested operation. Otherwise, the
/* exit status is the exit status from the command.
/* BUGS
@ -53,20 +53,20 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* LOCKING CONTROLS
/* .ad
/* .fi
/* .IP "\fBdeliver_lock_attempts (20)\fR"
/* The maximal number of attempts to acquire an exclusive lock on a
/* mailbox file or bounce(8) logfile.
/* mailbox file or \fBbounce\fR(8) logfile.
/* .IP "\fBdeliver_lock_delay (1s)\fR"
/* The time between attempts to acquire an exclusive lock on a mailbox
/* file or bounce(8) logfile.
/* file or \fBbounce\fR(8) logfile.
/* .IP "\fBstale_lock_time (500s)\fR"
/* The time after which a stale exclusive mailbox lockfile is removed.
/* .IP "\fBmailbox_delivery_lock (see 'postconf -d' output)\fR"
/* How to lock a UNIX-style local(8) mailbox before attempting delivery.
/* How to lock a UNIX-style \fBlocal\fR(8) mailbox before attempting delivery.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi

View File

@ -16,8 +16,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -50,7 +52,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: postlog.c,v 1.1.1.3 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postlog.c,v 1.1.1.4 2005/08/18 21:08:16 rpaulo Exp $ */
/*++
/* NAME
@ -10,12 +10,12 @@
/* \fBpostlog\fR [\fB-iv\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-p \fIpriority\fB] [\fB-t \fItag\fR] [\fItext...\fR]
/* DESCRIPTION
/* The \fBpostlog\fR command implements a Postfix-compatible logging
/* The \fBpostlog\fR(1) command implements a Postfix-compatible logging
/* interface for use in, for example, shell scripts.
/*
/* By default, \fBpostlog\fR logs the \fItext\fR given on the command
/* By default, \fBpostlog\fR(1) logs the \fItext\fR given on the command
/* line as one record. If no \fItext\fR is specified on the command
/* line, \fBpostlog\fR reads from standard input and logs each input
/* line, \fBpostlog\fR(1) reads from standard input and logs each input
/* line as one record.
/*
/* Logging is sent to \fBsyslogd\fR(8); when the standard error stream
@ -49,7 +49,7 @@
/* this program.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
update: ../../bin/$(PROG)
@ -25,7 +27,7 @@ update: ../../bin/$(PROG)
tests: test1 test2
test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-ABC1.ref
test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-uABC1.ref
./$(PROG) map.in
for key in abc ghi; \
do \
@ -34,11 +36,11 @@ test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-ABC1.ref
./$(PROG) -f map.in
for key in ABC; \
do \
./$(PROG) -fq $${key} map.in | diff map-$${key}1.ref -; \
./$(PROG) -fq $${key} map.in | diff map-u$${key}1.ref -; \
done
rm -f map.in.db
test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-ABC2.ref
test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-uABC2.ref
./$(PROG) map.in
for key in abc ghi; \
do \
@ -47,7 +49,7 @@ test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-ABC2.ref
./$(PROG) -f map.in
for key in ABC; \
do \
echo $${key} | ./$(PROG) -fq - map.in | diff map-$${key}2.ref -; \
echo $${key} | ./$(PROG) -fq - map.in | diff map-u$${key}2.ref -; \
done
rm -f map.in.db
@ -70,7 +72,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -0,0 +1 @@
DEF

View File

@ -0,0 +1 @@
ABC DEF

View File

@ -1,4 +1,4 @@
/* $NetBSD: postmap.c,v 1.1.1.7 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postmap.c,v 1.1.1.8 2005/08/18 21:08:18 rpaulo Exp $ */
/*++
/* NAME
@ -7,11 +7,11 @@
/* Postfix lookup table management
/* SYNOPSIS
/* .fi
/* \fBpostmap\fR [\fB-Nfinoprvw\fR] [\fB-c \fIconfig_dir\fR]
/* \fBpostmap\fR [\fB-Nfinoprsvw\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
/* [\fIfile_type\fR:]\fIfile_name\fR ...
/* DESCRIPTION
/* The \fBpostmap\fR command creates or queries one or more Postfix
/* The \fBpostmap\fR(1) command creates or queries one or more Postfix
/* lookup tables, or updates an existing one. The input and output
/* file formats are expected to be compatible with:
/*
@ -64,19 +64,21 @@
/* a map.
/* .IP \fB-i\fR
/* Incremental mode. Read entries from standard input and do not
/* truncate an existing database. By default, \fBpostmap\fR creates
/* truncate an existing database. By default, \fBpostmap\fR(1) creates
/* a new database from the entries in \fBfile_name\fR.
/* .IP \fB-N\fR
/* Include the terminating null character that terminates lookup keys
/* and values. By default, Postfix does whatever is the default for
/* and values. By default, \fBpostmap\fR(1) does whatever is
/* the default for
/* the host operating system.
/* .IP \fB-n\fR
/* Don't include the terminating null character that terminates lookup
/* keys and values. By default, Postfix does whatever is the default for
/* keys and values. By default, \fBpostmap\fR(1) does whatever
/* is the default for
/* the host operating system.
/* .IP \fB-o\fR
/* Do not release root privileges when processing a non-root
/* input file. By default, \fBpostmap\fR drops root privileges
/* input file. By default, \fBpostmap\fR(1) drops root privileges
/* and runs as the source file owner instead.
/* .IP \fB-p\fR
/* Do not inherit the file access permissions from the input file
@ -92,37 +94,48 @@
/* \fIkey value\fR output for each key that was found. The exit
/* status is zero when at least one of the requested keys was found.
/* .IP \fB-r\fR
/* When updating a table, do not warn about duplicate entries; silently
/* replace them.
/* When updating a table, do not complain about attempts to update
/* existing entries, and make those updates anyway.
/* .IP \fB-s\fR
/* Retrieve all database elements, and write one line of
/* \fIkey value\fR output for each element. The elements are
/* printed in database order, which is not necessarily the same
/* as the original input order.
/* This feature is available in Postfix version 2.2 and later,
/* and is not available for all database types.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
/* .IP \fB-w\fR
/* When updating a table, do not warn about duplicate entries; silently
/* ignore them.
/* When updating a table, do not complain about attempts to update
/* existing entries, and ignore those attempts.
/* .PP
/* Arguments:
/* .IP \fIfile_type\fR
/* The database type. To find out what types are supported, use
/* the "\fBpostconf -m" command.
/* the "\fBpostconf -m\fR" command.
/*
/* The \fBpostmap\fR command can query any supported file type,
/* The \fBpostmap\fR(1) command can query any supported file type,
/* but it can create only the following file types:
/* .RS
/* .IP \fBbtree\fR
/* The output file is a btree file, named \fIfile_name\fB.db\fR.
/* This is available only on systems with support for \fBdb\fR databases.
/* This is available on systems with support for \fBdb\fR databases.
/* .IP \fBcdb\fR
/* The output consists of one file, named \fIfile_name\fB.cdb\fR.
/* This is available on systems with support for \fBcdb\fR databases.
/* .IP \fBdbm\fR
/* The output consists of two files, named \fIfile_name\fB.pag\fR and
/* \fIfile_name\fB.dir\fR.
/* This is available only on systems with support for \fBdbm\fR databases.
/* This is available on systems with support for \fBdbm\fR databases.
/* .IP \fBhash\fR
/* The output file is a hashed file, named \fIfile_name\fB.db\fR.
/* This is available only on systems with support for \fBdb\fR databases.
/* This is available on systems with support for \fBdb\fR databases.
/* .IP \fBsdbm\fR
/* The output consists of two files, named \fIfile_name\fB.pag\fR and
/* \fIfile_name\fB.dir\fR.
/* This is available on systems with support for \fBsdbm\fR databases.
/* .PP
/* Use the command \fBpostconf -m\fR to find out what types of database
/* your Postfix installation can support.
/*
/* When no \fIfile_type\fR is specified, the software uses the database
/* type specified via the \fBdefault_database_type\fR configuration
/* parameter.
@ -135,8 +148,8 @@
/* No output means that no problems were detected. Duplicate entries are
/* skipped and are flagged with a warning.
/*
/* \fBpostmap\fR terminates with zero exit status in case of success
/* (including successful \fBpostmap -q\fR lookup) and terminates
/* \fBpostmap\fR(1) terminates with zero exit status in case of success
/* (including successful "\fBpostmap -q\fR" lookup) and terminates
/* with non-zero exit status in case of failure.
/* ENVIRONMENT
/* .ad
@ -151,7 +164,7 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBberkeley_db_create_buffer_size (16777216)\fR"
/* The per-table I/O buffer size for programs that create Berkeley DB
/* hash or btree tables.
@ -162,8 +175,8 @@
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBdefault_database_type (see 'postconf -d' output)\fR"
/* The default database type for use in newaliases(1), postalias(1)
/* and postmap(1) commands.
/* The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1)
/* and \fBpostmap\fR(1) commands.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (postfix)\fR"
@ -422,8 +435,8 @@ static int postmap_query(const char *map_type, const char *map_name,
map_type, map_name);
}
vstream_printf("%s\n", value);
vstream_fflush(VSTREAM_OUT);
}
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
return (value != 0);
}
@ -486,11 +499,39 @@ static int postmap_delete(const char *map_type, const char *map_name,
return (status == 0);
}
/* postmap_seq - print all map entries to stdout */
static void postmap_seq(const char *map_type, const char *map_name)
{
DICT *dict;
const char *key;
const char *value;
int func;
dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK);
for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) {
if (dict_seq(dict, func, &key, &value) != 0)
break;
if (*key == 0) {
msg_warn("table %s:%s: empty lookup key value is not allowed",
map_type, map_name);
} else if (*value == 0) {
msg_warn("table %s:%s: key %s: empty string result is not allowed",
map_type, map_name, key);
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
map_type, map_name);
}
vstream_printf("%s %s\n", key, value);
}
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
}
/* usage - explain */
static NORETURN usage(char *myname)
{
msg_fatal("usage: %s [-Nfinorvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
msg_fatal("usage: %s [-Nfinoprsvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
myname);
}
@ -506,6 +547,7 @@ int main(int argc, char **argv)
int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_KEY;
char *query = 0;
char *delkey = 0;
int sequence = 0;
int found;
/*
@ -542,7 +584,7 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "Nc:d:finopq:rvw")) > 0) {
while ((ch = GETOPT(argc, argv, "Nc:d:finopq:rsvw")) > 0) {
switch (ch) {
default:
usage(argv[0]);
@ -556,8 +598,8 @@ int main(int argc, char **argv)
msg_fatal("out of memory");
break;
case 'd':
if (query || delkey)
msg_fatal("specify only one of -q or -d");
if (sequence || query || delkey)
msg_fatal("specify only one of -s -q or -d");
delkey = optarg;
break;
case 'f':
@ -577,14 +619,19 @@ int main(int argc, char **argv)
postmap_flags &= ~POSTMAP_FLAG_SAVE_PERM;
break;
case 'q':
if (query || delkey)
msg_fatal("specify only one of -q or -d");
if (sequence || query || delkey)
msg_fatal("specify only one of -s -q or -d");
query = optarg;
break;
case 'r':
dict_flags &= ~(DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE);
dict_flags |= DICT_FLAG_DUP_REPLACE;
break;
case 's':
if (query || delkey)
msg_fatal("specify only one of -s or -q or -d");
sequence = 1;
break;
case 'v':
msg_verbose++;
break;
@ -635,6 +682,16 @@ int main(int argc, char **argv)
optind++;
}
exit(1);
} else if (sequence) {
while (optind < argc) {
if ((path_name = split_at(argv[optind], ':')) != 0) {
postmap_seq(argv[optind], path_name);
} else {
postmap_seq(var_db_type, argv[optind]);
}
exit(0);
}
exit(1);
} else { /* create/update map(s) */
if (optind + 1 > argc)
usage(argv[0]);

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -77,3 +79,5 @@ postqueue.o: ../../include/mail_flush.h
postqueue.o: ../../include/flush_clnt.h
postqueue.o: ../../include/smtp_stream.h
postqueue.o: ../../include/vstring.h
postqueue.o: ../../include/user_acl.h
postqueue.o: ../../include/valid_mailhost_addr.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: postqueue.c,v 1.1.1.6 2004/05/31 00:24:42 heas Exp $ */
/* $NetBSD: postqueue.c,v 1.1.1.7 2005/08/18 21:08:20 rpaulo Exp $ */
/*++
/* NAME
@ -12,7 +12,7 @@
/* .br
/* \fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
/* DESCRIPTION
/* The \fBpostqueue\fR program implements the Postfix user interface
/* The \fBpostqueue\fR(1) command implements the Postfix user interface
/* for queue management. It implements operations that are
/* traditionally available via the \fBsendmail\fR(1) command.
/* See the \fBpostsuper\fR(1) command for queue operations
@ -27,7 +27,7 @@
/* .IP \fB-f\fR
/* Flush the queue: attempt to deliver all queued mail.
/*
/* This option implements the traditional \fBsendmail -q\fR command,
/* This option implements the traditional "\fBsendmail -q\fR" command,
/* by contacting the Postfix \fBqmgr\fR(8) daemon.
/*
/* Warning: flushing undeliverable mail frequently will result in
@ -53,11 +53,13 @@
/* .RE
/* .IP "\fB-s \fIsite\fR"
/* Schedule immediate delivery of all mail that is queued for the named
/* \fIsite\fR. The site must be eligible for the "fast flush" service.
/* \fIsite\fR. A numerical site must be specified as a valid RFC 2821
/* address literal enclosed in [], just like in email addresses.
/* The site must be eligible for the "fast flush" service.
/* See \fBflush\fR(8) for more information about the "fast flush"
/* service.
/*
/* This option implements the traditional \fBsendmail -qR\fIsite\fR
/* This option implements the traditional "\fBsendmail -qR\fIsite\fR"
/* command, by contacting the Postfix \fBflush\fR(8) daemon.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
@ -90,7 +92,7 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBalternate_config_directories (empty)\fR"
/* A list of non-default Postfix configuration directories that may
/* be specified with "-c config_directory" on the command line, or
@ -115,7 +117,13 @@
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* .IP "\fBtrigger_timeout (10s)\fR"
/* The time limit for sending a trigger to a Postfix daemon (for
/* example, the pickup(8) or qmgr(8) daemon).
/* example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon).
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBauthorized_flush_users (static:anyone)\fR"
/* List of users who are authorized to flush the queue.
/* .IP "\fBauthorized_mailq_users (static:anyone)\fR"
/* List of users who are authorized to view the queue.
/* FILES
/* /var/spool/postfix, mail queue
/* SEE ALSO
@ -182,6 +190,8 @@
#include <mail_flush.h>
#include <flush_clnt.h>
#include <smtp_stream.h>
#include <user_acl.h>
#include <valid_mailhost_addr.h>
/* Application-specific. */
@ -211,13 +221,33 @@
*/
#define STR vstring_str
/*
* Queue manipulation access lists.
*/
char *var_flush_acl;
char *var_showq_acl;
static CONFIG_STR_TABLE str_table[] = {
VAR_FLUSH_ACL, DEF_FLUSH_ACL, &var_flush_acl, 0, 0,
VAR_SHOWQ_ACL, DEF_SHOWQ_ACL, &var_showq_acl, 0, 0,
0,
};
/* show_queue - show queue status */
static void show_queue(void)
{
const char *errstr;
char buf[VSTREAM_BUFSIZE];
VSTREAM *showq;
int n;
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
&& (errstr = check_user_acl_byuid(var_showq_acl, uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to view the mail queue",
errstr, (long) uid);
/*
* Connect to the show queue service. Terminate silently when piping into
@ -280,6 +310,14 @@ static void show_queue(void)
static void flush_queue(void)
{
const char *errstr;
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
&& (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to flush the mail queue",
errstr, (long) uid);
/*
* Trigger the flush queue service.
@ -297,6 +335,14 @@ static void flush_queue(void)
static void flush_site(const char *site)
{
int status;
const char *errstr;
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
&& (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to flush the mail queue",
errstr, (long) uid);
flush_init();
@ -407,6 +453,7 @@ int main(int argc, char **argv)
* Further initialization...
*/
mail_conf_read();
get_mail_conf_str_table(str_table);
/*
* This program is designed to be set-gid, which makes it a potential
@ -432,14 +479,10 @@ int main(int argc, char **argv)
*/
if (site_to_flush != 0) {
bad_site = 0;
if (*site_to_flush == '['
&& *(last = site_to_flush + strlen(site_to_flush) - 1) == ']') {
*last = 0;
bad_site = !valid_hostaddr(site_to_flush + 1, DONT_GRIPE);
*last = ']';
if (*site_to_flush == '[') {
bad_site = !valid_mailhost_literal(site_to_flush, DONT_GRIPE);
} else {
bad_site = (!valid_hostname(site_to_flush, DONT_GRIPE)
&& !valid_hostaddr(site_to_flush, DONT_GRIPE));
bad_site = !valid_hostname(site_to_flush, DONT_GRIPE);
}
if (bad_site)
msg_fatal_status(EX_USAGE,

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: postsuper.c,v 1.1.1.8 2004/05/31 00:24:43 heas Exp $ */
/* $NetBSD: postsuper.c,v 1.1.1.9 2005/08/18 21:08:24 rpaulo Exp $ */
/*++
/* NAME
@ -12,12 +12,13 @@
/* [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR]
/* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR]
/* DESCRIPTION
/* The \fBpostsuper\fR command does maintenance jobs on the Postfix
/* The \fBpostsuper\fR(1) command does maintenance jobs on the Postfix
/* queue. Use of the command is restricted to the superuser.
/* See the \fBpostqueue\fR command for unprivileged queue operations
/* See the \fBpostqueue\fR(1) command for unprivileged queue operations
/* such as listing or flushing the mail queue.
/*
/* By default, \fBpostsuper\fR performs the operations requested with the
/* By default, \fBpostsuper\fR(1) performs the operations
/* requested with the
/* \fB-s\fR and \fB-p\fR command-line options on all Postfix queue
/* directories - this includes the \fBincoming\fR, \fBactive\fR and
/* \fBdeferred\fR directories with mail files and the \fBbounce\fR,
@ -32,13 +33,18 @@
/* Delete one message with the named queue ID from the named
/* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and
/* \fBdeferred\fR).
/*
/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
/* queue IDs from standard input. For example, to delete all mail
/* from or to \fBuser@example.com\fR:
/* with exactly one recipient \fBuser@example.com\fR:
/* .sp
/* mailq | tail +2 | awk \'BEGIN { RS = "" } \e
/* mailq | tail +2 | awk \'BEGIN { RS = "" }
/* .ti +4
/* / user@example\e.com$/ { print $1 } \e
/* # $7=sender, $8=recipient1, $9=recipient2
/* .ti +4
/* { if ($8 == "user@example.com" && $9 == "")
/* .ti +10
/* print $1 }
/* .br
/* \' | tr -d '*!' | postsuper -d -
/* .sp
@ -55,17 +61,17 @@
/* The scenario is as follows:
/* .RS
/* .IP 1)
/* The Postfix queue manager deletes the message that \fBpostsuper\fR
/* The Postfix queue manager deletes the message that \fBpostsuper\fR(1)
/* is asked to delete, because Postfix is finished with the
/* message (it is delivered, or it is returned to the sender).
/* .IP 2)
/* New mail arrives, and the new message is given the same queue ID
/* as the message that \fBpostsuper\fR is supposed to delete.
/* as the message that \fBpostsuper\fR(1) is supposed to delete.
/* The probability for reusing a deleted queue ID is about 1 in 2**15
/* (the number of different microsecond values that the system clock
/* can distinguish within a second).
/* .IP 3)
/* \fBpostsuper\fR deletes the new message, instead of the old
/* \fBpostsuper\fR(1) deletes the new message, instead of the old
/* message that it should have deleted.
/* .RE
/* .IP "\fB-h \fIqueue_id\fR"
@ -73,6 +79,7 @@
/* Move one message with the named queue ID from the named
/* mail queue(s) (default: \fBincoming\fR, \fBactive\fR and
/* \fBdeferred\fR) to the \fBhold\fR queue.
/*
/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
/* queue IDs from standard input.
/* .sp
@ -89,9 +96,14 @@
/* Release mail that was put "on hold".
/* Move one message with the named queue ID from the named
/* mail queue(s) (default: \fBhold\fR) to the \fBdeferred\fR queue.
/*
/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
/* queue IDs from standard input.
/* .sp
/* Note: use "\fBpostsuper -r\fR" to release mail that was kept on
/* hold for a significant fraction of \fB$maximal_queue_lifetime\fR
/* or \fB$bounce_queue_lifetime\fR, or longer.
/* .sp
/* Specify \fB-H ALL\fR to release all mail that is "on hold".
/* As a safety measure, the word \fBALL\fR must be specified in upper
/* case.
@ -104,6 +116,7 @@
/* \fBdeferred\fR).
/* To requeue multiple messages, specify multiple \fB-r\fR
/* command-line options.
/*
/* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified,
/* the program reads queue IDs from standard input.
/* .sp
@ -118,7 +131,7 @@
/* mappings have changed.
/* .sp
/* Warning: Postfix queue IDs are reused.
/* There is a very small possibility that \fBpostsuper\fR requeues
/* There is a very small possibility that \fBpostsuper\fR(1) requeues
/* the wrong message file when it is executed while the Postfix mail
/* system is running, but no harm should be done.
/* .IP \fB-s\fR
@ -143,7 +156,7 @@
/* Problems are reported to the standard error stream and to
/* \fBsyslogd\fR(8).
/*
/* \fBpostsuper\fR reports the number of messages deleted with \fB-d\fR,
/* \fBpostsuper\fR(1) reports the number of messages deleted with \fB-d\fR,
/* the number of messages requeued with \fB-r\fR, and the number of
/* messages whose queue file name was fixed with \fB-s\fR. The report
/* is written to the standard error stream and to \fBsyslogd\fR(8).
@ -161,14 +174,14 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBhash_queue_depth (1)\fR"
/* The number of subdirectory levels for queue directories listed with
/* the hash_queue_names parameter.
/* .IP "\fBhash_queue_names (see 'postconf -d' output)\fR"
/* .IP "\fBhash_queue_names (deferred, defer)\fR"
/* The names of queue directories that are split across multiple
/* subdirectory levels.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
@ -932,19 +945,31 @@ static void super(const char **queues, int action)
argv_free(hash_queue_names);
}
/* fatal_exit - print warning if queue fix is incomplete */
static void fatal_exit(void)
{
if (inode_mismatch > 0 || inode_fixed > 0 || position_mismatch > 0)
msg_fatal("OPERATION INCOMPLETE -- RERUN COMMAND TO FIX THE QUEUE FIRST");
}
/* interrupted - signal handler */
static void interrupted(int unused_sig)
static void interrupted(int sig)
{
fatal_exit();
/*
* This commands requires root privileges. We therefore do not worry
* about hostile signals, and report problems via msg_warn().
*/
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGTERM, SIG_IGN);
if (inode_mismatch > 0 || inode_fixed > 0 || position_mismatch > 0)
msg_warn("OPERATION INCOMPLETE -- RERUN COMMAND TO FIX THE QUEUE FIRST");
if (sig)
_exit(sig);
}
}
/* fatal_warning - print warning if queue fix is incomplete */
static void fatal_warning(void)
{
interrupted(0);
}
int main(int argc, char **argv)
@ -1125,7 +1150,7 @@ int main(int argc, char **argv)
signal(SIGINT, interrupted);
signal(SIGQUIT, interrupted);
signal(SIGTERM, interrupted);
msg_cleanup(fatal_exit);
msg_cleanup(fatal_warning);
/*
* Sanity checks.

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: proxymap.c,v 1.1.1.5 2004/07/28 22:49:25 heas Exp $ */
/* $NetBSD: proxymap.c,v 1.1.1.6 2005/08/18 21:08:26 rpaulo Exp $ */
/*++
/* NAME
@ -8,7 +8,7 @@
/* SYNOPSIS
/* \fBproxymap\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBproxymap\fR server provides read-only table
/* The \fBproxymap\fR(8) server provides read-only table
/* lookup service to Postfix processes. The purpose
/* of the service is:
/* .IP \(bu
@ -34,7 +34,7 @@
/* The total number of connections is limited by the number of
/* proxymap server processes.
/* .PP
/* The proxymap server implements the following requests:
/* The \fBproxymap\fR(8) server implements the following requests:
/* .IP "\fBopen\fR \fImaptype:mapname flags\fR"
/* Open the table with type \fImaptype\fR and name \fImapname\fR,
/* as controlled by \fIflags\fR. The reply includes the \fImaptype\fR
@ -53,40 +53,47 @@
/* SERVER PROCESS MANAGEMENT
/* .ad
/* .fi
/* \fBproxymap\fR servers run under control by the Postfix \fBmaster\fR
/* \fBproxymap\fR(8) servers run under control by the Postfix
/* \fBmaster\fR(8)
/* server. Each server can handle multiple simultaneous connections.
/* When all servers are busy while a client connects, the \fBmaster\fR
/* creates a new \fBproxymap\fR server process, provided that the
/* When all servers are busy while a client connects, the \fBmaster\fR(8)
/* creates a new \fBproxymap\fR(8) server process, provided that the
/* process limit is not exceeded.
/* Each server terminates after serving at least \fB$max_use\fR clients
/* or after \fB$max_idle\fR seconds of idle time.
/* SECURITY
/* .ad
/* .fi
/* The proxymap server opens only tables that are approved via the
/* The \fBproxymap\fR(8) server opens only tables that are approved via the
/* \fBproxy_read_maps\fR configuration parameter, does not talk to
/* users, and can run at fixed low privilege, chrooted or not.
/* However, running the proxymap server chrooted severely limits
/* usability, because it can open only chrooted tables.
/*
/* The proxymap server is not a trusted daemon process, and must
/* The \fBproxymap\fR(8) server is not a trusted daemon process, and must
/* not be used to look up sensitive information such as user or
/* group IDs, mailbox file/directory names or external commands.
/*
/* In Postfix version 2.2 and later, the proxymap client recognizes
/* requests to access a table for security-sensitive purposes,
/* and opens the table directly. This allows the same main.cf
/* setting to be used by sensitive and non-sensitive processes.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
/* The proxymap server provides service to multiple clients,
/* The \fBproxymap\fR(8) server provides service to multiple clients,
/* and must therefore not be used for tables that have high-latency
/* lookups.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* On busy mail systems a long time may pass before proxymap(8) relevant
/* On busy mail systems a long time may pass before
/* \fBproxymap\fR(8) relevant
/* changes to \fBmain.cf\fR are picked up. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
@ -107,7 +114,18 @@
/* .IP "\fBprocess_name (read-only)\fR"
/* The process name of a Postfix command or daemon process.
/* .IP "\fBproxy_read_maps (see 'postconf -d' output)\fR"
/* The lookup tables that the proxymap(8) server is allowed to access.
/* The lookup tables that the \fBproxymap\fR(8) server is allowed to access.
/* SEE ALSO
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* README FILES
/* .ad
/* .fi
/* Use "\fBpostconf readme_directory\fR" or
/* "\fBpostconf html_directory\fR" to locate this information.
/* .na
/* .nf
/* DATABASE_README, Postfix lookup table overview
/* LICENSE
/* .ad
/* .fi

View File

@ -21,8 +21,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -53,7 +55,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -157,6 +159,9 @@ qmgr_entry.o: ../../include/events.h
qmgr_entry.o: ../../include/vstream.h
qmgr_entry.o: ../../include/vbuf.h
qmgr_entry.o: ../../include/mail_params.h
qmgr_entry.o: ../../include/deliver_request.h
qmgr_entry.o: ../../include/vstring.h
qmgr_entry.o: ../../include/recipient_list.h
qmgr_entry.o: qmgr.h
qmgr_entry.o: ../../include/scan_dir.h
qmgr_job.o: qmgr_job.c
@ -198,6 +203,7 @@ qmgr_message.o: ../../include/mail_proto.h
qmgr_message.o: ../../include/iostuff.h
qmgr_message.o: ../../include/attr.h
qmgr_message.o: ../../include/qmgr_user.h
qmgr_message.o: ../../include/split_addr.h
qmgr_message.o: ../../include/rewrite_clnt.h
qmgr_message.o: ../../include/resolve_clnt.h
qmgr_message.o: qmgr.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr.c,v 1.1.1.7 2004/07/28 22:49:25 heas Exp $ */
/* $NetBSD: qmgr.c,v 1.1.1.8 2005/08/18 21:08:27 rpaulo Exp $ */
/*++
/* NAME
@ -8,7 +8,7 @@
/* SYNOPSIS
/* \fBqmgr\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBqmgr\fR daemon awaits the arrival of incoming mail
/* The \fBqmgr\fR(8) daemon awaits the arrival of incoming mail
/* and arranges for its delivery via Postfix delivery processes.
/* The actual mail routing strategy is delegated to the
/* \fBtrivial-rewrite\fR(8) daemon.
@ -21,10 +21,10 @@
/* MAIL QUEUES
/* .ad
/* .fi
/* The \fBqmgr\fR daemon maintains the following queues:
/* The \fBqmgr\fR(8) daemon maintains the following queues:
/* .IP \fBincoming\fR
/* Inbound mail from the network, or mail picked up by the
/* local \fBpickup\fR agent from the \fBmaildrop\fR directory.
/* local \fBpickup\fR(8) daemon from the \fBmaildrop\fR directory.
/* .IP \fBactive\fR
/* Messages that the queue manager has opened for delivery. Only
/* a limited number of messages is allowed to enter the \fBactive\fR
@ -41,7 +41,7 @@
/* DELIVERY STATUS REPORTS
/* .ad
/* .fi
/* The \fBqmgr\fR daemon keeps an eye on per-message delivery status
/* The \fBqmgr\fR(8) daemon keeps an eye on per-message delivery status
/* reports in the following directories. Each status report file has
/* the same name as the corresponding message file:
/* .IP \fBbounce\fR
@ -55,7 +55,7 @@
/* Postfix "\fBsendmail -v\fR" or "\fBsendmail -bv\fR" command.
/* These files are maintained by the \fBtrace\fR(8) daemon.
/* .PP
/* The \fBqmgr\fR daemon is responsible for asking the
/* The \fBqmgr\fR(8) daemon is responsible for asking the
/* \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemons to
/* send delivery reports.
/* STRATEGIES
@ -115,7 +115,7 @@
/* servers that should not go away forever. The action is to start
/* an incoming queue scan.
/* .PP
/* The \fBqmgr\fR daemon reads an entire buffer worth of triggers.
/* The \fBqmgr\fR(8) daemon reads an entire buffer worth of triggers.
/* Multiple identical trigger requests are collapsed into one, and
/* trigger requests are sorted so that \fBA\fR and \fBF\fR precede
/* \fBD\fR and \fBI\fR. Thus, in order to force a deferred queue run,
@ -124,13 +124,13 @@
/* STANDARDS
/* .ad
/* .fi
/* None. The \fBqmgr\fR daemon does not interact with the outside world.
/* None. The \fBqmgr\fR(8) daemon does not interact with the outside world.
/* SECURITY
/* .ad
/* .fi
/* The \fBqmgr\fR daemon is not security sensitive. It reads
/* The \fBqmgr\fR(8) daemon is not security sensitive. It reads
/* single-character messages from untrusted local users, and thus may
/* be susceptible to denial of service attacks. The \fBqmgr\fR daemon
/* be susceptible to denial of service attacks. The \fBqmgr\fR(8) daemon
/* does not talk to the outside world, and it can be run at fixed low
/* privilege in a chrooted environment.
/* DIAGNOSTICS
@ -142,17 +142,18 @@
/* the postmaster is notified of bounces and of other trouble.
/* BUGS
/* A single queue manager process has to compete for disk access with
/* multiple front-end processes such as \fBsmtpd\fR. A sudden burst of
/* multiple front-end processes such as \fBcleanup\fR(8). A sudden burst of
/* inbound mail can negatively impact outbound delivery rates.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are not picked up automatically as qmgr(8)
/* processes are persistent. Use the \fBpostfix reload\fR command after
/* Changes to \fBmain.cf\fR are not picked up automatically
/* as \fBqmgr\fR(8)
/* is a persistent process. Use the "\fBpostfix reload\fR" command after
/* a configuration change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/*
/* In the text below, \fItransport\fR is the first field in a
/* \fBmaster.cf\fR entry.
@ -286,8 +287,9 @@
/* trivial-rewrite(8), address routing
/* bounce(8), delivery status reports
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* master(8), process manager
/* syslogd(8) system logging
/* syslogd(8), system logging
/* README FILES
/* .ad
/* .fi
@ -547,10 +549,15 @@ static void qmgr_post_init(char *name, char **unused_argv)
* Sanity check.
*/
if (var_qmgr_rcpt_limit < var_qmgr_active_limit) {
msg_warn("%s is smaller than %s",
VAR_QMGR_RCPT_LIMIT, VAR_QMGR_ACT_LIMIT);
msg_warn("%s is smaller than %s - adjusting %s",
VAR_QMGR_RCPT_LIMIT, VAR_QMGR_ACT_LIMIT, VAR_QMGR_RCPT_LIMIT);
var_qmgr_rcpt_limit = var_qmgr_active_limit;
}
if (var_dsn_queue_time > var_max_queue_time) {
msg_warn("%s is larger than %s - adjusting %s",
VAR_DSN_QUEUE_TIME, VAR_MAX_QUEUE_TIME, VAR_DSN_QUEUE_TIME);
var_dsn_queue_time = var_max_queue_time;
}
/*
* This routine runs after the skeleton code has entered the chroot jail.

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr.h,v 1.1.1.5 2004/05/31 00:24:44 heas Exp $ */
/* $NetBSD: qmgr.h,v 1.1.1.6 2005/08/18 21:08:32 rpaulo Exp $ */
/*++
/* NAME
@ -178,6 +178,8 @@ struct QMGR_ENTRY_LIST {
};
struct QMGR_QUEUE {
int dflags; /* delivery request options */
time_t last_done; /* last delivery completion */
char *name; /* domain name or address */
char *nexthop; /* domain name */
int todo_refcount; /* queue entries (todo list) */
@ -283,6 +285,10 @@ struct QMGR_MESSAGE {
char *client_addr; /* client address */
char *client_proto; /* client protocol */
char *client_helo; /* helo parameter */
char *sasl_method; /* SASL method */
char *sasl_username; /* SASL user name */
char *sasl_sender; /* SASL sender */
char *rewrite_context; /* address qualification */
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
int rcpt_count; /* used recipient slots */
int rcpt_limit; /* maximum read in-core */

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_deliver.c,v 1.1.1.7 2004/05/31 00:24:44 heas Exp $ */
/* $NetBSD: qmgr_deliver.c,v 1.1.1.8 2005/08/18 21:08:34 rpaulo Exp $ */
/*++
/* NAME
@ -150,6 +150,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
}
flags = message->tflags
| entry->queue->dflags
| (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT);
attr_print(stream, ATTR_FLAG_MORE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
@ -167,6 +168,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_entry.c,v 1.1.1.4 2004/05/31 00:24:44 heas Exp $ */
/* $NetBSD: qmgr_entry.c,v 1.1.1.5 2005/08/18 21:08:35 rpaulo Exp $ */
/*++
/* NAME
@ -94,6 +94,7 @@
/* Global library. */
#include <mail_params.h>
#include <deliver_request.h> /* opportunistic session caching */
/* Application-specific. */
@ -103,6 +104,7 @@
QMGR_ENTRY *qmgr_entry_select(QMGR_PEER *peer)
{
char *myname = "qmgr_entry_select";
QMGR_ENTRY *entry;
QMGR_QUEUE *queue;
@ -114,6 +116,59 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_PEER *peer)
queue->busy_refcount++;
QMGR_LIST_UNLINK(peer->entry_list, QMGR_ENTRY *, entry, peer_peers);
peer->job->selected_entries++;
/*
* With opportunistic session caching, the delivery agent must not
* only 1) save a session upon completion, but also 2) reuse a cached
* session upon the next delivery request. In order to not miss out
* on 2), we have to make caching sticky or else we get silly
* behavior when the in-memory queue drains. Specifically, new
* connections must not be made as long as cached connections exist.
*
* Safety: don't enable opportunistic session caching unless the queue
* manager is able to schedule concurrent or back-to-back deliveries
* (we need to recognize back-to-back deliveries for transports with
* concurrency 1).
*
* XXX It would be nice if we could say "try to reuse a cached
* connection, but don't bother saving it when you're done". As long
* as we can't, we must not turn off session caching too early.
*/
#define CONCURRENT_OR_BACK_TO_BACK_DELIVERY() \
(queue->busy_refcount > 1 || BACK_TO_BACK_DELIVERY())
#define BACK_TO_BACK_DELIVERY() \
(queue->last_done + 1 >= event_time())
/*
* Turn on session caching after we get up to speed. Don't enable
* session caching just because we have concurrent deliveries. This
* prevents unnecessary session caching when we have a burst of mail
* <= the initial concurrency limit.
*/
if ((queue->dflags & DEL_REQ_FLAG_SCACHE) == 0) {
if (BACK_TO_BACK_DELIVERY()) {
if (msg_verbose)
msg_info("%s: allowing on-demand session caching for %s",
myname, queue->name);
queue->dflags |= DEL_REQ_FLAG_SCACHE;
}
}
/*
* Turn off session caching when concurrency drops and we're running
* out of steam. This is what prevents from turning off session
* caching too early, and from making new connections while old ones
* are still cached.
*/
else {
if (!CONCURRENT_OR_BACK_TO_BACK_DELIVERY()) {
if (msg_verbose)
msg_info("%s: disallowing on-demand session caching for %s",
myname, queue->name);
queue->dflags &= ~DEL_REQ_FLAG_SCACHE;
}
}
}
return (entry);
}
@ -220,6 +275,11 @@ void qmgr_entry_done(QMGR_ENTRY *entry, int which)
if (peer->refcount == 0)
qmgr_peer_free(peer);
/*
* Maintain back-to-back delivery status.
*/
queue->last_done = event_time();
/*
* When the in-core queue for this site is empty and when this site is
* not dead, discard the in-core queue. When this site is dead, but the

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmgr_queue.c,v 1.1.1.4 2004/05/31 00:24:44 heas Exp $ */
/* $NetBSD: qmgr_queue.c,v 1.1.1.5 2005/08/18 21:08:40 rpaulo Exp $ */
/*++
/* NAME
@ -183,6 +183,7 @@ void qmgr_queue_throttle(QMGR_QUEUE *queue, const char *reason)
queue->reason = mystrdup(reason);
event_request_timer(qmgr_queue_unthrottle_wrapper,
(char *) queue, var_min_backoff_time);
queue->dflags = 0;
}
}
@ -233,6 +234,8 @@ QMGR_QUEUE *qmgr_queue_create(QMGR_TRANSPORT *transport, const char *name,
queue = (QMGR_QUEUE *) mymalloc(sizeof(QMGR_QUEUE));
qmgr_queue_count++;
queue->dflags = 0;
queue->last_done = 0;
queue->name = mystrdup(name);
queue->nexthop = mystrdup(nexthop);
queue->todo_refcount = 0;

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libdns.a ../../lib/
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -58,7 +60,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -100,12 +102,19 @@ qmqpd_peer.o: qmqpd_peer.c
qmqpd_peer.o: ../../include/sys_defs.h
qmqpd_peer.o: ../../include/msg.h
qmqpd_peer.o: ../../include/mymalloc.h
qmqpd_peer.o: ../../include/valid_hostname.h
qmqpd_peer.o: ../../include/stringops.h
qmqpd_peer.o: ../../include/vstring.h
qmqpd_peer.o: ../../include/vbuf.h
qmqpd_peer.o: qmqpd.h
qmqpd_peer.o: ../../include/myaddrinfo.h
qmqpd_peer.o: ../../include/sock_addr.h
qmqpd_peer.o: ../../include/inet_proto.h
qmqpd_peer.o: ../../include/mail_proto.h
qmqpd_peer.o: ../../include/vstream.h
qmqpd_peer.o: ../../include/iostuff.h
qmqpd_peer.o: ../../include/attr.h
qmqpd_peer.o: ../../include/valid_mailhost_addr.h
qmqpd_peer.o: ../../include/valid_hostname.h
qmqpd_peer.o: qmqpd.h
qmqpd_peer.o: ../../include/mail_stream.h
qmqpd_state.o: qmqpd_state.c
qmqpd_state.o: ../../include/sys_defs.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmqpd.c,v 1.1.1.6 2004/05/31 00:24:45 heas Exp $ */
/* $NetBSD: qmqpd.c,v 1.1.1.7 2005/08/18 21:08:43 rpaulo Exp $ */
/*++
/* NAME
@ -37,12 +37,12 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically, as qmqpd(8)
/* Changes to \fBmain.cf\fR are picked up automatically, as \fBqmqpd\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* CONTENT INSPECTION CONTROLS
/* .ad
/* .fi
@ -51,7 +51,7 @@
/* it is queued.
/* .IP "\fBreceive_override_options (empty)\fR"
/* Enable or disable recipient validation, built-in content
/* filtering, or address rewriting.
/* filtering, or address mapping.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@ -117,7 +117,7 @@
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* .IP "\fBverp_delimiter_filter (-=+)\fR"
/* The characters Postfix accepts as VERP delimiter characters on the
/* Postfix sendmail(1) command line and in SMTP commands.
/* Postfix \fBsendmail\fR(1) command line and in SMTP commands.
/* SEE ALSO
/* http://cr.yp.to/proto/qmqp.html, QMQP protocol
/* cleanup(8), message canonicalization
@ -236,12 +236,8 @@ static void qmqpd_open_file(QMQPD_STATE *state)
/*
* Connect to the cleanup server. Log client name/address with queue ID.
*/
cleanup_flags = CLEANUP_FLAG_MASK_EXTERNAL;
if (qmqpd_input_transp_mask & INPUT_TRANSP_ADDRESS_MAPPING)
cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK);
if (qmqpd_input_transp_mask & INPUT_TRANSP_HEADER_BODY)
cleanup_flags &= ~CLEANUP_FLAG_FILTER;
cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL,
qmqpd_input_transp_mask);
state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (state->dest == 0
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
@ -325,7 +321,7 @@ static void qmqpd_write_attributes(QMQPD_STATE *state)
MAIL_ATTR_CLIENT_NAME, state->name);
if (IS_AVAIL_CLIENT_ADDR(state->addr))
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_CLIENT_ADDR, state->addr);
MAIL_ATTR_CLIENT_ADDR, state->rfc_addr);
if (IS_AVAIL_CLIENT_NAMADDR(state->namaddr))
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ORIGIN, state->namaddr);
@ -404,7 +400,7 @@ static void qmqpd_write_content(QMQPD_STATE *state)
*/
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
rec_fprintf(state->cleanup, REC_TYPE_NORM, "Received: from %s (%s [%s])",
state->name, state->name, state->addr);
state->name, state->name, state->rfc_addr);
if (state->rcpt_count == 1 && state->recipient) {
rec_fprintf(state->cleanup, REC_TYPE_NORM,
"\tby %s (%s) with %s id %s",

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmqpd.h,v 1.1.1.3 2004/05/31 00:24:45 heas Exp $ */
/* $NetBSD: qmqpd.h,v 1.1.1.4 2005/08/18 21:08:43 rpaulo Exp $ */
/*++
/* NAME
@ -38,6 +38,7 @@ typedef struct {
char *name; /* client name */
char *addr; /* client IP address */
char *namaddr; /* name[addr] */
char *rfc_addr; /* RFC 2821 client IP address */
char *queue_id; /* queue file ID */
VSTREAM *cleanup; /* cleanup server */
MAIL_STREAM *dest; /* cleanup server */

View File

@ -1,4 +1,4 @@
/* $NetBSD: qmqpd_peer.c,v 1.1.1.3 2004/05/31 00:24:45 heas Exp $ */
/* $NetBSD: qmqpd_peer.c,v 1.1.1.4 2005/08/18 21:08:44 rpaulo Exp $ */
/*++
/* NAME
@ -28,7 +28,7 @@
/* .IP namaddr
/* String of the form: "name[addr]".
/* .PP
/* qmqpd_peer_reset() releases memory allocate by qmqpd_peer_init().
/* qmqpd_peer_reset() releases memory allocated by qmqpd_peer_init().
/* LICENSE
/* .ad
/* .fi
@ -51,36 +51,19 @@
#include <netdb.h>
#include <string.h>
/*
* Older systems don't have h_errno. Even modern systems don't have
* hstrerror().
*/
#ifdef NO_HERRNO
static int h_errno = TRY_AGAIN;
#define HSTRERROR(err) "Host not found"
#else
#define HSTRERROR(err) (\
err == TRY_AGAIN ? "Host not found, try again" : \
err == HOST_NOT_FOUND ? "Host not found" : \
err == NO_DATA ? "Host name has no address" : \
err == NO_RECOVERY ? "Name server failure" : \
strerror(errno) \
)
#endif
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <valid_hostname.h>
#include <stringops.h>
#include <myaddrinfo.h>
#include <sock_addr.h>
#include <inet_proto.h>
/* Global library. */
#include <mail_proto.h>
#include <valid_mailhost_addr.h>
/* Application-specific. */
@ -90,16 +73,19 @@ static int h_errno = TRY_AGAIN;
void qmqpd_peer_init(QMQPD_STATE *state)
{
struct sockaddr_in sin;
SOCKADDR_SIZE len = sizeof(sin);
struct hostent *hp;
int i;
char *myname = "qmqpd_peer_init";
struct sockaddr_storage ss;
struct sockaddr *sa;
SOCKADDR_SIZE sa_len;
INET_PROTO_INFO *proto_info = inet_proto_info();
sa = (struct sockaddr *) & ss;
sa_len = sizeof(ss);
/*
* Look up the peer address information.
*/
if (getpeername(vstream_fileno(state->client),
(struct sockaddr *) & sin, &len) >= 0) {
if (getpeername(vstream_fileno(state->client), sa, &sa_len) >= 0) {
errno = 0;
}
@ -107,54 +93,130 @@ void qmqpd_peer_init(QMQPD_STATE *state)
* If peer went away, give up.
*/
if (errno == ECONNRESET || errno == ECONNABORTED) {
state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
state->addr = mystrdup(CLIENT_ATTR_UNKNOWN);
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
}
/*
* Look up and "verify" the client hostname.
* Convert the client address to printable address and hostname.
*/
else if (errno == 0 && sin.sin_family == AF_INET) {
state->addr = mystrdup(inet_ntoa(sin.sin_addr));
hp = gethostbyaddr((char *) &(sin.sin_addr),
sizeof(sin.sin_addr), AF_INET);
if (hp == 0) {
state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
else if (errno == 0
&& strchr((char *) proto_info->sa_family_list, sa->sa_family)) {
MAI_HOSTNAME_STR client_name;
MAI_HOSTADDR_STR client_addr;
int aierr;
char *colonp;
/*
* Convert the client address to printable form.
*/
if ((aierr = sockaddr_to_hostaddr(sa, sa_len, &client_addr,
(MAI_SERVPORT_STR *) 0, 0)) != 0)
msg_fatal("%s: cannot convert client address to string: %s",
myname, MAI_STRERROR(aierr));
/*
* We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
* but only if IPv4 support is enabled (why would anyone want to turn
* it off)? With IPv4 support enabled we have no need for the IPv6
* form in logging, hostname verification and access checks.
*/
#ifdef HAS_IPV6
if (sa->sa_family == AF_INET6) {
if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
&& IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
&& (colonp = strrchr(client_addr.buf, ':')) != 0) {
struct addrinfo *res0;
if (msg_verbose > 1)
msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
myname, client_addr.buf, colonp + 1);
state->addr = mystrdup(colonp + 1);
state->rfc_addr = mystrdup(colonp + 1);
aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
if (aierr)
msg_fatal("%s: cannot convert %s from string to binary: %s",
myname, state->addr, MAI_STRERROR(aierr));
sa_len = res0->ai_addrlen;
memcpy((char *) sa, res0->ai_addr, sa_len);
freeaddrinfo(res0);
}
/*
* Following RFC 2821 section 4.1.3, an IPv6 address literal gets
* a prefix of 'IPv6:'. We do this consistently for all IPv6
* addresses that that appear in headers or envelopes. The fact
* that valid_mailhost_addr() enforces the form helps of course.
* We use the form without IPV6: prefix when doing access
* control, or when accessing the connection cache.
*/
else {
state->addr = mystrdup(client_addr.buf);
state->rfc_addr =
concatenate(IPV6_COL, client_addr.buf, (char *) 0);
}
}
/*
* An IPv4 address is in dotted quad decimal form.
*/
else
#endif
{
state->addr = mystrdup(client_addr.buf);
state->rfc_addr = mystrdup(client_addr.buf);
}
/*
* Look up and sanity check the client hostname.
*
* It is unsafe to allow numeric hostnames, especially because there
* exists pressure to turn off the name->addr double check. In that
* case an attacker could trivally bypass access restrictions.
*
* sockaddr_to_hostname() already rejects malformed or numeric names.
*/
#define REJECT_PEER_NAME(state) { \
myfree(state->name); \
state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
}
if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
} else {
state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
struct addrinfo *res0;
struct addrinfo *res;
state->name = mystrdup(client_name.buf);
/*
* Reject the hostname if it does not list the peer address.
*/
#define REJECT_PEER_NAME(state) { \
myfree(state->name); \
state->name = mystrdup(CLIENT_ATTR_UNKNOWN); \
}
hp = gethostbyname(state->name); /* clobbers hp->name!! */
if (hp == 0) {
aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0);
if (aierr) {
msg_warn("%s: hostname %s verification failed: %s",
state->addr, state->name, HSTRERROR(h_errno));
REJECT_PEER_NAME(state);
} else if (hp->h_length != sizeof(sin.sin_addr)) {
msg_warn("%s: hostname %s verification failed: bad address size %d",
state->addr, state->name, hp->h_length);
state->addr, state->name, MAI_STRERROR(aierr));
REJECT_PEER_NAME(state);
} else {
for (i = 0; /* void */ ; i++) {
if (hp->h_addr_list[i] == 0) {
for (res = res0; /* void */ ; res = res->ai_next) {
if (res == 0) {
msg_warn("%s: address not listed for hostname %s",
state->addr, state->name);
REJECT_PEER_NAME(state);
break;
}
if (memcmp(hp->h_addr_list[i],
(char *) &sin.sin_addr,
sizeof(sin.sin_addr)) == 0)
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
msg_info("skipping address family %d for host %s",
res->ai_family, state->name);
continue;
}
if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
break; /* keep peer name */
}
freeaddrinfo(res0);
}
}
}
@ -166,6 +228,7 @@ void qmqpd_peer_init(QMQPD_STATE *state)
else {
state->name = mystrdup("localhost");
state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
}
/*
@ -182,4 +245,5 @@ void qmqpd_peer_reset(QMQPD_STATE *state)
myfree(state->name);
myfree(state->addr);
myfree(state->namaddr);
myfree(state->rfc_addr);
}

72
gnu/dist/postfix/src/scache/Makefile.in vendored Normal file
View File

@ -0,0 +1,72 @@
SHELL = /bin/sh
SRCS = scache.c
OBJS = scache.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
PROG = scache
INC_DIR = ../../include
LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
.c.o:; $(CC) $(CFLAGS) -c $*.c
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
tests: test
update: ../../libexec/$(PROG)
../../libexec/$(PROG): $(PROG)
cp $(PROG) ../../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
lint:
lint $(DEFS) $(SRCS) $(LINTFIX)
clean:
rm -f *.o *core $(PROG) $(TESTPROG) junk
rm -rf printfck
tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend'
scache.o: scache.c
scache.o: ../../include/sys_defs.h
scache.o: ../../include/msg.h
scache.o: ../../include/iostuff.h
scache.o: ../../include/htable.h
scache.o: ../../include/ring.h
scache.o: ../../include/events.h
scache.o: ../../include/mail_params.h
scache.o: ../../include/mail_proto.h
scache.o: ../../include/vstream.h
scache.o: ../../include/vbuf.h
scache.o: ../../include/attr.h
scache.o: ../../include/scache.h
scache.o: ../../include/vstring.h
scache.o: ../../include/mail_server.h
scache.o: ../../include/mail_conf.h

544
gnu/dist/postfix/src/scache/scache.c vendored Normal file
View File

@ -0,0 +1,544 @@
/* $NetBSD: scache.c,v 1.1.1.1 2005/08/18 21:11:11 rpaulo Exp $ */
/*++
/* NAME
/* scache 8
/* SUMMARY
/* Postfix shared connection cache server
/* SYNOPSIS
/* \fBscache\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBscache\fR(8) server maintains a shared multi-connection
/* cache. This information can be used by, for example, Postfix
/* SMTP clients or other Postfix delivery agents.
/*
/* The connection cache is organized into logical destination
/* names, physical endpoint names, and connections.
/*
/* As a specific example, logical SMTP destinations specify
/* (transport, domain, port), and physical SMTP endpoints
/* specify (transport, IP address, port). An SMTP connection
/* may be saved after a successful mail transaction.
/*
/* In the general case, one logical destination may refer to
/* zero or more physical endpoints, one physical endpoint may
/* be referenced by zero or more logical destinations, and
/* one endpoint may refer to zero or more connections.
/*
/* The exact syntax of a logical destination or endpoint name
/* is application dependent; the \fBscache\fR(8) server does
/* not care. A connection is stored as a file descriptor together
/* with application-dependent information that is needed to
/* re-activate a connection object. Again, the \fBscache\fR(8)
/* server is completely unaware of the details of that
/* information.
/*
/* All information is stored with a finite time to live (ttl).
/* The connection cache daemon terminates when no client is
/* connected for \fBmax_idle\fR time units.
/*
/* This server implements the following requests:
/* .IP "\fBsave_endp\fI ttl endpoint endpoint_properties file_descriptor\fR"
/* Save the specified file descriptor and connection property data
/* under the specified endpoint name. The endpoint properties
/* are used by the client to re-activate a passivated connection
/* object.
/* .IP "\fBfind_endp\fI endpoint\fR"
/* Look up cached properties and a cached file descriptor for the
/* specified endpoint.
/* .IP "\fBsave_dest\fI ttl destination destination_properties endpoint\fR"
/* Save the binding between a logical destination and an
/* endpoint under the destination name, together with destination
/* specific connection properties. The destination properties
/* are used by the client to re-activate a passivated connection
/* object.
/* .IP "\fBfind_dest\fI destination\fR"
/* Look up cached destination properties, cached endpoint properties,
/* and a cached file descriptor for the specified logical destination.
/* SECURITY
/* .ad
/* .fi
/* The \fBscache\fR(8) server is not security-sensitive. It does not
/* talk to the network, and it does not talk to local users.
/* The \fBscache\fR(8) server can run chrooted at fixed low privilege.
/*
/* The \fBscache\fR(8) server is not a trusted process. It must
/* not be used to store information that is security sensitive.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
/* The session cache cannot be shared among multiple machines.
/*
/* When a connection expires from the cache, it is closed without
/* the appropriate protocol specific handshake.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically as \fBscache\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
/* RESOURCE CONTROLS
/* .ad
/* .fi
/* .IP "\fBconnection_cache_ttl_limit (2s)\fR"
/* The maximal time-to-live value that the \fBscache\fR(8) connection
/* cache server
/* allows.
/* .IP "\fBconnection_cache_status_update_time (600s)\fR"
/* How frequently the \fBscache\fR(8) server logs usage statistics with
/* connection cache hit and miss rates for logical destinations and for
/* physical endpoints.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBdaemon_timeout (18000s)\fR"
/* How much time a Postfix daemon process may take to handle a
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBipc_timeout (3600s)\fR"
/* The time limit for sending or receiving information over an internal
/* communication channel.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process
/* waits for the next service request before exiting.
/* .IP "\fBprocess_id (read-only)\fR"
/* The process ID of a Postfix command or daemon process.
/* .IP "\fBprocess_name (read-only)\fR"
/* The process name of a Postfix command or daemon process.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (postfix)\fR"
/* The mail system name that is prepended to the process name in syslog
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* SEE ALSO
/* smtp(8), SMTP client
/* postconf(5), configuration parameters
/* master(8), process manager
/* syslogd(8), system logging
/* README FILES
/* .ad
/* .fi
/* Use "\fBpostconf readme_directory\fR" or
/* "\fBpostconf html_directory\fR" to locate this information.
/* .na
/* .nf
/* CONNECTION_CACHE_README, Postfix connection cache
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* HISTORY
/* This service was introduced with Postfix version 2.2.
/* 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 <time.h>
/* Utility library. */
#include <msg.h>
#include <iostuff.h>
#include <htable.h>
#include <ring.h>
#include <events.h>
/* Global library. */
#include <mail_params.h>
#include <mail_proto.h>
#include <scache.h>
/* Single server skeleton. */
#include <mail_server.h>
#include <mail_conf.h>
/* Application-specific. */
/*
* Tunable parameters.
*/
int var_scache_ttl_lim;
int var_scache_stat_time;
/*
* Request parameters.
*/
static VSTRING *scache_request;
static VSTRING *scache_dest_label;
static VSTRING *scache_dest_prop;
static VSTRING *scache_endp_label;
static VSTRING *scache_endp_prop;
#ifdef CANT_WRITE_BEFORE_SENDING_FD
static VSTRING *scache_dummy;
#endif
/*
* Session cache instance.
*/
static SCACHE *scache;
/*
* Statistics.
*/
static int scache_dest_hits;
static int scache_dest_miss;
static int scache_dest_count;
static int scache_endp_hits;
static int scache_endp_miss;
static int scache_endp_count;
static int scache_sess_count;
time_t scache_start_time;
/*
* Silly little macros.
*/
#define STR(x) vstring_str(x)
#define VSTREQ(x,y) (strcmp(STR(x),y) == 0)
/* scache_save_endp_service - protocol to save endpoint->stream binding */
static void scache_save_endp_service(VSTREAM *client_stream)
{
const char *myname = "scache_save_endp_service";
int ttl;
int fd;
SCACHE_SIZE size;
if (attr_scan(client_stream,
ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_TTL, &ttl,
ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_endp_label,
ATTR_TYPE_STR, MAIL_ATTR_PROP, scache_endp_prop,
ATTR_TYPE_END) != 3
|| ttl <= 0) {
msg_warn("%s: bad or missing request parameter", myname);
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD,
ATTR_TYPE_END);
return;
} else if (
#ifdef CANT_WRITE_BEFORE_SENDING_FD
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
ATTR_TYPE_END) != 0
|| vstream_fflush(client_stream) != 0
|| read_wait(vstream_fileno(client_stream),
client_stream->timeout) < 0 /* XXX */
||
#endif
(fd = LOCAL_RECV_FD(vstream_fileno(client_stream))) < 0) {
msg_warn("%s: unable to receive file descriptor: %m", myname);
(void) attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL,
ATTR_TYPE_END);
return;
} else {
scache_save_endp(scache,
ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl,
STR(scache_endp_label), STR(scache_endp_prop), fd);
(void) attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK,
ATTR_TYPE_END);
scache_size(scache, &size);
if (size.endp_count > scache_endp_count)
scache_endp_count = size.endp_count;
if (size.sess_count > scache_sess_count)
scache_sess_count = size.sess_count;
return;
}
}
/* scache_find_endp_service - protocol to find connection for endpoint */
static void scache_find_endp_service(VSTREAM *client_stream)
{
const char *myname = "scache_find_endp_service";
int fd;
if (attr_scan(client_stream,
ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_endp_label,
ATTR_TYPE_END) != 1) {
msg_warn("%s: bad or missing request parameter", myname);
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD,
ATTR_TYPE_STR, MAIL_ATTR_PROP, "",
ATTR_TYPE_END);
return;
} else if ((fd = scache_find_endp(scache, STR(scache_endp_label),
scache_endp_prop)) < 0) {
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL,
ATTR_TYPE_STR, MAIL_ATTR_PROP, "",
ATTR_TYPE_END);
scache_endp_miss++;
return;
} else {
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK,
ATTR_TYPE_STR, MAIL_ATTR_PROP, STR(scache_endp_prop),
ATTR_TYPE_END);
if (vstream_fflush(client_stream) != 0
#ifdef CANT_WRITE_BEFORE_SENDING_FD
|| attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
ATTR_TYPE_END) != 1
#endif
|| LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0
#ifdef MUST_READ_AFTER_SENDING_FD
|| attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
ATTR_TYPE_END) != 1
#endif
)
msg_warn("%s: cannot send file descriptor: %m", myname);
if (close(fd) < 0)
msg_warn("close(%d): %m", fd);
scache_endp_hits++;
return;
}
}
/* scache_save_dest_service - protocol to save destination->endpoint binding */
static void scache_save_dest_service(VSTREAM *client_stream)
{
const char *myname = "scache_save_dest_service";
int ttl;
SCACHE_SIZE size;
if (attr_scan(client_stream,
ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_TTL, &ttl,
ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_dest_label,
ATTR_TYPE_STR, MAIL_ATTR_PROP, scache_dest_prop,
ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_endp_label,
ATTR_TYPE_END) != 4
|| ttl <= 0) {
msg_warn("%s: bad or missing request parameter", myname);
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD,
ATTR_TYPE_END);
return;
} else {
scache_save_dest(scache,
ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl,
STR(scache_dest_label), STR(scache_dest_prop),
STR(scache_endp_label));
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK,
ATTR_TYPE_END);
scache_size(scache, &size);
if (size.dest_count > scache_dest_count)
scache_dest_count = size.dest_count;
if (size.endp_count > scache_endp_count)
scache_endp_count = size.endp_count;
return;
}
}
/* scache_find_dest_service - protocol to find connection for destination */
static void scache_find_dest_service(VSTREAM *client_stream)
{
const char *myname = "scache_find_dest_service";
int fd;
if (attr_scan(client_stream,
ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_dest_label,
ATTR_TYPE_END) != 1) {
msg_warn("%s: bad or missing request parameter", myname);
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD,
ATTR_TYPE_STR, MAIL_ATTR_PROP, "",
ATTR_TYPE_STR, MAIL_ATTR_PROP, "",
ATTR_TYPE_END);
return;
} else if ((fd = scache_find_dest(scache, STR(scache_dest_label),
scache_dest_prop,
scache_endp_prop)) < 0) {
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL,
ATTR_TYPE_STR, MAIL_ATTR_PROP, "",
ATTR_TYPE_STR, MAIL_ATTR_PROP, "",
ATTR_TYPE_END);
scache_dest_miss++;
return;
} else {
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK,
ATTR_TYPE_STR, MAIL_ATTR_PROP, STR(scache_dest_prop),
ATTR_TYPE_STR, MAIL_ATTR_PROP, STR(scache_endp_prop),
ATTR_TYPE_END);
if (vstream_fflush(client_stream) != 0
#ifdef CANT_WRITE_BEFORE_SENDING_FD
|| attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
ATTR_TYPE_END) != 1
#endif
|| LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0
#ifdef MUST_READ_AFTER_SENDING_FD
|| attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
ATTR_TYPE_END) != 1
#endif
)
msg_warn("%s: cannot send file descriptor: %m", myname);
if (close(fd) < 0)
msg_warn("close(%d): %m", fd);
scache_dest_hits++;
return;
}
}
/* scache_service - perform service for client */
static void scache_service(VSTREAM *client_stream, char *unused_service,
char **argv)
{
/*
* Sanity check. This service takes no command-line arguments.
*/
if (argv[0])
msg_fatal("unexpected command-line argument: %s", argv[0]);
/*
* This routine runs whenever a client connects to the UNIX-domain socket
* dedicated to the scache service. All connection-management stuff is
* handled by the common code in multi_server.c.
*/
if (attr_scan(client_stream,
ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_REQ, scache_request,
ATTR_TYPE_END) == 1) {
if (VSTREQ(scache_request, SCACHE_REQ_SAVE_DEST)) {
scache_save_dest_service(client_stream);
} else if (VSTREQ(scache_request, SCACHE_REQ_FIND_DEST)) {
scache_find_dest_service(client_stream);
} else if (VSTREQ(scache_request, SCACHE_REQ_SAVE_ENDP)) {
scache_save_endp_service(client_stream);
} else if (VSTREQ(scache_request, SCACHE_REQ_FIND_ENDP)) {
scache_find_endp_service(client_stream);
} else {
msg_warn("unrecognized request: \"%s\", ignored",
STR(scache_request));
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD,
ATTR_TYPE_END);
}
}
vstream_fflush(client_stream);
}
/* scache_status_dump - log and reset cache statistics */
static void scache_status_dump(char *unused_name, char **unused_argv)
{
if (scache_dest_hits || scache_dest_miss
|| scache_endp_hits || scache_endp_miss
|| scache_dest_count || scache_endp_count
|| scache_sess_count)
msg_info("statistics: start interval %.15s",
ctime(&scache_start_time) + 4);
if (scache_dest_hits || scache_dest_miss) {
msg_info("statistics: domain lookup hits=%d miss=%d success=%d%%",
scache_dest_hits, scache_dest_miss,
scache_dest_hits * 100
/ (scache_dest_hits + scache_dest_miss));
scache_dest_hits = scache_dest_miss = 0;
}
if (scache_endp_hits || scache_endp_miss) {
msg_info("statistics: address lookup hits=%d miss=%d success=%d%%",
scache_endp_hits, scache_endp_miss,
scache_endp_hits * 100
/ (scache_endp_hits + scache_endp_miss));
scache_endp_hits = scache_endp_miss = 0;
}
if (scache_dest_count || scache_endp_count || scache_sess_count) {
msg_info("statistics: max simultaneous domains=%d addresses=%d connection=%d",
scache_dest_count, scache_endp_count, scache_sess_count);
scache_dest_count = 0;
scache_endp_count = 0;
scache_sess_count = 0;
}
scache_start_time = event_time();
}
/* scache_status_update - log and reset cache statistics periodically */
static void scache_status_update(int unused_event, char *context)
{
scache_status_dump((char *) 0, (char **) 0);
event_request_timer(scache_status_update, context, var_scache_stat_time);
}
/* post_jail_init - initialization after privilege drop */
static void post_jail_init(char *unused_name, char **unused_argv)
{
/*
* Pre-allocate the cache instance.
*/
scache = scache_multi_create();
/*
* Pre-allocate buffers.
*/
scache_request = vstring_alloc(10);
scache_dest_label = vstring_alloc(10);
scache_dest_prop = vstring_alloc(10);
scache_endp_label = vstring_alloc(10);
scache_endp_prop = vstring_alloc(10);
#ifdef CANT_WRITE_BEFORE_SENDING_FD
scache_dummy = vstring_alloc(10);
#endif
/*
* Disable the max_use limit. We still terminate when no client is
* connected for $idle_limit time units.
*/
var_use_limit = 0;
/*
* Dump and reset cache statistics every so often.
*/
event_request_timer(scache_status_update, (char *) 0, var_scache_stat_time);
scache_start_time = event_time();
}
/* main - pass control to the multi-threaded skeleton */
int main(int argc, char **argv)
{
static CONFIG_TIME_TABLE time_table[] = {
VAR_SCACHE_TTL_LIM, DEF_SCACHE_TTL_LIM, &var_scache_ttl_lim, 1, 0,
VAR_SCACHE_STAT_TIME, DEF_SCACHE_STAT_TIME, &var_scache_stat_time, 1, 0,
0,
};
multi_server_main(argc, argv, scache_service,
MAIL_SERVER_TIME_TABLE, time_table,
MAIL_SERVER_POST_INIT, post_jail_init,
MAIL_SERVER_EXIT, scache_status_dump,
MAIL_SERVER_SOLITARY,
0);
}

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -92,3 +94,4 @@ sendmail.o: ../../include/deliver_request.h
sendmail.o: ../../include/recipient_list.h
sendmail.o: ../../include/mime_state.h
sendmail.o: ../../include/header_opts.h
sendmail.o: ../../include/user_acl.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: sendmail.c,v 1.1.1.9 2004/05/31 00:24:45 heas Exp $ */
/* $NetBSD: sendmail.c,v 1.1.1.10 2005/08/18 21:08:46 rpaulo Exp $ */
/*++
/* NAME
@ -14,14 +14,15 @@
/* \fBnewaliases\fR
/* \fBsendmail -I\fR
/* DESCRIPTION
/* The Postfix \fBsendmail\fR command implements the Postfix to Sendmail
/* compatibility interface.
/* The Postfix \fBsendmail\fR(1) command implements the Postfix
/* to Sendmail compatibility interface.
/* For the sake of compatibility with existing applications, some
/* Sendmail command-line options are recognized but silently ignored.
/*
/* By default, Postfix \fBsendmail\fR reads a message from standard input
/* By default, Postfix \fBsendmail\fR(1) reads a message from
/* standard input
/* until EOF or until it reads a line with only a \fB.\fR character,
/* and arranges for delivery. Postfix \fBsendmail\fR relies on the
/* and arranges for delivery. Postfix \fBsendmail\fR(1) relies on the
/* \fBpostdrop\fR(1) command to create a queue file in the \fBmaildrop\fR
/* directory.
/*
@ -43,7 +44,7 @@
/* command.
/* .sp
/* Note: it may take a minute or so before an alias database update
/* becomes visible. Use the \fBpostfix reload\fR command to eliminate
/* becomes visible. Use the "\fBpostfix reload\fR" command to eliminate
/* this delay.
/* .PP
/* These and other features can be selected by specifying the
@ -59,7 +60,7 @@
/* The message body MIME type: \fB7BIT\fR or \fB8BITMIME\fR.
/* .IP \fB-bd\fR
/* Go into daemon mode. This mode of operation is implemented by
/* executing the \fBpostfix start\fR command.
/* executing the "\fBpostfix start\fR" command.
/* .IP "\fB-bh\fR (ignored)"
/* .IP "\fB-bH\fR (ignored)"
/* Postfix has no persistent host status database.
@ -94,8 +95,8 @@
/* have no \fBFrom:\fR message header.
/* .IP "\fB-f \fIsender\fR"
/* Set the envelope sender address. This is the address where
/* delivery problems are sent to, unless the message contains an
/* \fBErrors-To:\fR message header.
/* delivery problems are sent to. With Postfix versions before 2.1, the
/* \fBErrors-To:\fR message header overrides the error return address.
/* .IP "\fB-G\fR (ignored)"
/* Gateway (relay) submission, as opposed to initial user submission.
/* .IP "\fB-h \fIhop_count\fR (ignored)"
@ -121,6 +122,8 @@
/* Non-default alias database. Specify \fIpathname\fR or
/* \fItype\fR:\fIpathname\fR. See \fBpostalias\fR(1) for
/* details.
/* .IP "\fB-O \fIoption=value\fR (ignored)"
/* Backwards compatibility.
/* .IP "\fB-o7\fR (ignored)"
/* .IP "\fB-o8\fR (ignored)"
/* To send 8-bit or binary content, use an appropriate MIME encapsulation
@ -135,8 +138,8 @@
/* configuration parameter in \fBmain.cf\fR instead.
/* .IP "\fB-r \fIsender\fR"
/* Set the envelope sender address. This is the address where
/* delivery problems are sent to, unless the message contains an
/* \fBErrors-To:\fR message header.
/* delivery problems are sent to. With Postfix versions before 2.1, the
/* \fBErrors-To:\fR message header overrides the error return address.
/* .IP "\fB-R \fIreturn_limit\fR (ignored)"
/* Limit the size of bounced mail. Use the \fBbounce_size_limit\fR
/* configuration parameter instead.
@ -157,7 +160,7 @@
/* See \fBflush\fR(8) for more information about the "fast flush"
/* service.
/* .IP \fB-qS\fIsite\fR
/* This command is not implemented. Use the slower \fBsendmail -q\fR
/* This command is not implemented. Use the slower "\fBsendmail -q\fR"
/* command instead.
/* .IP \fB-t\fR
/* Extract recipients from message headers. These are added to any
@ -217,7 +220,7 @@
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* TROUBLE SHOOTING CONTROLS
/* .ad
/* .fi
@ -233,6 +236,17 @@
/* Optional list of remote client or server hostname or network
/* address patterns that cause the verbose logging level to increase
/* by the amount specified in $debug_peer_level.
/* ACCESS CONTROLS
/* .ad
/* .fi
/* Available in Postfix version 2.2 and later:
/* .IP "\fBauthorized_flush_users (static:anyone)\fR"
/* List of users who are authorized to flush the queue.
/* .IP "\fBauthorized_mailq_users (static:anyone)\fR"
/* List of users who are authorized to view the queue.
/* .IP "\fBauthorized_submit_users (static:anyone)\fR"
/* List of users who are authorized to submit mail with the \fBsendmail\fR(1)
/* command (and with the privileged \fBpostdrop\fR(1) helper command).
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@ -266,12 +280,12 @@
/* The two default VERP delimiter characters.
/* .IP "\fBverp_delimiter_filter (-=+)\fR"
/* The characters Postfix accepts as VERP delimiter characters on the
/* Postfix sendmail(1) command line and in SMTP commands.
/* Postfix \fBsendmail\fR(1) command line and in SMTP commands.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
/* .IP "\fBalias_database (see 'postconf -d' output)\fR"
/* The alias databases for local(8) delivery that are updated with
/* The alias databases for \fBlocal\fR(8) delivery that are updated with
/* "\fBnewaliases\fR" or with "\fBsendmail -bi\fR".
/* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
/* The location of all postfix administrative commands.
@ -281,11 +295,17 @@
/* .IP "\fBdaemon_directory (see 'postconf -d' output)\fR"
/* The directory with Postfix support programs and daemon programs.
/* .IP "\fBdefault_database_type (see 'postconf -d' output)\fR"
/* The default database type for use in newaliases(1), postalias(1)
/* and postmap(1) commands.
/* The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1)
/* and \fBpostmap\fR(1) commands.
/* .IP "\fBdelay_warning_time (0h)\fR"
/* The time after which the sender receives the message headers of
/* mail that is still queued.
/* .IP "\fBenable_errors_to (no)\fR"
/* Report mail delivery errors to the address specified with the
/* non-standard Errors-To: message header, instead of the envelope
/* sender address (this feature is removed with Postfix 2.2, is
/* turned off by default with Postfix 2.1, and is always turned on
/* with older Postfix versions).
/* .IP "\fBmail_owner (postfix)\fR"
/* The UNIX system account that owns the Postfix queue and most Postfix
/* daemon processes.
@ -298,7 +318,7 @@
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* .IP "\fBtrigger_timeout (10s)\fR"
/* The time limit for sending a trigger to a Postfix daemon (for
/* example, the pickup(8) or qmgr(8) daemon).
/* example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon).
/* FILES
/* /var/spool/postfix, mail queue
/* /etc/postfix, configuration files
@ -385,6 +405,7 @@
#include <deliver_request.h>
#include <mime_state.h>
#include <header_opts.h>
#include <user_acl.h>
/* Application-specific. */
@ -410,7 +431,7 @@
/*
* VERP support.
*/
char *verp_delims;
static char *verp_delims;
/*
* Callback context for extracting recipients.
@ -425,6 +446,16 @@ typedef struct SM_STATE {
VSTRING *temp; /* scratch buffer */
} SM_STATE;
/*
* Mail submission ACL
*/
char *var_submit_acl;
static CONFIG_STR_TABLE str_table[] = {
VAR_SUBMIT_ACL, DEF_SUBMIT_ACL, &var_submit_acl, 0, 0,
0,
};
/*
* Silly little macros (SLMs).
*/
@ -457,6 +488,7 @@ static void output_header(void *context, int header_class,
char *start;
char *line;
char *next_line;
int len;
/*
* Parse the header line, and save copies of recipient addresses in the
@ -473,11 +505,11 @@ static void output_header(void *context, int header_class,
state->resent = 1;
} else
rcpt = state->recipients;
tree = tok822_parse(vstring_str(buf) + strlen(header_info->name) + 1);
tree = tok822_parse(STR(buf) + strlen(header_info->name) + 1);
addr_list = tok822_grep(tree, TOK822_ADDR);
for (tpp = addr_list; *tpp; tpp++) {
tok822_internalize(state->temp, tpp[0]->head, TOK822_STR_DEFL);
argv_add(rcpt, vstring_str(state->temp), (char *) 0);
argv_add(rcpt, STR(state->temp), (char *) 0);
}
myfree((char *) addr_list);
tok822_free_tree(tree);
@ -485,12 +517,24 @@ static void output_header(void *context, int header_class,
/*
* Pipe the unmodified message header through the header line folding
* routine.
* routine, and ensure that long lines are chopped appropriately.
*/
for (line = start = STR(buf); line; line = next_line) {
next_line = split_at(line, '\n');
output_text(context, REC_TYPE_NORM, line, next_line ?
next_line - line - 1 : strlen(line), offset);
len = next_line ? next_line - line - 1 : strlen(line);
do {
if (len > var_line_limit) {
output_text(context, REC_TYPE_CONT, line, var_line_limit, offset);
line += var_line_limit;
len -= var_line_limit;
offset += var_line_limit;
} else {
output_text(context, REC_TYPE_NORM, line, len, offset);
offset += len;
break;
}
} while (len > 0);
offset += 1;
}
}
@ -508,6 +552,7 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
int skip_from_;
TOK822 *tree;
TOK822 *tp;
int rcpt_count = 0;
enum {
STRIP_CR_DUNNO, STRIP_CR_DO, STRIP_CR_DONT
} strip_cr;
@ -520,6 +565,16 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
MIME_STATE *mime_state = 0;
SM_STATE state;
int mime_errs;
const char *errstr;
int addr_count;
/*
* Access control is enforced in the postdrop command. The code here
* merely produces a more user-friendly interface.
*/
if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to submit mail", errstr, (long) uid);
/*
* Initialize.
@ -599,16 +654,25 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
if (recipients) {
for (cpp = recipients; *cpp != 0; cpp++) {
tree = tok822_parse(*cpp);
for (tp = tree; tp != 0; tp = tp->next) {
for (addr_count = 0, tp = tree; tp != 0; tp = tp->next) {
if (tp->type == TOK822_ADDR) {
tok822_internalize(buf, tp->head, TOK822_STR_DEFL);
if (REC_PUT_BUF(dst, REC_TYPE_RCPT, buf) < 0)
msg_fatal_status(EX_TEMPFAIL,
"%s(%ld): error writing queue file: %m",
saved_sender, (long) uid);
++rcpt_count;
++addr_count;
}
}
tok822_free_tree(tree);
if (addr_count == 0) {
if (rec_put(dst, REC_TYPE_RCPT, "", 0) < 0)
msg_fatal_status(EX_TEMPFAIL,
"%s(%ld): error writing queue file: %m",
saved_sender, (long) uid);
++rcpt_count;
}
}
}
@ -623,6 +687,10 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
*/
rec_fputs(dst, REC_TYPE_MESG, "");
if (DEL_REQ_TRACE_ONLY(flags) != 0) {
if (flags & SM_FLAG_XRCPT)
msg_fatal_status(EX_USAGE, "-t option cannot be used with -bv");
if (*saved_sender)
rec_fprintf(dst, REC_TYPE_NORM, "From: %s", saved_sender);
rec_fprintf(dst, REC_TYPE_NORM, "Subject: probe");
if (recipients) {
rec_fprintf(dst, REC_TYPE_NORM, "To:");
@ -669,7 +737,7 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
}
if (skip_from_) {
if (type == REC_TYPE_NORM) {
start = vstring_str(buf);
start = STR(buf);
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0)
continue;
}
@ -724,11 +792,17 @@ static void enqueue(const int flags, const char *encoding, const char *sender,
msg_fatal_status(EX_TEMPFAIL,
"%s(%ld): error writing queue file: %m",
saved_sender, (long) uid);
++rcpt_count;
}
argv_free(state.recipients);
argv_free(state.resent_recip);
vstring_free(state.temp);
}
if (rcpt_count == 0)
msg_fatal_status(EX_USAGE, (flags & SM_FLAG_XRCPT) ?
"No recipient addresses found in message header" :
"Recipient addresses must be specified on"
" the command line or via the -t option");
/*
* Identify the end of the queue file.
@ -786,6 +860,8 @@ int main(int argc, char **argv)
char *site_to_flush = 0;
char *encoding = 0;
char *qtime = 0;
const char *errstr;
uid_t uid;
/*
* Be consistent with file permissions.
@ -847,6 +923,7 @@ int main(int argc, char **argv)
* Further initialization...
*/
mail_conf_read();
get_mail_conf_str_table(str_table);
if (chdir(var_queue_dir))
msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
@ -897,7 +974,7 @@ int main(int argc, char **argv)
optind++;
continue;
}
if ((c = GETOPT(argc, argv, "A:B:C:F:GIL:N:R:UV:X:b:ce:f:h:imno:p:r:q:tvx")) <= 0)
if ((c = GETOPT(argc, argv, "A:B:C:F:GIL:N:O:R:UV:X:b:ce:f:h:imno:p:r:q:tvx")) <= 0)
break;
switch (c) {
default:
@ -1106,6 +1183,11 @@ int main(int argc, char **argv)
if (argv[OPTIND])
msg_fatal_status(EX_USAGE,
"stand-alone mode requires no recipient");
/* The actual enforcement happens in the postdrop command. */
if ((errstr = check_user_acl_byuid(var_submit_acl, uid = getuid())) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to submit mail",
errstr, (long) uid);
ext_argv = argv_alloc(2);
argv_add(ext_argv, "smtpd", "-S", (char *) 0);
for (n = 0; n < msg_verbose; n++)

View File

@ -15,8 +15,10 @@ LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -46,7 +48,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2

View File

@ -1,4 +1,4 @@
/* $NetBSD: showq.c,v 1.1.1.7 2004/05/31 00:24:45 heas Exp $ */
/* $NetBSD: showq.c,v 1.1.1.8 2005/08/18 21:08:47 rpaulo Exp $ */
/*++
/* NAME
@ -8,38 +8,39 @@
/* SYNOPSIS
/* \fBshowq\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The \fBshowq\fR daemon reports the Postfix mail queue status.
/* The \fBshowq\fR(8) daemon reports the Postfix mail queue status.
/* It is the program that emulates the sendmail `mailq' command.
/*
/* The \fBshowq\fR daemon can also be run in stand-alone mode
/* The \fBshowq\fR(8) daemon can also be run in stand-alone mode
/* by the superuser. This mode of operation is used to emulate
/* the `mailq' command while the Postfix mail system is down.
/* SECURITY
/* .ad
/* .fi
/* The \fBshowq\fR daemon can run in a chroot jail at fixed low
/* The \fBshowq\fR(8) daemon can run in a chroot jail at fixed low
/* privilege, and takes no input from the client. Its service port
/* is accessible to local untrusted users, so the service can be
/* susceptible to denial of service attacks.
/* STANDARDS
/* .ad
/* .fi
/* None. The showq daemon does not interact with the outside world.
/* None. The \fBshowq\fR(8) daemon does not interact with the
/* outside world.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
/* The \fBshowq\fR daemon runs at a fixed low privilege; consequently,
/* The \fBshowq\fR(8) daemon runs at a fixed low privilege; consequently,
/* it cannot extract information from queue files in the
/* \fBmaildrop\fR directory.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically as showq(8)
/* Changes to \fBmain.cf\fR are picked up automatically as \fBshowq\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
@ -48,8 +49,8 @@
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBduplicate_filter_limit (1000)\fR"
/* The maximal number of addresses remembered by the address
/* duplicate filter for aliases(5) or virtual(5) alias expansion, or
/* for showq(8) queue displays.
/* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
/* for \fBshowq\fR(8) queue displays.
/* .IP "\fBempty_address_recipient (MAILER-DAEMON)\fR"
/* The recipient of mail addressed to the null address.
/* .IP "\fBipc_timeout (3600s)\fR"

View File

@ -1,30 +1,33 @@
SHELL = /bin/sh
SRCS = smtp.c smtp_connect.c smtp_proto.c smtp_chat.c smtp_session.c \
smtp_addr.c smtp_trouble.c smtp_state.c smtp_rcpt.c \
smtp_sasl_proto.c smtp_sasl_glue.c
smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c
OBJS = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
smtp_addr.o smtp_trouble.o smtp_state.o smtp_rcpt.o \
smtp_sasl_proto.o smtp_sasl_glue.o
HDRS = smtp.h smtp_sasl.h
smtp_sasl_proto.o smtp_sasl_glue.o smtp_reuse.o smtp_map11.o
HDRS = smtp.h smtp_sasl.h smtp_addr.h smtp_reuse.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG= smtp_unalias
TESTPROG= smtp_unalias smtp_map11
PROG = smtp
INC_DIR = ../../include
LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libdns.a ../../lib/libutil.a
LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \
../../lib/libglobal.a ../../lib/libutil.a
.c.o:; $(CC) $(CFLAGS) -c $*.c
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
tests: test
tests: smtp_map11_test
update: ../../libexec/$(PROG)
@ -51,10 +54,23 @@ tidy: clean
smtp_unalias: smtp_unalias.c $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
smtp_map11: smtp_map11.c $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
# This needs trivial-rewrite service and myorigin==mydomain
smtp_map11_test: smtp_map11 map11_map smtp_map11.ref
../postmap/postmap map11_map
./smtp_map11 hash:map11_map foo@example.com bar@example.com \
baz@example.com foo@example.net >smtp_map11.tmp 2>&1
sed -e "s/MYDOMAIN/`postconf -h mydomain`/" \
-e "s/MYHOSTNAME/`postconf -h myhostname`/" smtp_map11.ref | \
diff - smtp_map11.tmp
rm -f smtp_map11.tmp map11_map.db
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -76,8 +92,18 @@ smtp.o: ../../include/mail_params.h
smtp.o: ../../include/mail_conf.h
smtp.o: ../../include/debug_peer.h
smtp.o: ../../include/flush_clnt.h
smtp.o: ../../include/scache.h
smtp.o: ../../include/string_list.h
smtp.o: ../../include/match_list.h
smtp.o: ../../include/match_ops.h
smtp.o: ../../include/maps.h
smtp.o: ../../include/ext_prop.h
smtp.o: ../../include/mail_server.h
smtp.o: smtp.h
smtp.o: ../../include/htable.h
smtp.o: ../../include/tok822.h
smtp.o: ../../include/resolve_clnt.h
smtp.o: ../../include/tls.h
smtp.o: smtp_sasl.h
smtp_addr.o: smtp_addr.c
smtp_addr.o: ../../include/sys_defs.h
@ -86,16 +112,28 @@ smtp_addr.o: ../../include/vstring.h
smtp_addr.o: ../../include/vbuf.h
smtp_addr.o: ../../include/mymalloc.h
smtp_addr.o: ../../include/inet_addr_list.h
smtp_addr.o: ../../include/myaddrinfo.h
smtp_addr.o: ../../include/stringops.h
smtp_addr.o: ../../include/myrand.h
smtp_addr.o: ../../include/inet_proto.h
smtp_addr.o: ../../include/mail_params.h
smtp_addr.o: ../../include/own_inet_addr.h
smtp_addr.o: ../../include/dns.h
smtp_addr.o: ../../include/sock_addr.h
smtp_addr.o: smtp.h
smtp_addr.o: ../../include/vstream.h
smtp_addr.o: ../../include/argv.h
smtp_addr.o: ../../include/htable.h
smtp_addr.o: ../../include/deliver_request.h
smtp_addr.o: ../../include/recipient_list.h
smtp_addr.o: ../../include/scache.h
smtp_addr.o: ../../include/string_list.h
smtp_addr.o: ../../include/match_list.h
smtp_addr.o: ../../include/match_ops.h
smtp_addr.o: ../../include/maps.h
smtp_addr.o: ../../include/dict.h
smtp_addr.o: ../../include/tok822.h
smtp_addr.o: ../../include/resolve_clnt.h
smtp_addr.o: ../../include/tls.h
smtp_addr.o: smtp_addr.h
smtp_chat.o: smtp_chat.c
smtp_chat.o: ../../include/sys_defs.h
@ -117,6 +155,16 @@ smtp_chat.o: ../../include/cleanup_user.h
smtp_chat.o: ../../include/mail_error.h
smtp_chat.o: ../../include/name_mask.h
smtp_chat.o: smtp.h
smtp_chat.o: ../../include/htable.h
smtp_chat.o: ../../include/scache.h
smtp_chat.o: ../../include/string_list.h
smtp_chat.o: ../../include/match_list.h
smtp_chat.o: ../../include/match_ops.h
smtp_chat.o: ../../include/maps.h
smtp_chat.o: ../../include/dict.h
smtp_chat.o: ../../include/tok822.h
smtp_chat.o: ../../include/resolve_clnt.h
smtp_chat.o: ../../include/tls.h
smtp_connect.o: smtp_connect.c
smtp_connect.o: ../../include/sys_defs.h
smtp_connect.o: ../../include/msg.h
@ -126,14 +174,15 @@ smtp_connect.o: ../../include/vstring.h
smtp_connect.o: ../../include/split_at.h
smtp_connect.o: ../../include/mymalloc.h
smtp_connect.o: ../../include/inet_addr_list.h
smtp_connect.o: ../../include/myaddrinfo.h
smtp_connect.o: ../../include/iostuff.h
smtp_connect.o: ../../include/timed_connect.h
smtp_connect.o: ../../include/stringops.h
smtp_connect.o: ../../include/host_port.h
smtp_connect.o: ../../include/sane_connect.h
smtp_connect.o: ../../include/sock_addr.h
smtp_connect.o: ../../include/mail_params.h
smtp_connect.o: ../../include/own_inet_addr.h
smtp_connect.o: ../../include/debug_peer.h
smtp_connect.o: ../../include/deliver_pass.h
smtp_connect.o: ../../include/deliver_request.h
smtp_connect.o: ../../include/recipient_list.h
@ -144,7 +193,42 @@ smtp_connect.o: ../../include/name_mask.h
smtp_connect.o: ../../include/dns.h
smtp_connect.o: smtp.h
smtp_connect.o: ../../include/argv.h
smtp_connect.o: ../../include/htable.h
smtp_connect.o: ../../include/scache.h
smtp_connect.o: ../../include/string_list.h
smtp_connect.o: ../../include/match_list.h
smtp_connect.o: ../../include/match_ops.h
smtp_connect.o: ../../include/maps.h
smtp_connect.o: ../../include/dict.h
smtp_connect.o: ../../include/tok822.h
smtp_connect.o: ../../include/resolve_clnt.h
smtp_connect.o: ../../include/tls.h
smtp_connect.o: smtp_addr.h
smtp_connect.o: smtp_reuse.h
smtp_map11.o: smtp_map11.c
smtp_map11.o: ../../include/sys_defs.h
smtp_map11.o: ../../include/msg.h
smtp_map11.o: ../../include/vstring.h
smtp_map11.o: ../../include/vbuf.h
smtp_map11.o: ../../include/dict.h
smtp_map11.o: ../../include/vstream.h
smtp_map11.o: ../../include/argv.h
smtp_map11.o: ../../include/tok822.h
smtp_map11.o: ../../include/resolve_clnt.h
smtp_map11.o: ../../include/valid_hostname.h
smtp_map11.o: ../../include/mail_addr_map.h
smtp_map11.o: ../../include/maps.h
smtp_map11.o: ../../include/quote_822_local.h
smtp_map11.o: ../../include/quote_flags.h
smtp_map11.o: smtp.h
smtp_map11.o: ../../include/htable.h
smtp_map11.o: ../../include/deliver_request.h
smtp_map11.o: ../../include/recipient_list.h
smtp_map11.o: ../../include/scache.h
smtp_map11.o: ../../include/string_list.h
smtp_map11.o: ../../include/match_list.h
smtp_map11.o: ../../include/match_ops.h
smtp_map11.o: ../../include/tls.h
smtp_proto.o: smtp_proto.c
smtp_proto.o: ../../include/sys_defs.h
smtp_proto.o: ../../include/msg.h
@ -174,8 +258,22 @@ smtp_proto.o: ../../include/mail_proto.h
smtp_proto.o: ../../include/attr.h
smtp_proto.o: ../../include/mime_state.h
smtp_proto.o: ../../include/header_opts.h
smtp_proto.o: smtp.h
smtp_proto.o: ../../include/ehlo_mask.h
smtp_proto.o: ../../include/maps.h
smtp_proto.o: ../../include/dict.h
smtp_proto.o: ../../include/argv.h
smtp_proto.o: ../../include/tok822.h
smtp_proto.o: ../../include/resolve_clnt.h
smtp_proto.o: ../../include/mail_addr_map.h
smtp_proto.o: ../../include/ext_prop.h
smtp_proto.o: ../../include/lex_822.h
smtp_proto.o: smtp.h
smtp_proto.o: ../../include/htable.h
smtp_proto.o: ../../include/scache.h
smtp_proto.o: ../../include/string_list.h
smtp_proto.o: ../../include/match_list.h
smtp_proto.o: ../../include/match_ops.h
smtp_proto.o: ../../include/tls.h
smtp_proto.o: smtp_sasl.h
smtp_rcpt.o: smtp_rcpt.c
smtp_rcpt.o: ../../include/sys_defs.h
@ -189,6 +287,43 @@ smtp_rcpt.o: ../../include/deliver_completed.h
smtp_rcpt.o: ../../include/sent.h
smtp_rcpt.o: smtp.h
smtp_rcpt.o: ../../include/argv.h
smtp_rcpt.o: ../../include/htable.h
smtp_rcpt.o: ../../include/scache.h
smtp_rcpt.o: ../../include/string_list.h
smtp_rcpt.o: ../../include/match_list.h
smtp_rcpt.o: ../../include/match_ops.h
smtp_rcpt.o: ../../include/maps.h
smtp_rcpt.o: ../../include/dict.h
smtp_rcpt.o: ../../include/tok822.h
smtp_rcpt.o: ../../include/resolve_clnt.h
smtp_rcpt.o: ../../include/tls.h
smtp_reuse.o: smtp_reuse.c
smtp_reuse.o: ../../include/sys_defs.h
smtp_reuse.o: ../../include/msg.h
smtp_reuse.o: ../../include/mymalloc.h
smtp_reuse.o: ../../include/vstream.h
smtp_reuse.o: ../../include/vbuf.h
smtp_reuse.o: ../../include/vstring.h
smtp_reuse.o: ../../include/htable.h
smtp_reuse.o: ../../include/stringops.h
smtp_reuse.o: ../../include/scache.h
smtp_reuse.o: ../../include/mail_params.h
smtp_reuse.o: smtp.h
smtp_reuse.o: ../../include/argv.h
smtp_reuse.o: ../../include/deliver_request.h
smtp_reuse.o: ../../include/recipient_list.h
smtp_reuse.o: ../../include/string_list.h
smtp_reuse.o: ../../include/match_list.h
smtp_reuse.o: ../../include/match_ops.h
smtp_reuse.o: ../../include/maps.h
smtp_reuse.o: ../../include/dict.h
smtp_reuse.o: ../../include/tok822.h
smtp_reuse.o: ../../include/resolve_clnt.h
smtp_reuse.o: ../../include/tls.h
smtp_reuse.o: smtp_reuse.h
smtp_reuse.o: ../../include/dns.h
smtp_reuse.o: ../../include/sock_addr.h
smtp_reuse.o: ../../include/myaddrinfo.h
smtp_sasl_glue.o: smtp_sasl_glue.c
smtp_sasl_glue.o: ../../include/sys_defs.h
smtp_sasl_glue.o: ../../include/msg.h
@ -207,46 +342,85 @@ smtp_sasl_glue.o: ../../include/dict.h
smtp_sasl_glue.o: ../../include/vstream.h
smtp_sasl_glue.o: ../../include/argv.h
smtp_sasl_glue.o: smtp.h
smtp_sasl_glue.o: ../../include/htable.h
smtp_sasl_glue.o: ../../include/deliver_request.h
smtp_sasl_glue.o: ../../include/recipient_list.h
smtp_sasl_glue.o: ../../include/scache.h
smtp_sasl_glue.o: ../../include/tok822.h
smtp_sasl_glue.o: ../../include/resolve_clnt.h
smtp_sasl_glue.o: ../../include/tls.h
smtp_sasl_glue.o: smtp_sasl.h
smtp_sasl_proto.o: smtp_sasl_proto.c
smtp_sasl_proto.o: ../../include/sys_defs.h
smtp_sasl_proto.o: ../../include/msg.h
smtp_sasl_proto.o: ../../include/mymalloc.h
smtp_sasl_proto.o: ../../include/stringops.h
smtp_sasl_proto.o: ../../include/vstring.h
smtp_sasl_proto.o: ../../include/vbuf.h
smtp_sasl_proto.o: ../../include/mail_params.h
smtp_sasl_proto.o: smtp.h
smtp_sasl_proto.o: ../../include/vstream.h
smtp_sasl_proto.o: ../../include/vbuf.h
smtp_sasl_proto.o: ../../include/vstring.h
smtp_sasl_proto.o: ../../include/argv.h
smtp_sasl_proto.o: ../../include/htable.h
smtp_sasl_proto.o: ../../include/deliver_request.h
smtp_sasl_proto.o: ../../include/recipient_list.h
smtp_sasl_proto.o: ../../include/scache.h
smtp_sasl_proto.o: ../../include/string_list.h
smtp_sasl_proto.o: ../../include/match_list.h
smtp_sasl_proto.o: ../../include/match_ops.h
smtp_sasl_proto.o: ../../include/maps.h
smtp_sasl_proto.o: ../../include/dict.h
smtp_sasl_proto.o: ../../include/tok822.h
smtp_sasl_proto.o: ../../include/resolve_clnt.h
smtp_sasl_proto.o: ../../include/tls.h
smtp_sasl_proto.o: smtp_sasl.h
smtp_session.o: smtp_session.c
smtp_session.o: ../../include/sys_defs.h
smtp_session.o: ../../include/msg.h
smtp_session.o: ../../include/mymalloc.h
smtp_session.o: ../../include/vstream.h
smtp_session.o: ../../include/vbuf.h
smtp_session.o: ../../include/stringops.h
smtp_session.o: ../../include/vstring.h
smtp_session.o: smtp.h
smtp_session.o: ../../include/mime_state.h
smtp_session.o: ../../include/header_opts.h
smtp_session.o: ../../include/debug_peer.h
smtp_session.o: ../../include/mail_params.h
smtp_session.o: ../../include/maps.h
smtp_session.o: ../../include/dict.h
smtp_session.o: ../../include/argv.h
smtp_session.o: smtp.h
smtp_session.o: ../../include/htable.h
smtp_session.o: ../../include/deliver_request.h
smtp_session.o: ../../include/recipient_list.h
smtp_session.o: ../../include/scache.h
smtp_session.o: ../../include/string_list.h
smtp_session.o: ../../include/match_list.h
smtp_session.o: ../../include/match_ops.h
smtp_session.o: ../../include/tok822.h
smtp_session.o: ../../include/resolve_clnt.h
smtp_session.o: ../../include/tls.h
smtp_state.o: smtp_state.c
smtp_state.o: ../../include/sys_defs.h
smtp_state.o: ../../include/mymalloc.h
smtp_state.o: ../../include/vstring.h
smtp_state.o: ../../include/vbuf.h
smtp_state.o: ../../include/vstream.h
smtp_state.o: ../../include/mail_conf.h
smtp_state.o: ../../include/mime_state.h
smtp_state.o: ../../include/header_opts.h
smtp_state.o: ../../include/mail_params.h
smtp_state.o: smtp.h
smtp_state.o: ../../include/vstream.h
smtp_state.o: ../../include/argv.h
smtp_state.o: ../../include/htable.h
smtp_state.o: ../../include/deliver_request.h
smtp_state.o: ../../include/recipient_list.h
smtp_state.o: ../../include/scache.h
smtp_state.o: ../../include/string_list.h
smtp_state.o: ../../include/match_list.h
smtp_state.o: ../../include/match_ops.h
smtp_state.o: ../../include/maps.h
smtp_state.o: ../../include/dict.h
smtp_state.o: ../../include/tok822.h
smtp_state.o: ../../include/resolve_clnt.h
smtp_state.o: ../../include/tls.h
smtp_state.o: smtp_sasl.h
smtp_trouble.o: smtp_trouble.c
smtp_trouble.o: ../../include/sys_defs.h
@ -266,6 +440,16 @@ smtp_trouble.o: ../../include/mail_error.h
smtp_trouble.o: ../../include/name_mask.h
smtp_trouble.o: smtp.h
smtp_trouble.o: ../../include/argv.h
smtp_trouble.o: ../../include/htable.h
smtp_trouble.o: ../../include/scache.h
smtp_trouble.o: ../../include/string_list.h
smtp_trouble.o: ../../include/match_list.h
smtp_trouble.o: ../../include/match_ops.h
smtp_trouble.o: ../../include/maps.h
smtp_trouble.o: ../../include/dict.h
smtp_trouble.o: ../../include/tok822.h
smtp_trouble.o: ../../include/resolve_clnt.h
smtp_trouble.o: ../../include/tls.h
smtp_unalias.o: smtp_unalias.c
smtp_unalias.o: ../../include/sys_defs.h
smtp_unalias.o: ../../include/htable.h
@ -273,8 +457,19 @@ smtp_unalias.o: ../../include/vstring.h
smtp_unalias.o: ../../include/vbuf.h
smtp_unalias.o: ../../include/msg.h
smtp_unalias.o: ../../include/dns.h
smtp_unalias.o: ../../include/sock_addr.h
smtp_unalias.o: ../../include/myaddrinfo.h
smtp_unalias.o: smtp.h
smtp_unalias.o: ../../include/vstream.h
smtp_unalias.o: ../../include/argv.h
smtp_unalias.o: ../../include/deliver_request.h
smtp_unalias.o: ../../include/recipient_list.h
smtp_unalias.o: ../../include/scache.h
smtp_unalias.o: ../../include/string_list.h
smtp_unalias.o: ../../include/match_list.h
smtp_unalias.o: ../../include/match_ops.h
smtp_unalias.o: ../../include/maps.h
smtp_unalias.o: ../../include/dict.h
smtp_unalias.o: ../../include/tok822.h
smtp_unalias.o: ../../include/resolve_clnt.h
smtp_unalias.o: ../../include/tls.h

3
gnu/dist/postfix/src/smtp/map11_map vendored Normal file
View File

@ -0,0 +1,3 @@
foo@example.com bar@com.example
bar@example.com bar
baz@example.com @com.example

View File

@ -1,14 +1,14 @@
/* $NetBSD: smtp.c,v 1.1.1.7 2004/05/31 00:24:46 heas Exp $ */
/* $NetBSD: smtp.c,v 1.1.1.8 2005/08/18 21:08:49 rpaulo Exp $ */
/*++
/* NAME
/* smtp 8
/* SUMMARY
/* Postfix remote delivery via SMTP
/* Postfix SMTP client
/* SYNOPSIS
/* \fBsmtp\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The SMTP client processes message delivery requests from
/* The Postfix SMTP client processes message delivery requests from
/* the queue manager. Each request specifies a queue file, a sender
/* address, a domain or host to deliver to, and recipient information.
/* This program expects to be run from the \fBmaster\fR(8) process
@ -27,6 +27,15 @@
/* When a server is not reachable, or when mail delivery fails due
/* to a recoverable error condition, the SMTP client will try to
/* deliver the mail to an alternate host.
/*
/* After a successful mail transaction, a connection may be saved
/* to the \fBscache\fR(8) connection cache server, so that it
/* may be used by any SMTP client for a subsequent transaction.
/*
/* By default, connection caching is enabled temporarily for
/* destinations that have a high volume of mail in the active
/* queue. Session caching can be enabled permanently for
/* specific destinations.
/* SECURITY
/* .ad
/* .fi
@ -44,6 +53,7 @@
/* RFC 2554 (AUTH command)
/* RFC 2821 (SMTP protocol)
/* RFC 2920 (SMTP Pipelining)
/* RFC 3207 (STARTTLS command)
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* Corrupted message files are marked so that the queue manager can
@ -52,15 +62,22 @@
/* Depending on the setting of the \fBnotify_classes\fR parameter,
/* the postmaster is notified of bounces, protocol problems, and of
/* other trouble.
/* BUGS
/* SMTP connection caching does not work with TLS. The necessary
/* support for TLS object passivation and re-activation does not
/* exist without closing the session, which defeats the purpose.
/*
/* SMTP connection caching assumes that SASL credentials are valid for
/* all destinations that map onto the same IP address and TCP port.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically, as smtp(8)
/* Changes to \fBmain.cf\fR are picked up automatically, as \fBsmtp\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* postconf(5) for more details including examples.
/* \fBpostconf\fR(5) for more details including examples.
/* COMPATIBILITY CONTROLS
/* .ad
/* .fi
@ -96,6 +113,21 @@
/* .IP "\fBsmtp_skip_4xx_greeting (yes)\fR"
/* Skip SMTP servers that greet with a 4XX status code (go away, try
/* again later).
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBsmtp_discard_ehlo_keyword_address_maps (empty)\fR"
/* Lookup tables, indexed by the remote SMTP server address, with
/* case insensitive lists of EHLO keywords (pipelining, starttls,
/* auth, etc.) that the SMTP client will ignore in the EHLO response
/* from a remote SMTP server.
/* .IP "\fBsmtp_discard_ehlo_keywords (empty)\fR"
/* A case insensitive list of EHLO keywords (pipelining, starttls,
/* auth, etc.) that the SMTP client will ignore in the EHLO response
/* from a remote SMTP server.
/* .IP "\fBsmtp_generic_maps (empty)\fR"
/* Optional lookup tables that perform address rewriting in the
/* SMTP client, typically to transform a locally valid address into
/* a globally valid address when sending mail across the Internet.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
@ -105,8 +137,7 @@
/* .IP "\fBmime_boundary_length_limit (2048)\fR"
/* The maximal length of MIME multipart boundary strings.
/* .IP "\fBmime_nesting_limit (100)\fR"
/* The maximal nesting level of multipart mail that the MIME processor
/* will handle.
/* The maximal recursion level that the MIME processor will handle.
/* EXTERNAL CONTENT INSPECTION CONTROLS
/* .ad
/* .fi
@ -125,6 +156,69 @@
/* .IP "\fBsmtp_sasl_security_options (noplaintext, noanonymous)\fR"
/* What authentication mechanisms the Postfix SMTP client is allowed
/* to use.
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBsmtp_sasl_mechanism_filter (empty)\fR"
/* If non-empty, a Postfix SMTP client filter for the remote SMTP
/* server's list of offered SASL mechanisms.
/* STARTTLS SUPPORT CONTROLS
/* .ad
/* .fi
/* Detailed information about STARTTLS configuration may be found
/* in the TLS_README document.
/* .IP "\fBsmtp_use_tls (no)\fR"
/* Opportunistic mode: use TLS when a remote SMTP server announces
/* STARTTLS support, otherwise send the mail in the clear.
/* .IP "\fBsmtp_enforce_tls (no)\fR"
/* Enforcement mode: require that remote SMTP servers use TLS
/* encryption, and never send mail in the clear.
/* .IP "\fBsmtp_sasl_tls_security_options ($smtp_sasl_security_options)\fR"
/* The SASL authentication security options that the Postfix SMTP
/* client uses for TLS encrypted SMTP sessions.
/* .IP "\fBsmtp_starttls_timeout (300s)\fR"
/* Time limit for Postfix SMTP client write and read operations
/* during TLS startup and shutdown handshake procedures.
/* .IP "\fBsmtp_tls_CAfile (empty)\fR"
/* The file with the certificate of the certification authority
/* (CA) that issued the Postfix SMTP client certificate.
/* .IP "\fBsmtp_tls_CApath (empty)\fR"
/* Directory with PEM format certificate authority certificates
/* that the Postfix SMTP client uses to verify a remote SMTP server
/* certificate.
/* .IP "\fBsmtp_tls_cert_file (empty)\fR"
/* File with the Postfix SMTP client RSA certificate in PEM format.
/* .IP "\fBsmtp_tls_cipherlist (empty)\fR"
/* Controls the Postfix SMTP client TLS cipher selection scheme.
/* .IP "\fBsmtp_tls_dcert_file (empty)\fR"
/* File with the Postfix SMTP client DSA certificate in PEM format.
/* .IP "\fBsmtp_tls_dkey_file ($smtp_tls_dcert_file)\fR"
/* File with the Postfix SMTP client DSA private key in PEM format.
/* .IP "\fBsmtp_tls_enforce_peername (yes)\fR"
/* When TLS encryption is enforced, require that the remote SMTP
/* server hostname matches the information in the remote SMTP server
/* certificate.
/* .IP "\fBsmtp_tls_key_file ($smtp_tls_cert_file)\fR"
/* File with the Postfix SMTP client RSA private key in PEM format.
/* .IP "\fBsmtp_tls_loglevel (0)\fR"
/* Enable additional Postfix SMTP client logging of TLS activity.
/* .IP "\fBsmtp_tls_note_starttls_offer (no)\fR"
/* Log the hostname of a remote SMTP server that offers STARTTLS,
/* when TLS is not already enabled for that server.
/* .IP "\fBsmtp_tls_per_site (empty)\fR"
/* Optional lookup tables with the Postfix SMTP client TLS usage
/* policy by next-hop domain name and by remote SMTP server hostname.
/* .IP "\fBsmtp_tls_scert_verifydepth (5)\fR"
/* The verification depth for remote SMTP server certificates.
/* .IP "\fBsmtp_tls_session_cache_database (empty)\fR"
/* Name of the file containing the optional Postfix SMTP client
/* TLS session cache.
/* .IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
/* The expiration time of Postfix SMTP client TLS session cache
/* information.
/* .IP "\fBtls_daemon_random_bytes (32)\fR"
/* The number of pseudo-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8)
/* process requests from the \fBtlsmgr\fR(8) server in order to seed its
/* internal pseudo random number generator (PRNG).
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@ -169,9 +263,23 @@
/* The maximal number of SMTP sessions per delivery request before
/* giving up or delivering to a fall-back relay host, or zero (no
/* limit).
/* .IP "\fBsmtp_rset_timeout (120s)\fR"
/* .IP "\fBsmtp_rset_timeout (20s)\fR"
/* The SMTP client time limit for sending the RSET command, and
/* for receiving the server response.
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBsmtp_connection_cache_destinations (empty)\fR"
/* Permanently enable SMTP connection caching for the specified
/* destinations.
/* .IP "\fBsmtp_connection_cache_on_demand (yes)\fR"
/* Temporarily enable SMTP connection caching while a destination
/* has a high volume of mail in the active queue.
/* .IP "\fBsmtp_connection_cache_reuse_limit (10)\fR"
/* When SMTP connection caching is enabled, the number of times that
/* an SMTP session is reused before it is closed.
/* .IP "\fBsmtp_connection_cache_time_limit (2s)\fR"
/* When SMTP connection caching is enabled, the amount of time that
/* an unused SMTP client socket is kept open before it is closed.
/* TROUBLE SHOOTING CONTROLS
/* .ad
/* .fi
@ -206,8 +314,11 @@
/* Optional list of relay hosts for SMTP destinations that can't be
/* found or that are unreachable.
/* .IP "\fBinet_interfaces (all)\fR"
/* The network interface addresses that this mail system receives mail
/* on.
/* The network interface addresses that this mail system receives
/* mail on.
/* .IP "\fBinet_protocols (ipv4)\fR"
/* The Internet protocols Postfix will attempt to use when making
/* or accepting connections.
/* .IP "\fBipc_timeout (3600s)\fR"
/* The time limit for sending or receiving information over an internal
/* communication channel.
@ -226,7 +337,10 @@
/* on by way of a proxy or network address translation unit.
/* .IP "\fBsmtp_bind_address (empty)\fR"
/* An optional numerical network address that the SMTP client should
/* bind to when making a connection.
/* bind to when making an IPv4 connection.
/* .IP "\fBsmtp_bind_address6 (empty)\fR"
/* An optional numerical network address that the SMTP client should
/* bind to when making an IPv6 connection.
/* .IP "\fBsmtp_helo_name ($myhostname)\fR"
/* The hostname to send in the SMTP EHLO or HELO command.
/* .IP "\fBsmtp_host_lookup (dns)\fR"
@ -242,8 +356,11 @@
/* SEE ALSO
/* qmgr(8), queue manager
/* bounce(8), delivery status reports
/* scache(8), connection cache server
/* postconf(5), configuration parameters
/* master(5), generic daemon options
/* master(8), process manager
/* tlsmgr(8), TLS session and PRNG management
/* syslogd(8), system logging
/* README FILES
/* .ad
@ -253,6 +370,7 @@
/* .na
/* .nf
/* SASL_README, Postfix SASL howto
/* TLS_README, Postfix STARTTLS howto
/* LICENSE
/* .ad
/* .fi
@ -262,6 +380,25 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Command pipelining in cooperation with:
/* Jon Ribbens
/* Oaktree Internet Solutions Ltd.,
/* Internet House,
/* Canal Basin,
/* Coventry,
/* CV1 4LY, United Kingdom.
/*
/* Connection caching in cooperation with:
/* Victor Duchovni
/* Morgan Stanley
/*
/* TLS support originally by:
/* Lutz Jaenicke
/* BTU Cottbus
/* Allgemeine Elektrotechnik
/* Universitaetsplatz 3-4
/* D-03044 Cottbus, Germany
/*--*/
/* System library. */
@ -286,6 +423,10 @@
#include <mail_conf.h>
#include <debug_peer.h>
#include <flush_clnt.h>
#include <scache.h>
#include <string_list.h>
#include <maps.h>
#include <ext_prop.h>
/* Single server skeleton. */
@ -323,7 +464,9 @@ int var_smtp_never_ehlo;
char *var_smtp_sasl_opts;
char *var_smtp_sasl_passwd;
bool var_smtp_sasl_enable;
char *var_smtp_sasl_mechs;
char *var_smtp_bind_addr;
char *var_smtp_bind_addr6;
bool var_smtp_rand_addr;
int var_smtp_pix_thresh;
int var_smtp_pix_delay;
@ -335,6 +478,27 @@ bool var_smtp_defer_mxaddr;
bool var_smtp_send_xforward;
int var_smtp_mxaddr_limit;
int var_smtp_mxsess_limit;
int var_smtp_cache_conn;
int var_smtp_reuse_limit;
char *var_smtp_cache_dest;
char *var_scache_service;
bool var_smtp_cache_demand;
char *var_smtp_ehlo_dis_words;
char *var_smtp_ehlo_dis_maps;
bool var_smtp_use_tls;
bool var_smtp_enforce_tls;
char *var_smtp_tls_per_site;
#ifdef USE_TLS
int var_smtp_starttls_tmout;
char *var_smtp_sasl_tls_opts;
bool var_smtp_tls_enforce_peername;
int var_smtp_tls_scert_vd;
bool var_smtp_tls_note_starttls_offer;
#endif
char *var_smtp_generic_maps;
char *var_prop_extension;
/*
* Global variables. smtp_errno is set by the address lookup routines and by
@ -342,10 +506,24 @@ int var_smtp_mxsess_limit;
*/
int smtp_errno;
int smtp_host_lookup_mask;
STRING_LIST *smtp_cache_dest;
SCACHE *smtp_scache;
MAPS *smtp_ehlo_dis_maps;
MAPS *smtp_generic_maps;
int smtp_ext_prop_mask;
#ifdef USE_TLS
/*
* OpenSSL client state.
*/
SSL_CTX *smtp_tls_ctx;
#endif
/* deliver_message - deliver message with extreme prejudice */
static int deliver_message(DELIVER_REQUEST *request)
static int deliver_message(const char *service, DELIVER_REQUEST *request)
{
SMTP_STATE *state;
int result;
@ -371,6 +549,7 @@ static int deliver_message(DELIVER_REQUEST *request)
state = smtp_state_alloc();
state->request = request;
state->src = request->fp;
state->service = service;
SMTP_RCPT_INIT(state);
/*
@ -384,7 +563,6 @@ static int deliver_message(DELIVER_REQUEST *request)
/*
* Clean up.
*/
smtp_chat_reset(state);
smtp_state_free(state);
return (result);
@ -392,7 +570,7 @@ static int deliver_message(DELIVER_REQUEST *request)
/* smtp_service - perform service for client */
static void smtp_service(VSTREAM *client_stream, char *unused_service, char **argv)
static void smtp_service(VSTREAM *client_stream, char *service, char **argv)
{
DELIVER_REQUEST *request;
int status;
@ -412,14 +590,14 @@ static void smtp_service(VSTREAM *client_stream, char *unused_service, char **ar
* the common code in single_server.c.
*/
if ((request = deliver_request_read(client_stream)) != 0) {
status = deliver_message(request);
status = deliver_message(service, request);
deliver_request_done(client_stream, request, status);
}
}
/* pre_init - pre-jail initialization */
/* post_init - post-jail initialization */
static void pre_init(char *unused_name, char **unused_argv)
static void post_init(char *unused_name, char **unused_argv)
{
static NAME_MASK lookup_masks[] = {
SMTP_HOST_LOOKUP_DNS, SMTP_HOST_FLAG_DNS,
@ -427,11 +605,6 @@ static void pre_init(char *unused_name, char **unused_argv)
0,
};
/*
* Turn on per-peer debugging.
*/
debug_peer_init();
/*
* Select hostname lookup mechanisms.
*/
@ -445,6 +618,29 @@ static void pre_init(char *unused_name, char **unused_argv)
str_name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
smtp_host_lookup_mask));
/*
* Session cache instance.
*/
if (*var_smtp_cache_dest || var_smtp_cache_demand)
#if 0
smtp_scache = scache_multi_create();
#else
smtp_scache = scache_clnt_create(var_scache_service,
var_ipc_idle_limit,
var_ipc_ttl_limit);
#endif
}
/* pre_init - pre-jail initialization */
static void pre_init(char *unused_name, char **unused_argv)
{
/*
* Turn on per-peer debugging.
*/
debug_peer_init();
/*
* SASL initialization.
*/
@ -456,10 +652,47 @@ static void pre_init(char *unused_name, char **unused_argv)
VAR_SMTP_SASL_ENABLE);
#endif
/*
* Initialize the TLS data before entering the chroot jail
*/
if (var_smtp_use_tls || var_smtp_enforce_tls || var_smtp_tls_per_site[0]) {
#ifdef USE_TLS
smtp_tls_ctx = tls_client_init(var_smtp_tls_scert_vd);
smtp_tls_list_init();
#else
msg_warn("TLS has been selected, but TLS support is not compiled in");
#endif
}
/*
* Flush client.
*/
flush_init();
/*
* Session cache domain list.
*/
if (*var_smtp_cache_dest)
smtp_cache_dest = string_list_init(MATCH_FLAG_NONE, var_smtp_cache_dest);
/*
* EHLO keyword filter.
*/
if (*var_smtp_ehlo_dis_maps)
smtp_ehlo_dis_maps = maps_create(VAR_SMTPD_EHLO_DIS_MAPS,
var_smtp_ehlo_dis_maps,
DICT_FLAG_LOCK);
/*
* Generic maps.
*/
if (*var_prop_extension)
smtp_ext_prop_mask =
ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension);
if (*var_smtp_generic_maps)
smtp_generic_maps =
maps_create(VAR_SMTP_GENERIC_MAPS, var_smtp_generic_maps,
DICT_FLAG_LOCK);
}
/* pre_accept - see if tables have changed */
@ -495,9 +728,21 @@ int main(int argc, char **argv)
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
#ifdef USE_TLS
VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
#endif
VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
VAR_SMTP_HOST_LOOKUP, DEF_SMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0,
VAR_SMTP_CACHE_DEST, DEF_SMTP_CACHE_DEST, &var_smtp_cache_dest, 0, 0,
VAR_SCACHE_SERVICE, DEF_SCACHE_SERVICE, &var_scache_service, 1, 0,
VAR_SMTP_EHLO_DIS_WORDS, DEF_SMTP_EHLO_DIS_WORDS, &var_smtp_ehlo_dis_words, 0, 0,
VAR_SMTP_EHLO_DIS_MAPS, DEF_SMTP_EHLO_DIS_MAPS, &var_smtp_ehlo_dis_maps, 0, 0,
VAR_SMTP_TLS_PER_SITE, DEF_SMTP_TLS_PER_SITE, &var_smtp_tls_per_site, 0, 0,
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
VAR_SMTP_GENERIC_MAPS, DEF_SMTP_GENERIC_MAPS, &var_smtp_generic_maps, 0, 0,
0,
};
static CONFIG_TIME_TABLE time_table[] = {
@ -513,12 +758,20 @@ int main(int argc, char **argv)
VAR_SMTP_QUIT_TMOUT, DEF_SMTP_QUIT_TMOUT, &var_smtp_quit_tmout, 1, 0,
VAR_SMTP_PIX_THRESH, DEF_SMTP_PIX_THRESH, &var_smtp_pix_thresh, 0, 0,
VAR_SMTP_PIX_DELAY, DEF_SMTP_PIX_DELAY, &var_smtp_pix_delay, 1, 0,
VAR_SMTP_CACHE_CONN, DEF_SMTP_CACHE_CONN, &var_smtp_cache_conn, 1, 0,
#ifdef USE_TLS
VAR_SMTP_STARTTLS_TMOUT, DEF_SMTP_STARTTLS_TMOUT, &var_smtp_starttls_tmout, 1, 0,
#endif
0,
};
static CONFIG_INT_TABLE int_table[] = {
VAR_SMTP_LINE_LIMIT, DEF_SMTP_LINE_LIMIT, &var_smtp_line_limit, 0, 0,
VAR_SMTP_MXADDR_LIMIT, DEF_SMTP_MXADDR_LIMIT, &var_smtp_mxaddr_limit, 0, 0,
VAR_SMTP_MXSESS_LIMIT, DEF_SMTP_MXSESS_LIMIT, &var_smtp_mxsess_limit, 0, 0,
VAR_SMTP_REUSE_LIMIT, DEF_SMTP_REUSE_LIMIT, &var_smtp_reuse_limit, 1, 0,
#ifdef USE_TLS
VAR_SMTP_TLS_SCERT_VD, DEF_SMTP_TLS_SCERT_VD, &var_smtp_tls_scert_vd, 0, 0,
#endif
0,
};
static CONFIG_BOOL_TABLE bool_table[] = {
@ -532,6 +785,14 @@ int main(int argc, char **argv)
VAR_SMTP_QUOTE_821_ENV, DEF_SMTP_QUOTE_821_ENV, &var_smtp_quote_821_env,
VAR_SMTP_DEFER_MXADDR, DEF_SMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
VAR_SMTP_SEND_XFORWARD, DEF_SMTP_SEND_XFORWARD, &var_smtp_send_xforward,
VAR_SMTP_CACHE_DEMAND, DEF_SMTP_CACHE_DEMAND, &var_smtp_cache_demand,
VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls,
VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_tls,
#ifdef USE_TLS
VAR_SMTP_TLS_ENFORCE_PN, DEF_SMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername,
VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
#endif
0,
};
@ -541,6 +802,7 @@ int main(int argc, char **argv)
MAIL_SERVER_STR_TABLE, str_table,
MAIL_SERVER_BOOL_TABLE, bool_table,
MAIL_SERVER_PRE_INIT, pre_init,
MAIL_SERVER_POST_INIT, post_init,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
MAIL_SERVER_EXIT, pre_exit,
0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp.h,v 1.1.1.5 2004/05/31 00:24:46 heas Exp $ */
/* $NetBSD: smtp.h,v 1.1.1.6 2005/08/18 21:08:50 rpaulo Exp $ */
/*++
/* NAME
@ -24,39 +24,54 @@
#include <vstream.h>
#include <vstring.h>
#include <argv.h>
#include <htable.h>
/*
* Global library.
*/
#include <deliver_request.h>
#include <scache.h>
#include <string_list.h>
#include <maps.h>
#include <tok822.h>
/*
* State information associated with each SMTP delivery. We're bundling the
* state so that we can give meaningful diagnostics in case of problems.
* Postfix TLS library.
*/
#ifdef USE_TLS
#include <tls.h>
#endif
/*
* State information associated with each SMTP delivery request.
* Session-specific state is stored separately.
*/
typedef struct SMTP_STATE {
VSTREAM *src; /* queue file stream */
const char *service; /* transport name */
DELIVER_REQUEST *request; /* envelope info, offsets */
struct SMTP_SESSION *session; /* network connection */
VSTRING *buffer; /* I/O buffer */
VSTRING *scratch; /* scratch buffer */
VSTRING *scratch2; /* scratch buffer */
int status; /* delivery status */
int features; /* server features */
ARGV *history; /* transaction log */
int error_mask; /* error classes */
#ifdef USE_SASL_AUTH
char *sasl_mechanism_list; /* server mechanism list */
char *sasl_username; /* client username */
char *sasl_passwd; /* client password */
sasl_conn_t *sasl_conn; /* SASL internal state */
VSTRING *sasl_encoded; /* encoding buffer */
VSTRING *sasl_decoded; /* decoding buffer */
sasl_callback_t *sasl_callbacks; /* stateful callbacks */
#endif
off_t size_limit; /* server limit or unknown */
int space_left; /* output length control */
struct MIME_STATE *mime_state; /* mime state machine */
/*
* Connection cache support. The (nexthop_lookup_mx, nexthop_domain,
* nexthop_port) triple is a parsed next-hop specification, and should be
* a data type by itself. The (service, nexthop_mumble) members specify
* the name under which the first good connection should be cached. The
* nexthop_mumble members are initialized by the connection management
* module. nexthop_domain is reset to null after one connection is saved
* under the (service, nexthop_mumble) label, or upon exit from the
* connection management module.
*/
HTABLE *cache_used; /* cached addresses that were used */
VSTRING *dest_label; /* cached logical/physical binding */
VSTRING *dest_prop; /* binding properties, passivated */
VSTRING *endp_label; /* cached session physical endpoint */
VSTRING *endp_prop; /* endpoint properties, passivated */
int nexthop_lookup_mx; /* do/don't MX expand nexthop_domain */
char *nexthop_domain; /* next-hop name or bare address */
unsigned nexthop_port; /* next-hop TCP port, network order */
/*
* Flags and counters to control the handling of mail delivery errors.
@ -69,6 +84,20 @@ typedef struct SMTP_STATE {
int rcpt_keep; /* recipients marked as keep */
} SMTP_STATE;
#define SET_NEXTHOP_STATE(state, lookup_mx, domain, port) { \
(state)->nexthop_lookup_mx = lookup_mx; \
(state)->nexthop_domain = mystrdup(domain); \
(state)->nexthop_port = port; \
}
#define FREE_NEXTHOP_STATE(state) { \
myfree((state)->nexthop_domain); \
(state)->nexthop_domain = 0; \
}
#define HAVE_NEXTHOP_STATE(state) ((state)->nexthop_domain != 0)
/*
* Server features.
*/
@ -83,11 +112,28 @@ typedef struct SMTP_STATE {
#define SMTP_FEATURE_XFORWARD_ADDR (1<<8)
#define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
#define SMTP_FEATURE_XFORWARD_DOMAIN (1<<11)
#define SMTP_FEATURE_BEST_MX (1<<12) /* for next-hop or fall-back */
#define SMTP_FEATURE_RSET_REJECTED (1<<13) /* RSET probe rejected */
#define SMTP_FEATURE_FROM_CACHE (1<<14) /* cached connection */
/*
* Features that passivate under the endpoint.
*/
#define SMTP_FEATURE_ENDPOINT_MASK \
(~(SMTP_FEATURE_BEST_MX | SMTP_FEATURE_RSET_REJECTED \
| SMTP_FEATURE_FROM_CACHE))
/*
* Features that passivate under the logical destination.
*/
#define SMTP_FEATURE_DESTINATION_MASK (SMTP_FEATURE_BEST_MX)
/*
* Misc flags.
*/
#define SMTP_MISC_FLAG_LOOP_DETECT (1<<0)
#define SMTP_MISC_FLAG_IN_STARTTLS (1<<1)
#define SMTP_MISC_FLAG_DEFAULT SMTP_MISC_FLAG_LOOP_DETECT
@ -106,19 +152,84 @@ extern int smtp_host_lookup_mask; /* host lookup methods to use */
#define SMTP_HOST_FLAG_DNS (1<<0)
#define SMTP_HOST_FLAG_NATIVE (1<<1)
extern SCACHE *smtp_scache; /* connection cache instance */
extern STRING_LIST *smtp_cache_dest; /* cached destinations */
extern MAPS *smtp_ehlo_dis_maps; /* ehlo keyword filter */
extern MAPS *smtp_generic_maps; /* make internal address valid */
extern int smtp_ext_prop_mask; /* address externsion propagation */
#ifdef USE_TLS
extern SSL_CTX *smtp_tls_ctx; /* client-side TLS engine */
#endif
/*
* smtp_session.c
*/
typedef struct SMTP_SESSION {
VSTREAM *stream; /* network connection */
char *dest; /* nexthop or fallback */
char *host; /* mail exchanger */
char *addr; /* mail exchanger */
char *namaddr; /* mail exchanger */
int best; /* most preferred host */
char *helo; /* helo response */
unsigned port; /* network byte order */
VSTRING *buffer; /* I/O buffer */
VSTRING *scratch; /* scratch buffer */
VSTRING *scratch2; /* scratch buffer */
int features; /* server features */
off_t size_limit; /* server limit or unknown */
ARGV *history; /* transaction log */
int error_mask; /* error classes */
struct MIME_STATE *mime_state; /* mime state machine */
int sndbufsize; /* PIPELINING buffer size */
int send_proto_helo; /* XFORWARD support */
int reuse_count; /* how many uses left */
#ifdef USE_SASL_AUTH
char *sasl_mechanism_list; /* server mechanism list */
char *sasl_username; /* client username */
char *sasl_passwd; /* client password */
sasl_conn_t *sasl_conn; /* SASL internal state */
VSTRING *sasl_encoded; /* encoding buffer */
VSTRING *sasl_decoded; /* decoding buffer */
sasl_callback_t *sasl_callbacks; /* stateful callbacks */
#endif
/*
* TLS related state.
*/
#ifdef USE_TLS
int tls_use_tls; /* can do TLS */
int tls_enforce_tls; /* must do TLS */
int tls_enforce_peername; /* cert must match */
TLScontext_t *tls_context; /* TLS session state */
tls_info_t tls_info; /* legacy */
#endif
} SMTP_SESSION;
extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, char *, char *);
extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, const char *,
const char *, const char *, unsigned, int);
extern void smtp_session_free(SMTP_SESSION *);
extern int smtp_session_passivate(SMTP_SESSION *, VSTRING *, VSTRING *);
extern SMTP_SESSION *smtp_session_activate(int, VSTRING *, VSTRING *);
#define SMTP_SESS_FLAG_NONE 0 /* no options */
#define SMTP_SESS_FLAG_CACHE (1<<0) /* enable session caching */
#ifdef USE_TLS
extern void smtp_tls_list_init(void);
#endif
/*
* smtp_connect.c
@ -130,7 +241,8 @@ extern int smtp_connect(SMTP_STATE *);
*/
extern int smtp_helo(SMTP_STATE *, int);
extern int smtp_xfer(SMTP_STATE *);
extern void smtp_quit(SMTP_STATE *);
extern int smtp_rset(SMTP_STATE *);
extern int smtp_quit(SMTP_STATE *);
/*
* smtp_chat.c
@ -141,10 +253,11 @@ typedef struct SMTP_RESP { /* server response */
VSTRING *buf; /* origin of text */
} SMTP_RESP;
extern void PRINTFLIKE(2, 3) smtp_chat_cmd(SMTP_STATE *, char *,...);
extern SMTP_RESP *smtp_chat_resp(SMTP_STATE *);
extern void smtp_chat_reset(SMTP_STATE *);
extern void smtp_chat_notify(SMTP_STATE *);
extern void PRINTFLIKE(2, 3) smtp_chat_cmd(SMTP_SESSION *, char *,...);
extern SMTP_RESP *smtp_chat_resp(SMTP_SESSION *);
extern void smtp_chat_init(SMTP_SESSION *);
extern void smtp_chat_reset(SMTP_SESSION *);
extern void smtp_chat_notify(SMTP_SESSION *);
/*
* These operations implement a redundant mark-and-sweep algorithm that
@ -208,6 +321,13 @@ extern VSTRING *smtp_unalias_addr(VSTRING *, const char *);
extern SMTP_STATE *smtp_state_alloc(void);
extern void smtp_state_free(SMTP_STATE *);
/*
* smtp_map11.c
*/
extern int smtp_map11_external(VSTRING *, MAPS *, int);
extern int smtp_map11_tree(TOK822 *, MAPS *, int);
extern int smtp_map11_internal(VSTRING *, MAPS *, int);
/* LICENSE
/* .ad
/* .fi
@ -217,4 +337,11 @@ extern void smtp_state_free(SMTP_STATE *);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* TLS support originally by:
/* Lutz Jaenicke
/* BTU Cottbus
/* Allgemeine Elektrotechnik
/* Universitaetsplatz 3-4
/* D-03044 Cottbus, Germany
/*--*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_addr.h,v 1.1.1.3 2004/05/31 00:24:46 heas Exp $ */
/* $NetBSD: smtp_addr.h,v 1.1.1.4 2005/08/18 21:08:51 rpaulo Exp $ */
/*++
/* NAME
@ -19,7 +19,7 @@
* Internal interfaces.
*/
extern DNS_RR *smtp_host_addr(char *, int, VSTRING *);
extern DNS_RR *smtp_domain_addr(char *, int, VSTRING *);
extern DNS_RR *smtp_domain_addr(char *, int, VSTRING *, int *);
/* LICENSE
/* .ad

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_chat.c,v 1.1.1.6 2004/11/13 05:05:53 heas Exp $ */
/* $NetBSD: smtp_chat.c,v 1.1.1.7 2005/08/18 21:08:51 rpaulo Exp $ */
/*++
/* NAME
@ -16,18 +16,21 @@
/* .in -4
/* } SMTP_RESP;
/*
/* void smtp_chat_cmd(state, format, ...)
/* SMTP_STATE *state;
/* void smtp_chat_cmd(session, format, ...)
/* SMTP_SESSION *session;
/* char *format;
/*
/* SMTP_RESP *smtp_chat_resp(state)
/* SMTP_STATE *state;
/* SMTP_RESP *smtp_chat_resp(session)
/* SMTP_SESSION *session;
/*
/* void smtp_chat_notify(state)
/* SMTP_STATE *state;
/* void smtp_chat_notify(session)
/* SMTP_SESSION *session;
/*
/* void smtp_chat_reset(state)
/* SMTP_STATE *state;
/* void smtp_chat_init(session)
/* SMTP_SESSION *session;
/*
/* void smtp_chat_reset(session)
/* SMTP_SESSION *session;
/* DESCRIPTION
/* This module implements SMTP client support for request/reply
/* conversations, and maintains a limited SMTP transaction log.
@ -45,6 +48,9 @@
/* when delivery is possible immediately. It is an error to call
/* smtp_chat_notify() when no SMTP transaction log exists.
/*
/* smtp_chat_init() initializes the per-session transaction log.
/* This must be done at the beginning of a new SMTP session.
/*
/* smtp_chat_reset() resets the transaction log. This is
/* typically done at the beginning or end of an SMTP session,
/* or within a session to discard non-error information.
@ -102,60 +108,72 @@
#define STR(x) ((char *) vstring_str(x))
#define LEN VSTRING_LEN
/* smtp_chat_init - initialize SMTP transaction log */
void smtp_chat_init(SMTP_SESSION *session)
{
session->history = 0;
}
/* smtp_chat_reset - reset SMTP transaction log */
void smtp_chat_reset(SMTP_STATE *state)
void smtp_chat_reset(SMTP_SESSION *session)
{
if (state->history) {
argv_free(state->history);
state->history = 0;
if (session->history) {
argv_free(session->history);
session->history = 0;
}
}
/* smtp_chat_append - append record to SMTP transaction log */
static void smtp_chat_append(SMTP_STATE *state, char *direction, char *data)
static void smtp_chat_append(SMTP_SESSION *session, char *direction, char *data)
{
char *line;
if (state->history == 0)
state->history = argv_alloc(10);
if (session->history == 0)
session->history = argv_alloc(10);
line = concatenate(direction, data, (char *) 0);
argv_add(state->history, line, (char *) 0);
argv_add(session->history, line, (char *) 0);
myfree(line);
}
/* smtp_chat_cmd - send an SMTP command */
void smtp_chat_cmd(SMTP_STATE *state, char *fmt,...)
void smtp_chat_cmd(SMTP_SESSION *session, char *fmt,...)
{
SMTP_SESSION *session = state->session;
va_list ap;
/*
* Format the command, and update the transaction log.
*/
va_start(ap, fmt);
vstring_vsprintf(state->buffer, fmt, ap);
vstring_vsprintf(session->buffer, fmt, ap);
va_end(ap);
smtp_chat_append(state, "Out: ", STR(state->buffer));
smtp_chat_append(session, "Out: ", STR(session->buffer));
/*
* Optionally log the command first, so we can see in the log what the
* program is trying to do.
*/
if (msg_verbose)
msg_info("> %s: %s", session->namaddr, STR(state->buffer));
msg_info("> %s: %s", session->namaddr, STR(session->buffer));
/*
* Send the command to the SMTP server.
*/
smtp_fputs(STR(state->buffer), LEN(state->buffer), session->stream);
smtp_fputs(STR(session->buffer), LEN(session->buffer), session->stream);
/*
* This code is in the wrong place and can run before an I/O error
* handler is set up. To make matters worse, this code pre-empts better
* output flushing code that sits in the smtp_xfer() routine.
* Force flushing of output does not belong here. It is done in the
* smtp_loop() main protocol loop when reading the server response, and
* in smtp_helo() when reading the EHLO response after sending the EHLO
* command.
*
* If we do forced flush here, then we must longjmp() on error, and a
* matching "prepare for disaster" error handler must be set up before
* every smtp_chat_cmd() call.
*/
#if 0
@ -177,12 +195,12 @@ void smtp_chat_cmd(SMTP_STATE *state, char *fmt,...)
/* smtp_chat_resp - read and process SMTP server response */
SMTP_RESP *smtp_chat_resp(SMTP_STATE *state)
SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session)
{
SMTP_SESSION *session = state->session;
static SMTP_RESP rdata;
char *cp;
int last_char;
int three_digs = 0;
/*
* Initialize the response data buffer.
@ -197,13 +215,13 @@ SMTP_RESP *smtp_chat_resp(SMTP_STATE *state)
*/
VSTRING_RESET(rdata.buf);
for (;;) {
last_char = smtp_get(state->buffer, session->stream, var_line_limit);
printable(STR(state->buffer), '?');
last_char = smtp_get(session->buffer, session->stream, var_line_limit);
printable(STR(session->buffer), '?');
if (last_char != '\n')
msg_warn("%s: response longer than %d: %.30s...",
session->namaddr, var_line_limit, STR(state->buffer));
session->namaddr, var_line_limit, STR(session->buffer));
if (msg_verbose)
msg_info("< %s: %.100s", session->namaddr, STR(state->buffer));
msg_info("< %s: %.100s", session->namaddr, STR(session->buffer));
/*
* Defend against a denial of service attack by limiting the amount
@ -212,8 +230,8 @@ SMTP_RESP *smtp_chat_resp(SMTP_STATE *state)
if (LEN(rdata.buf) < var_line_limit) {
if (VSTRING_LEN(rdata.buf))
VSTRING_ADDCH(rdata.buf, '\n');
vstring_strcat(rdata.buf, STR(state->buffer));
smtp_chat_append(state, "In: ", STR(state->buffer));
vstring_strcat(rdata.buf, STR(session->buffer));
smtp_chat_append(session, "In: ", STR(session->buffer));
}
/*
@ -221,17 +239,20 @@ SMTP_RESP *smtp_chat_resp(SMTP_STATE *state)
* that any character except space (or end of line) will have the
* same effect as the '-' line continuation character.
*/
for (cp = STR(state->buffer); *cp && ISDIGIT(*cp); cp++)
for (cp = STR(session->buffer); *cp && ISDIGIT(*cp); cp++)
/* void */ ;
if (cp - STR(state->buffer) == 3) {
if ((three_digs = (cp - STR(session->buffer) == 3)) != 0) {
if (*cp == '-')
continue;
if (*cp == ' ' || *cp == 0)
break;
}
state->error_mask |= MAIL_ERROR_PROTOCOL;
session->error_mask |= MAIL_ERROR_PROTOCOL;
}
rdata.code = atoi(STR(state->buffer));
if (three_digs != 0)
rdata.code = atoi(STR(session->buffer));
else
rdata.code = 0;
VSTRING_TERMINATE(rdata.buf);
rdata.str = STR(rdata.buf);
return (&rdata);
@ -248,17 +269,16 @@ static void print_line(const char *str, int len, int indent, char *context)
/* smtp_chat_notify - notify postmaster */
void smtp_chat_notify(SMTP_STATE *state)
void smtp_chat_notify(SMTP_SESSION *session)
{
char *myname = "smtp_chat_notify";
SMTP_SESSION *session = state->session;
VSTREAM *notice;
char **cpp;
/*
* Sanity checks.
*/
if (state->history == 0)
if (session->history == 0)
msg_panic("%s: no conversation history", myname);
if (msg_verbose)
msg_info("%s: notify postmaster", myname);
@ -292,8 +312,8 @@ void smtp_chat_notify(SMTP_STATE *state)
post_mail_fputs(notice, "");
post_mail_fputs(notice, "Transcript of session follows.");
post_mail_fputs(notice, "");
argv_terminate(state->history);
for (cpp = state->history->argv; *cpp; cpp++)
argv_terminate(session->history);
for (cpp = session->history->argv; *cpp; cpp++)
line_wrap(printable(*cpp, '?'), LENGTH, INDENT, print_line,
(char *) notice);
(void) post_mail_fclose(notice);

171
gnu/dist/postfix/src/smtp/smtp_map11.c vendored Normal file
View File

@ -0,0 +1,171 @@
/* $NetBSD: smtp_map11.c,v 1.1.1.1 2005/08/18 21:08:58 rpaulo Exp $ */
/*++
/* NAME
/* smtp_map11 3
/* SUMMARY
/* one-to-one address mapping
/* SYNOPSIS
/* #include <smtp.h>
/*
/* int smtp_map11_external(addr, maps, propagate)
/* VSTRING *addr;
/* MAPS *maps;
/* int propagate;
/*
/* int smtp_map11_internal(addr, maps, propagate)
/* VSTRING *addr;
/* MAPS *maps;
/* int propagate;
/*
/* int smtp_map11_tree(tree, maps, propagate)
/* TOK822 *tree;
/* MAPS *maps;
/* int propagate;
/* DESCRIPTION
/* This module performs non-recursive one-to-one address mapping.
/* An unmatched address extension is propagated when
/* \fIpropagate\fR is non-zero.
/*
/* smtp_map11_external() looks up the RFC 822 external (quoted) string
/* form of an address in the maps specified via the \fImaps\fR argument.
/*
/* smtp_map11_internal() is a wrapper around the
/* smtp_map11_external() routine that transforms from
/* internal (quoted) string form to external form and back.
/*
/* smtp_map11_tree() is a wrapper around the
/* smtp_map11_external() routine that transforms from
/* internal parse tree form to external form and back.
/* DIAGNOSTICS
/* Table lookup errors are fatal.
/* SEE ALSO
/* mail_addr_map(3) address mappings
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
/* Utility library. */
#include <msg.h>
#include <vstring.h>
#include <dict.h>
#include <argv.h>
#include <tok822.h>
#include <valid_hostname.h>
/* Global library. */
#include <mail_addr_map.h>
#include <quote_822_local.h>
/* Application-specific. */
#include <smtp.h>
#define STR vstring_str
/* smtp_map11_external - one-to-one table lookups */
int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate)
{
const char *myname = "smtp_map11_external";
ARGV *new_addr;
const char *result;
if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) {
if (new_addr->argc > 1)
msg_warn("multi-valued %s result for %s", maps->title, STR(addr));
result = new_addr->argv[0];
if (msg_verbose)
msg_info("%s: %s -> %s", myname, STR(addr), result);
vstring_strcpy(addr, result);
argv_free(new_addr);
return (1);
} else {
if (dict_errno != 0)
msg_fatal("%s map lookup problem for %s", maps->title, STR(addr));
if (msg_verbose)
msg_info("%s: %s not found", myname, STR(addr));
return (0);
}
}
/* smtp_map11_tree - rewrite address node */
int smtp_map11_tree(TOK822 *tree, MAPS *maps, int propagate)
{
VSTRING *temp = vstring_alloc(100);
int ret;
tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
ret = smtp_map11_external(temp, maps, propagate);
tok822_free_tree(tree->head);
tree->head = tok822_scan(STR(temp), &tree->tail);
vstring_free(temp);
return (ret);
}
/* smtp_map11_internal - rewrite address internal form */
int smtp_map11_internal(VSTRING *addr, MAPS *maps, int propagate)
{
VSTRING *temp = vstring_alloc(100);
int ret;
quote_822_local(temp, STR(addr));
ret = smtp_map11_external(temp, maps, propagate);
unquote_822_local(addr, STR(temp));
vstring_free(temp);
return (ret);
}
#ifdef TEST
#include <msg_vstream.h>
#include <stringops.h>
#include <mail_params.h>
int main(int argc, char **argv)
{
VSTRING *buf = vstring_alloc(100);
MAPS *maps;
msg_vstream_init(basename(argv[0]), VSTREAM_ERR);
if (argc < 3)
msg_fatal("usage: %s maptype:mapname address...", argv[0]);
maps = maps_create(argv[1], argv[1], 0);
mail_params_init();
if (chdir(var_queue_dir) < 0)
msg_fatal("chdir(%s): %m", var_queue_dir);
argv += 1;
msg_verbose = 1;
while (--argc && *++argv) {
msg_info("-- start %s --", *argv);
smtp_map11_external(vstring_strcpy(buf, *argv), maps, 1);
msg_info("-- end %s --", *argv);
}
vstring_free(buf);
maps_free(maps);
return (0);
}
#endif

View File

@ -0,0 +1,66 @@
smtp_map11: -- start foo@example.com --
smtp_map11: maps_find: hash:map11_map: hash:map11_map(0,0): foo@example.com = bar@com.example
smtp_map11: mail_addr_find: foo@example.com -> bar@com.example
smtp_map11: connect to subsystem private/rewrite
smtp_map11: send attr request = rewrite
smtp_map11: send attr rule = local
smtp_map11: send attr address = bar@com.example
smtp_map11: private/rewrite socket: wanted attribute: flags
smtp_map11: input attribute name: flags
smtp_map11: input attribute value: 0
smtp_map11: private/rewrite socket: wanted attribute: address
smtp_map11: input attribute name: address
smtp_map11: input attribute value: bar@com.example
smtp_map11: private/rewrite socket: wanted attribute: (list terminator)
smtp_map11: input attribute name: (end)
smtp_map11: rewrite_clnt: local: bar@com.example -> bar@com.example
smtp_map11: mail_addr_map: foo@example.com -> 0: bar@com.example
smtp_map11: smtp_map11_external: foo@example.com -> bar@com.example
smtp_map11: -- end foo@example.com --
smtp_map11: -- start bar@example.com --
smtp_map11: maps_find: hash:map11_map: hash:map11_map(0,0): bar@example.com = bar
smtp_map11: mail_addr_find: bar@example.com -> bar
smtp_map11: send attr request = rewrite
smtp_map11: send attr rule = local
smtp_map11: send attr address = bar
smtp_map11: private/rewrite socket: wanted attribute: flags
smtp_map11: input attribute name: flags
smtp_map11: input attribute value: 0
smtp_map11: private/rewrite socket: wanted attribute: address
smtp_map11: input attribute name: address
smtp_map11: input attribute value: bar@MYDOMAIN
smtp_map11: private/rewrite socket: wanted attribute: (list terminator)
smtp_map11: input attribute name: (end)
smtp_map11: rewrite_clnt: local: bar -> bar@MYDOMAIN
smtp_map11: mail_addr_map: bar@example.com -> 0: bar@MYDOMAIN
smtp_map11: smtp_map11_external: bar@example.com -> bar@MYDOMAIN
smtp_map11: -- end bar@example.com --
smtp_map11: -- start baz@example.com --
smtp_map11: maps_find: hash:map11_map: hash:map11_map(0,0): baz@example.com = @com.example
smtp_map11: mail_addr_find: baz@example.com -> @com.example
smtp_map11: send attr request = rewrite
smtp_map11: send attr rule = local
smtp_map11: send attr address = baz@com.example
smtp_map11: private/rewrite socket: wanted attribute: flags
smtp_map11: input attribute name: flags
smtp_map11: input attribute value: 0
smtp_map11: private/rewrite socket: wanted attribute: address
smtp_map11: input attribute name: address
smtp_map11: input attribute value: baz@com.example
smtp_map11: private/rewrite socket: wanted attribute: (list terminator)
smtp_map11: input attribute name: (end)
smtp_map11: rewrite_clnt: local: baz@com.example -> baz@com.example
smtp_map11: mail_addr_map: baz@example.com -> 0: baz@com.example
smtp_map11: smtp_map11_external: baz@example.com -> baz@com.example
smtp_map11: -- end baz@example.com --
smtp_map11: -- start foo@example.net --
smtp_map11: maps_find: hash:map11_map: foo@example.net: not found
smtp_map11: match_string: example.net ~? MYHOSTNAME
smtp_map11: match_string: example.net ~? localhost.MYDOMAIN
smtp_map11: match_string: example.net ~? localhost
smtp_map11: match_list_match: example.net: no match
smtp_map11: maps_find: hash:map11_map: @example.net: not found
smtp_map11: mail_addr_find: foo@example.net -> (not found)
smtp_map11: mail_addr_map: foo@example.net -> (not found)
smtp_map11: smtp_map11_external: foo@example.net not found
smtp_map11: -- end foo@example.net --

File diff suppressed because it is too large Load Diff

266
gnu/dist/postfix/src/smtp/smtp_reuse.c vendored Normal file
View File

@ -0,0 +1,266 @@
/* $NetBSD: smtp_reuse.c,v 1.1.1.1 2005/08/18 21:08:59 rpaulo Exp $ */
/*++
/* NAME
/* smtp_reuse 3
/* SUMMARY
/* SMTP session cache glue
/* SYNOPSIS
/* #include <smtp.h>
/* #include <smtp_reuse.h>
/*
/* void smtp_save_session(state)
/* SMTP_STATE *state;
/*
/* SMTP_SESSION *smtp_reuse_domain(state, lookup_mx, domain, port)
/* SMTP_STATE *state;
/* int lookup_mx;
/* char *domain;
/* unsigned port;
/*
/* SMTP_SESSION *smtp_reuse_addr(state, addr, port)
/* SMTP_STATE *state;
/* DNS_RR *addr;
/* unsigned port;
/* DESCRIPTION
/* This module implements the SMTP client specific interface to
/* the generic session cache infrastructure.
/*
/* smtp_save_session() stores the current session under the
/* next-hop logical destination (if available) and under the
/* remote server address. The SMTP_SESSION object is destroyed.
/*
/* smtp_reuse_domain() looks up a cached session by its logical
/* destination, and verifies that the session is still alive.
/* The restored session information includes the "best MX" bit.
/* The result is null in case of failure.
/*
/* smtp_reuse_addr() looks up a cached session by its server
/* address, and verifies that the session is still alive.
/* The result is null in case of failure.
/*
/* Arguments:
/* .IP state
/* SMTP client state, including the current session, the original
/* next-hop domain, etc.
/* .IP lookup_mx
/* Whether or not the domain is subject to MX lookup.
/* .IP domain
/* Domain name or bare numerical address.
/* .IP addr
/* The remote server name and address.
/* .IP port
/* The remote server port, network byte order.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <vstream.h>
#include <vstring.h>
#include <htable.h>
#include <stringops.h>
/* Global library. */
#include <scache.h>
#include <mail_params.h>
/* Application-specific. */
#include <smtp.h>
#include <smtp_reuse.h>
/*
* We encode the MX lookup/A lookup method into the name under which SMTP
* session information is cached. The following macros serve to make the
* remainder of the code less obscure.
*/
#define NO_MX_LOOKUP 0
#define SMTP_SCACHE_LABEL(mx_lookup_flag) \
((mx_lookup_flag) ? "%s:%s:%u" : "%s:[%s]:%u")
#define STR(x) vstring_str(x)
/* smtp_save_session - save session under next-hop name and server address */
void smtp_save_session(SMTP_STATE *state)
{
SMTP_SESSION *session = state->session;
int fd;
/*
* Encode the next-hop logical destination, if available. Reuse storage
* that is also used for cache lookup queries.
*
* Note: if the label needs to be made more specific (with e.g., SASL login
* information), just append the text with vstring_sprintf_append().
*/
if (HAVE_NEXTHOP_STATE(state))
vstring_sprintf(state->dest_label,
SMTP_SCACHE_LABEL(state->nexthop_lookup_mx),
state->service, state->nexthop_domain,
ntohs(state->nexthop_port));
/*
* Encode the physical endpoint name. Reuse storage that is also used for
* cache lookup queries.
*
* Note: if the label needs to be made more specific (with e.g., SASL login
* information), just append the text with vstring_sprintf_append().
*/
vstring_sprintf(state->endp_label,
SMTP_SCACHE_LABEL(NO_MX_LOOKUP),
state->service, session->addr, ntohs(session->port));
/*
* Passivate the SMTP_SESSION object, destroying the object in the
* process. Reuse storage that is also used for cache lookup results.
*/
fd = smtp_session_passivate(session, state->dest_prop, state->endp_prop);
state->session = 0;
/*
* Save the session under the next-hop name, if available.
*
* XXX The logical to physical binding can be kept for as long as the DNS
* allows us to (but that could result in the caching of lots of unused
* bindings). The session should be idle for no more than 30 seconds or
* so.
*/
if (HAVE_NEXTHOP_STATE(state))
scache_save_dest(smtp_scache, var_smtp_cache_conn, STR(state->dest_label),
STR(state->dest_prop), STR(state->endp_label));
/*
* Save every good session under its physical endpoint address.
*/
scache_save_endp(smtp_scache, var_smtp_cache_conn, STR(state->endp_label),
STR(state->endp_prop), fd);
}
/* smtp_reuse_common - common session reuse code */
static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
const char *label)
{
const char *myname = "smtp_reuse_common";
SMTP_SESSION *session;
/*
* Re-activate the SMTP_SESSION object.
*/
session = smtp_session_activate(fd, state->dest_prop, state->endp_prop);
if (session == 0) {
msg_warn("%s: bad cached session attribute for %s", myname, label);
(void) close(fd);
return (0);
}
state->session = session;
/*
* Send an RSET probe to verify that the session is still good.
*/
if (smtp_rset(state) < 0
|| (session->features & SMTP_FEATURE_RSET_REJECTED) != 0) {
smtp_session_free(session);
return (state->session = 0);
}
/*
* Update the list of used cached addresses.
*/
htable_enter(state->cache_used, session->addr, (char *) 0);
return (session);
}
/* smtp_reuse_domain - reuse session cached under domain name */
SMTP_SESSION *smtp_reuse_domain(SMTP_STATE *state, int lookup_mx,
const char *domain, unsigned port)
{
SMTP_SESSION *session;
int fd;
/*
* Look up the session by its logical name.
*
* Note: if the label needs to be made more specific (with e.g., SASL login
* information), just append the text with vstring_sprintf_append().
*/
vstring_sprintf(state->dest_label, SMTP_SCACHE_LABEL(lookup_mx),
state->service, domain, ntohs(port));
if ((fd = scache_find_dest(smtp_scache, STR(state->dest_label),
state->dest_prop, state->endp_prop)) < 0)
return (0);
/*
* Re-activate the SMTP_SESSION object, and verify that the session is
* still good.
*/
session = smtp_reuse_common(state, fd, STR(state->dest_label));
return (session);
}
/* smtp_reuse_addr - reuse session cached under numerical address */
SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, DNS_RR *addr, unsigned port)
{
MAI_HOSTADDR_STR hostaddr;
SMTP_SESSION *session;
int fd;
/*
* Look up the session by its IP address. This means that we have no
* destination-to-address binding properties.
*
* Note: if the label needs to be made more specific (with e.g., SASL login
* information), just append the text with vstring_sprintf_append().
*/
if (dns_rr_to_pa(addr, &hostaddr) == 0)
return (0);
vstring_sprintf(state->endp_label, SMTP_SCACHE_LABEL(NO_MX_LOOKUP),
state->service, hostaddr.buf, ntohs(port));
if ((fd = scache_find_endp(smtp_scache, STR(state->endp_label),
state->endp_prop)) < 0)
return (0);
VSTRING_RESET(state->dest_prop);
VSTRING_TERMINATE(state->dest_prop);
/*
* Re-activate the SMTP_SESSION object, and verify that the session is
* still good.
*/
session = smtp_reuse_common(state, fd, STR(state->endp_label));
/*
* XXX What if hostnames don't match (addr->name versus session->name),
* or if the SASL login name for this host does not match the SASL login
* name that was used when opening this session? If something depends
* critically on such information being identical, then that information
* should be included in the logical and physical labels under which a
* session is cached.
*/
return (session);
}

34
gnu/dist/postfix/src/smtp/smtp_reuse.h vendored Normal file
View File

@ -0,0 +1,34 @@
/* $NetBSD: smtp_reuse.h,v 1.1.1.1 2005/08/18 21:08:59 rpaulo Exp $ */
/*++
/* NAME
/* smtp_reuse 3h
/* SUMMARY
/* SMTP session cache glue
/* SYNOPSIS
/* #include <smtp_reuse.h>
/* DESCRIPTION
/* .nf
/*
* DNS library.
*/
#include <dns.h>
/*
* Internal interfaces.
*/
extern void smtp_save_session(SMTP_STATE *);
extern SMTP_SESSION *smtp_reuse_domain(SMTP_STATE *, int, const char *, unsigned);
extern SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *, DNS_RR *, unsigned);
/* 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
/*--*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_sasl.h,v 1.1.1.3 2004/05/31 00:24:47 heas Exp $ */
/* $NetBSD: smtp_sasl.h,v 1.1.1.4 2005/08/18 21:08:56 rpaulo Exp $ */
/*++
/* NAME
@ -14,15 +14,19 @@
* SASL protocol functions
*/
extern void smtp_sasl_initialize(void);
extern void smtp_sasl_connect(SMTP_STATE *);
extern int smtp_sasl_passwd_lookup(SMTP_STATE *);
extern void smtp_sasl_start(SMTP_STATE *, const char *, const char *);
extern int smtp_sasl_authenticate(SMTP_STATE *, VSTRING *);
extern void smtp_sasl_cleanup(SMTP_STATE *);
extern void smtp_sasl_connect(SMTP_SESSION *);
extern int smtp_sasl_passwd_lookup(SMTP_SESSION *);
extern void smtp_sasl_start(SMTP_SESSION *, const char *, const char *);
extern int smtp_sasl_authenticate(SMTP_SESSION *, VSTRING *);
extern void smtp_sasl_cleanup(SMTP_SESSION *);
extern void smtp_sasl_helo_auth(SMTP_STATE *, const char *);
extern void smtp_sasl_helo_auth(SMTP_SESSION *, const char *);
extern int smtp_sasl_helo_login(SMTP_STATE *);
extern void smtp_sasl_passivate(SMTP_SESSION *, VSTRING *);
extern int smtp_sasl_activate(SMTP_SESSION *, char *);
extern STRING_LIST *smtp_sasl_mechs;
/* LICENSE
/* .ad
/* .fi

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_sasl_glue.c,v 1.1.1.5 2004/05/31 00:24:46 heas Exp $ */
/* $NetBSD: smtp_sasl_glue.c,v 1.1.1.6 2005/08/18 21:08:57 rpaulo Exp $ */
/*++
/* NAME
@ -10,21 +10,29 @@
/*
/* void smtp_sasl_initialize()
/*
/* void smtp_sasl_connect(state)
/* SMTP_STATE *state;
/* void smtp_sasl_connect(session)
/* SMTP_SESSION *session;
/*
/* void smtp_sasl_start(state, sasl_opts_name, sasl_opts_val)
/* SMTP_STATE *state;
/* void smtp_sasl_start(session, sasl_opts_name, sasl_opts_val)
/* SMTP_SESSION *session;
/*
/* int smtp_sasl_passwd_lookup(state)
/* SMTP_STATE *state;
/* int smtp_sasl_passwd_lookup(session)
/* SMTP_SESSION *session;
/*
/* int smtp_sasl_authenticate(state, why)
/* SMTP_STATE *state;
/* int smtp_sasl_authenticate(session, why)
/* SMTP_SESSION *session;
/* VSTRING *why;
/*
/* void smtp_sasl_cleanup(state)
/* SMTP_STATE *state;
/* void smtp_sasl_cleanup(session)
/* SMTP_SESSION *session;
/*
/* void smtp_sasl_passivate(session, buf)
/* SMTP_SESSION *session;
/* VSTRING *buf;
/*
/* int smtp_sasl_activate(session, buf)
/* SMTP_SESSION *session;
/* char *buf;
/* DESCRIPTION
/* smtp_sasl_initialize() initializes the SASL library. This
/* routine must be called once at process startup, before any
@ -54,8 +62,15 @@
/* end of every SMTP session that uses SASL authentication.
/* This routine is a noop for non-SASL sessions.
/*
/* smtp_sasl_passivate() appends flattened SASL attributes to the
/* specified buffer. The SASL attributes are not destroyed.
/*
/* smtp_sasl_activate() restores SASL attributes from the
/* specified buffer. The buffer is modified. A result < 0
/* means there was an error.
/*
/* Arguments:
/* .IP state
/* .IP session
/* Session context.
/* .IP mech_list
/* String of SASL mechanisms (separated by blanks)
@ -177,6 +192,11 @@ static NAME_MASK smtp_sasl_sec_mask[] = {
*/
static MAPS *smtp_sasl_passwd_map;
/*
* Supported SASL mechanisms.
*/
STRING_LIST *smtp_sasl_mechs;
/* smtp_sasl_log - logging call-back routine */
static int smtp_sasl_log(void *unused_context, int priority,
@ -205,20 +225,20 @@ static int smtp_sasl_get_user(void *context, int unused_id, const char **result,
unsigned *len)
{
char *myname = "smtp_sasl_get_user";
SMTP_STATE *state = (SMTP_STATE *) context;
SMTP_SESSION *session = (SMTP_SESSION *) context;
if (msg_verbose)
msg_info("%s: %s", myname, state->sasl_username);
msg_info("%s: %s", myname, session->sasl_username);
/*
* Sanity check.
*/
if (state->sasl_passwd == 0)
if (session->sasl_passwd == 0)
msg_panic("%s: no username looked up", myname);
*result = state->sasl_username;
*result = session->sasl_username;
if (len)
*len = strlen(state->sasl_username);
*len = strlen(session->sasl_username);
return (SASL_OK);
}
@ -228,35 +248,35 @@ static int smtp_sasl_get_passwd(sasl_conn_t *conn, void *context,
int id, sasl_secret_t **psecret)
{
char *myname = "smtp_sasl_get_passwd";
SMTP_STATE *state = (SMTP_STATE *) context;
SMTP_SESSION *session = (SMTP_SESSION *) context;
int len;
if (msg_verbose)
msg_info("%s: %s", myname, state->sasl_passwd);
msg_info("%s: %s", myname, session->sasl_passwd);
/*
* Sanity check.
*/
if (!conn || !psecret || id != SASL_CB_PASS)
return (SASL_BADPARAM);
if (state->sasl_passwd == 0)
if (session->sasl_passwd == 0)
msg_panic("%s: no password looked up", myname);
/*
* Convert the password into a counted string.
*/
len = strlen(state->sasl_passwd);
len = strlen(session->sasl_passwd);
if ((*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len)) == 0)
return (SASL_NOMEM);
(*psecret)->len = len;
memcpy((*psecret)->data, state->sasl_passwd, len + 1);
memcpy((*psecret)->data, session->sasl_passwd, len + 1);
return (SASL_OK);
}
/* smtp_sasl_passwd_lookup - password lookup routine */
int smtp_sasl_passwd_lookup(SMTP_STATE *state)
int smtp_sasl_passwd_lookup(SMTP_SESSION *session)
{
char *myname = "smtp_sasl_passwd_lookup";
const char *value;
@ -271,21 +291,30 @@ int smtp_sasl_passwd_lookup(SMTP_STATE *state)
/*
* Look up the per-server password information. Try the hostname first,
* then try the destination.
*
* XXX Instead of using nexthop (the intended destination) we use dest
* (either the intended destination, or a fall-back destination).
*
* XXX SASL authentication currently depends on the host/domain but not on
* the TCP port. If the port is not :25, we should append it to the table
* lookup key. Code for this was briefly introduced into 2.2 snapshots,
* but didn't canonicalize the TCP port, and did not append the port to
* the MX hostname.
*/
if ((value = maps_find(smtp_sasl_passwd_map, state->session->host, 0)) != 0
|| (value = maps_find(smtp_sasl_passwd_map, state->request->nexthop, 0)) != 0) {
state->sasl_username = mystrdup(value);
passwd = split_at(state->sasl_username, ':');
state->sasl_passwd = mystrdup(passwd ? passwd : "");
if ((value = maps_find(smtp_sasl_passwd_map, session->host, 0)) != 0
|| (value = maps_find(smtp_sasl_passwd_map, session->dest, 0)) != 0) {
session->sasl_username = mystrdup(value);
passwd = split_at(session->sasl_username, ':');
session->sasl_passwd = mystrdup(passwd ? passwd : "");
if (msg_verbose)
msg_info("%s: host `%s' user `%s' pass `%s'",
myname, state->session->host,
state->sasl_username, state->sasl_passwd);
myname, session->host,
session->sasl_username, session->sasl_passwd);
return (1);
} else {
if (msg_verbose)
msg_info("%s: host `%s' no auth info found",
myname, state->session->host);
myname, session->host);
return (0);
}
}
@ -321,24 +350,30 @@ void smtp_sasl_initialize(void)
if (sasl_client_init(callbacks) != SASL_OK)
msg_fatal("SASL library initialization");
/*
* Initialize optional supported mechanism matchlist
*/
if (*var_smtp_sasl_mechs)
smtp_sasl_mechs = string_list_init(MATCH_FLAG_NONE,
var_smtp_sasl_mechs);
}
/* smtp_sasl_connect - per-session client initialization */
void smtp_sasl_connect(SMTP_STATE *state)
void smtp_sasl_connect(SMTP_SESSION *session)
{
state->sasl_mechanism_list = 0;
state->sasl_username = 0;
state->sasl_passwd = 0;
state->sasl_conn = 0;
state->sasl_encoded = 0;
state->sasl_decoded = 0;
state->sasl_callbacks = 0;
session->sasl_mechanism_list = 0;
session->sasl_username = 0;
session->sasl_passwd = 0;
session->sasl_conn = 0;
session->sasl_encoded = 0;
session->sasl_decoded = 0;
session->sasl_callbacks = 0;
}
/* smtp_sasl_start - per-session SASL initialization */
void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name,
void smtp_sasl_start(SMTP_SESSION *session, const char *sasl_opts_name,
const char *sasl_opts_val)
{
static sasl_callback_t callbacks[] = {
@ -359,18 +394,18 @@ void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name,
*/
#define NULL_SECFLAGS 0
state->sasl_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks));
memcpy((char *) state->sasl_callbacks, callbacks, sizeof(callbacks));
for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++)
cp->context = (void *) state;
session->sasl_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks));
memcpy((char *) session->sasl_callbacks, callbacks, sizeof(callbacks));
for (cp = session->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++)
cp->context = (void *) session;
#define NULL_SERVER_ADDR ((char *) 0)
#define NULL_CLIENT_ADDR ((char *) 0)
if (SASL_CLIENT_NEW("smtp", state->session->host,
if (SASL_CLIENT_NEW("smtp", session->host,
NULL_CLIENT_ADDR, NULL_SERVER_ADDR,
state->sasl_callbacks, NULL_SECFLAGS,
(sasl_conn_t **) &state->sasl_conn) != SASL_OK)
session->sasl_callbacks, NULL_SECFLAGS,
(sasl_conn_t **) &session->sasl_conn) != SASL_OK)
msg_fatal("per-session SASL client initialization");
/*
@ -379,14 +414,14 @@ void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name,
*/
memset(&sec_props, 0L, sizeof(sec_props));
sec_props.min_ssf = 0;
sec_props.max_ssf = 1; /* don't allow real SASL
sec_props.max_ssf = 0; /* don't allow real SASL
* security layer */
sec_props.security_flags = name_mask(sasl_opts_name, smtp_sasl_sec_mask,
sasl_opts_val);
sec_props.maxbufsize = 0;
sec_props.property_names = 0;
sec_props.property_values = 0;
if (sasl_setprop(state->sasl_conn, SASL_SEC_PROPS,
if (sasl_setprop(session->sasl_conn, SASL_SEC_PROPS,
&sec_props) != SASL_OK)
msg_fatal("set per-session SASL security properties");
@ -395,13 +430,13 @@ void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name,
* order to avoid memory leaks in case of read/write timeout or I/O
* error.
*/
state->sasl_encoded = vstring_alloc(10);
state->sasl_decoded = vstring_alloc(10);
session->sasl_encoded = vstring_alloc(10);
session->sasl_decoded = vstring_alloc(10);
}
/* smtp_sasl_authenticate - run authentication protocol */
int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
int smtp_sasl_authenticate(SMTP_SESSION *session, VSTRING *why)
{
char *myname = "smtp_sasl_authenticate";
unsigned enc_length;
@ -428,18 +463,18 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
if (msg_verbose)
msg_info("%s: %s: SASL mechanisms %s",
myname, state->session->namaddr, state->sasl_mechanism_list);
myname, session->namaddr, session->sasl_mechanism_list);
/*
* Start the client side authentication protocol.
*/
result = SASL_CLIENT_START((sasl_conn_t *) state->sasl_conn,
state->sasl_mechanism_list,
result = SASL_CLIENT_START((sasl_conn_t *) session->sasl_conn,
session->sasl_mechanism_list,
NO_SASL_SECRET, NO_SASL_INTERACTION,
&clientout, &clientoutlen, &mechanism);
if (result != SASL_OK && result != SASL_CONTINUE) {
vstring_sprintf(why, "cannot SASL authenticate to server %s: %s",
state->session->namaddr,
session->namaddr,
sasl_errstring(result, NO_SASL_LANGLIST,
NO_SASL_OUTLANG));
return (-1);
@ -455,28 +490,28 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
if (clientoutlen > 0) {
if (msg_verbose)
msg_info("%s: %s: uncoded initial reply: %.*s",
myname, state->session->namaddr,
(int) clientoutlen, clientout);
myname, session->namaddr, (int) clientoutlen, clientout);
enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
VSTRING_SPACE(state->sasl_encoded, enc_length);
VSTRING_SPACE(session->sasl_encoded, enc_length);
if (sasl_encode64(clientout, clientoutlen,
STR(state->sasl_encoded), enc_length,
STR(session->sasl_encoded), enc_length,
&enc_length_out) != SASL_OK)
msg_panic("%s: sasl_encode64 botch", myname);
#if SASL_VERSION_MAJOR < 2
/* SASL version 1 doesn't free memory that it allocates. */
free(clientout);
#endif
smtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded));
smtp_chat_cmd(session, "AUTH %s %s", mechanism,
STR(session->sasl_encoded));
} else {
smtp_chat_cmd(state, "AUTH %s", mechanism);
smtp_chat_cmd(session, "AUTH %s", mechanism);
}
/*
* Step through the authentication protocol until the server tells us
* that we are done.
*/
while ((resp = smtp_chat_resp(state))->code / 100 == 3) {
while ((resp = smtp_chat_resp(session))->code / 100 == 3) {
/*
* Process a server challenge.
@ -484,25 +519,24 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
line = resp->str;
(void) mystrtok(&line, "- \t\n"); /* skip over result code */
serverinlen = strlen(line);
VSTRING_SPACE(state->sasl_decoded, serverinlen);
if (SASL_DECODE64(line, serverinlen, STR(state->sasl_decoded),
VSTRING_SPACE(session->sasl_decoded, serverinlen);
if (SASL_DECODE64(line, serverinlen, STR(session->sasl_decoded),
serverinlen, &enc_length) != SASL_OK) {
vstring_sprintf(why, "malformed SASL challenge from server %s",
state->session->namaddr);
session->namaddr);
return (-1);
}
if (msg_verbose)
msg_info("%s: %s: decoded challenge: %.*s",
myname, state->session->namaddr,
(int) enc_length, STR(state->sasl_decoded));
result = sasl_client_step((sasl_conn_t *) state->sasl_conn,
STR(state->sasl_decoded), enc_length,
myname, session->namaddr, (int) enc_length,
STR(session->sasl_decoded));
result = sasl_client_step((sasl_conn_t *) session->sasl_conn,
STR(session->sasl_decoded), enc_length,
NO_SASL_INTERACTION, &clientout, &clientoutlen);
if (result != SASL_OK && result != SASL_CONTINUE)
msg_warn("SASL authentication failed to server %s: %s",
state->session->namaddr,
sasl_errstring(result, NO_SASL_LANGLIST,
NO_SASL_OUTLANG));
session->namaddr, sasl_errstring(result, NO_SASL_LANGLIST,
NO_SASL_OUTLANG));
/*
* Send a client response.
@ -510,12 +544,12 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
if (clientoutlen > 0) {
if (msg_verbose)
msg_info("%s: %s: uncoded client response %.*s",
myname, state->session->namaddr,
myname, session->namaddr,
(int) clientoutlen, clientout);
enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
VSTRING_SPACE(state->sasl_encoded, enc_length);
VSTRING_SPACE(session->sasl_encoded, enc_length);
if (sasl_encode64(clientout, clientoutlen,
STR(state->sasl_encoded), enc_length,
STR(session->sasl_encoded), enc_length,
&enc_length_out) != SASL_OK)
msg_panic("%s: sasl_encode64 botch", myname);
#if SASL_VERSION_MAJOR < 2
@ -523,9 +557,9 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
free(clientout);
#endif
} else {
vstring_strcat(state->sasl_encoded, "");
vstring_strcat(session->sasl_encoded, "");
}
smtp_chat_cmd(state, "%s", STR(state->sasl_encoded));
smtp_chat_cmd(session, "%s", STR(session->sasl_encoded));
}
/*
@ -533,7 +567,7 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
*/
if (resp->code / 100 != 2) {
vstring_sprintf(why, "SASL authentication failed; server %s said: %s",
state->session->namaddr, resp->str);
session->namaddr, resp->str);
return (0);
}
return (1);
@ -541,38 +575,51 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
/* smtp_sasl_cleanup - per-session cleanup */
void smtp_sasl_cleanup(SMTP_STATE *state)
void smtp_sasl_cleanup(SMTP_SESSION *session)
{
if (state->sasl_username) {
myfree(state->sasl_username);
state->sasl_username = 0;
if (session->sasl_username) {
myfree(session->sasl_username);
session->sasl_username = 0;
}
if (state->sasl_passwd) {
myfree(state->sasl_passwd);
state->sasl_passwd = 0;
if (session->sasl_passwd) {
myfree(session->sasl_passwd);
session->sasl_passwd = 0;
}
if (state->sasl_mechanism_list) {
if (session->sasl_mechanism_list) {
/* allocated in smtp_sasl_helo_auth */
myfree(state->sasl_mechanism_list);
state->sasl_mechanism_list = 0;
myfree(session->sasl_mechanism_list);
session->sasl_mechanism_list = 0;
}
if (state->sasl_conn) {
if (session->sasl_conn) {
if (msg_verbose)
msg_info("disposing SASL state information");
sasl_dispose(&state->sasl_conn);
sasl_dispose(&session->sasl_conn);
}
if (state->sasl_callbacks) {
myfree((char *) state->sasl_callbacks);
state->sasl_callbacks = 0;
if (session->sasl_callbacks) {
myfree((char *) session->sasl_callbacks);
session->sasl_callbacks = 0;
}
if (state->sasl_encoded) {
vstring_free(state->sasl_encoded);
state->sasl_encoded = 0;
if (session->sasl_encoded) {
vstring_free(session->sasl_encoded);
session->sasl_encoded = 0;
}
if (state->sasl_decoded) {
vstring_free(state->sasl_decoded);
state->sasl_decoded = 0;
if (session->sasl_decoded) {
vstring_free(session->sasl_decoded);
session->sasl_decoded = 0;
}
}
/* smtp_sasl_passivate - append serialized SASL attributes */
void smtp_sasl_passivate(SMTP_SESSION *session, VSTRING *buf)
{
}
/* smtp_sasl_activate - de-serialize SASL attributes */
int smtp_sasl_activate(SMTP_SESSION *session, char *buf)
{
return (0);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_sasl_proto.c,v 1.1.1.4 2004/05/31 00:24:45 heas Exp $ */
/* $NetBSD: smtp_sasl_proto.c,v 1.1.1.5 2005/08/18 21:08:57 rpaulo Exp $ */
/*++
/* NAME
@ -63,6 +63,7 @@
#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>
/* Global library. */
@ -75,30 +76,67 @@
#ifdef USE_SASL_AUTH
/* smtp_sasl_helo_auth - handle AUTH option in EHLO reply */
/* smtp_sasl_compat_mechs - Trim server's mechanism list */
void smtp_sasl_helo_auth(SMTP_STATE *state, const char *words)
static const char *smtp_sasl_compat_mechs(const char *words)
{
static VSTRING *buf;
char *mech_list;
char *save_mech;
char *mech;
int ret;
/*
* XXX If the server offers a null list of authentication mechanisms,
* Use server's mechanisms if no filter specified
*/
if (smtp_sasl_mechs == 0 || *words == 0)
return (words);
if (buf == 0)
buf = vstring_alloc(10);
VSTRING_RESET(buf);
VSTRING_TERMINATE(buf);
save_mech = mech_list = mystrdup(words);
while ((mech = mystrtok(&mech_list, " \t")) != 0) {
if (string_list_match(smtp_sasl_mechs, mech)) {
if (VSTRING_LEN(buf) > 0)
VSTRING_ADDCH(buf, ' ');
vstring_strcat(buf, mech);
}
}
myfree(save_mech);
return (vstring_str(buf));
}
/* smtp_sasl_helo_auth - handle AUTH option in EHLO reply */
void smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words)
{
const char *mech_list = smtp_sasl_compat_mechs(words);
/*
* XXX If the server offers no compatible authentication mechanisms,
* then pretend that the server doesn't support SASL authentication.
*/
if (state->sasl_mechanism_list) {
if (strcasecmp(state->sasl_mechanism_list, words) == 0)
if (session->sasl_mechanism_list) {
if (strcasecmp(session->sasl_mechanism_list, mech_list) == 0)
return;
myfree(state->sasl_mechanism_list);
msg_warn("%s offered AUTH option multiple times",
state->session->namaddr);
state->sasl_mechanism_list = 0;
state->features &= ~SMTP_FEATURE_AUTH;
myfree(session->sasl_mechanism_list);
msg_warn("%s offered AUTH option multiple times", session->namaddr);
session->sasl_mechanism_list = 0;
session->features &= ~SMTP_FEATURE_AUTH;
}
if (strlen(words) > 0) {
state->sasl_mechanism_list = mystrdup(words);
state->features |= SMTP_FEATURE_AUTH;
if (strlen(mech_list) > 0) {
session->sasl_mechanism_list = mystrdup(mech_list);
session->features |= SMTP_FEATURE_AUTH;
} else {
msg_warn("%s offered null AUTH mechanism list",
state->session->namaddr);
msg_warn(*words ? "%s offered no supported AUTH mechanisms: '%s'" :
"%s offered null AUTH mechanism list",
session->namaddr, words);
}
}
@ -106,20 +144,33 @@ void smtp_sasl_helo_auth(SMTP_STATE *state, const char *words)
int smtp_sasl_helo_login(SMTP_STATE *state)
{
VSTRING *why = vstring_alloc(10);
int ret = 0;
SMTP_SESSION *session = state->session;
VSTRING *why;
int ret;
/*
* Skip authentication when no authentication info exists for this
* server, so that we talk to each other like strangers. Otherwise, if
* authentication information exists, assume that authentication is
* required, and assume that an authentication error is recoverable.
* server, so that we talk to each other like strangers.
*/
if (smtp_sasl_passwd_lookup(state) != 0) {
smtp_sasl_start(state, VAR_SMTP_SASL_OPTS, var_smtp_sasl_opts);
if (smtp_sasl_authenticate(state, why) <= 0)
ret = smtp_site_fail(state, 450, "Authentication failed: %s",
vstring_str(why));
if (smtp_sasl_passwd_lookup(session) == 0) {
session->features &= ~SMTP_FEATURE_AUTH;
return 0;
}
/*
* Otherwise, if authentication information exists, assume that
* authentication is required, and assume that an authentication error is
* recoverable from the message delivery point of view. An authentication
* error is unrecoverable from a session point of view - the session will
* not be reused.
*/
why = vstring_alloc(10);
ret = 0;
smtp_sasl_start(session, VAR_SMTP_SASL_OPTS, var_smtp_sasl_opts);
if (smtp_sasl_authenticate(session, why) <= 0) {
ret = smtp_site_fail(state, 450, "Authentication failed: %s",
vstring_str(why));
/* Session reuse is disabled. */
}
vstring_free(why);
return (ret);

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_session.c,v 1.1.1.2 2004/05/31 00:24:47 heas Exp $ */
/* $NetBSD: smtp_session.c,v 1.1.1.3 2005/08/18 21:08:58 rpaulo Exp $ */
/*++
/* NAME
@ -8,21 +8,73 @@
/* SYNOPSIS
/* #include "smtp.h"
/*
/* SMTP_SESSION *smtp_session_alloc(stream, host, addr)
/* SMTP_SESSION *smtp_session_alloc(stream, dest, host, addr, port, flags)
/* VSTREAM *stream;
/* char *dest;
/* char *host;
/* char *addr;
/* unsigned port;
/* int flags;
/*
/* void smtp_session_free(session)
/* SMTP_SESSION *session;
/*
/* int smtp_session_passivate(session, dest_prop, endp_prop)
/* SMTP_SESSION *session;
/* VSTRING *dest_prop;
/* VSTRING *endp_prop;
/*
/* SMTP_SESSION *smtp_session_activate(fd, dest_prop, endp_prop)
/* int fd;
/* VSTRING *dest_prop;
/* VSTRING *endp_prop;
/* DESCRIPTION
/* smtp_session_alloc() allocates memory for an SMTP_SESSION structure
/* and initializes it with the given stream and host name and address
/* information. The host name and address strings are copied. The code
/* assumes that the stream is connected to the "best" alternative.
/* and initializes it with the given stream and destination, host name
/* and address information. The host name and address strings are
/* copied. The port is in network byte order.
/* When TLS is enabled, smtp_session_alloc() looks up the
/* per-site TLS policies for TLS enforcement and certificate
/* verification. The resulting policy is stored into the
/* SMTP_SESSION object.
/*
/* smtp_session_free() destroys an SMTP_SESSION structure and its
/* members, making memory available for reuse.
/* members, making memory available for reuse. It will handle the
/* case of a null stream and will assume it was given a different
/* purpose.
/*
/* smtp_session_passivate() flattens an SMTP session so that
/* it can be cached. The SMTP_SESSION structure is destroyed.
/*
/* smtp_session_activate() inflates a flattened SMTP session
/* so that it can be used. The input is modified.
/*
/* Arguments:
/* .IP stream
/* A full-duplex stream.
/* .IP dest
/* The unmodified next-hop or fall-back destination including
/* the optional [] and including the optional port or service.
/* .IP host
/* The name of the host that we are connected to.
/* .IP addr
/* The address of the host that we are connected to.
/* .IP port
/* The remote port, network byte order.
/* .IP flags
/* Zero or more of the following:
/* .RS
/* .IP SMTP_SESS_FLAG_CACHE
/* Enable session caching.
/* .RE
/* .IP
/* The manifest constant SMTP_SESS_FLAG_NONE requests no options.
/* .IP dest_prop
/* Destination specific session properties: the server is the
/* best MX host for the current logical destination.
/* .IP endp_prop
/* Endpoint specific session properties: all the features
/* advertised by the remote server.
/* LICENSE
/* .ad
/* .fi
@ -32,34 +84,196 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* TLS support originally by:
/* Lutz Jaenicke
/* BTU Cottbus
/* Allgemeine Elektrotechnik
/* Universitaetsplatz 3-4
/* D-03044 Cottbus, Germany
/*--*/
/* System library. */
#include <sys_defs.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <vstream.h>
#include <stringops.h>
/* Global library. */
#include <mime_state.h>
#include <debug_peer.h>
#include <mail_params.h>
#include <maps.h>
/* Application-specific. */
#include "smtp.h"
#include "smtp_sasl.h"
#define STR(x) vstring_str(x)
/*#define msg_verbose 1*/
#ifdef USE_TLS
/*
* Per-site policies can override main.cf settings.
*/
typedef struct {
int dont_use; /* don't use TLS */
int use; /* useless, see above */
int enforce; /* must always use TLS */
int enforce_peername; /* must verify certificate name */
} SMTP_TLS_SITE_POLICY;
static MAPS *tls_per_site; /* lookup table(s) */
/* smtp_tls_list_init - initialize per-site policy lists */
void smtp_tls_list_init(void)
{
tls_per_site = maps_create(VAR_SMTP_TLS_PER_SITE, var_smtp_tls_per_site,
DICT_FLAG_LOCK);
}
/* smtp_tls_site_policy - look up per-site TLS policy */
static void smtp_tls_site_policy(SMTP_TLS_SITE_POLICY *policy,
const char *site_name,
const char *site_class)
{
const char *lookup;
char *lookup_key;
/*
* Initialize the default policy.
*/
policy->dont_use = 0;
policy->use = 0;
policy->enforce = 0;
policy->enforce_peername = 0;
/*
* Look up a non-default policy.
*/
lookup_key = lowercase(mystrdup(site_name));
if ((lookup = maps_find(tls_per_site, lookup_key, 0)) != 0) {
if (!strcasecmp(lookup, "NONE"))
policy->dont_use = 1;
else if (!strcasecmp(lookup, "MAY"))
policy->use = 1;
else if (!strcasecmp(lookup, "MUST"))
policy->enforce = policy->enforce_peername = 1;
else if (!strcasecmp(lookup, "MUST_NOPEERMATCH"))
policy->enforce = 1;
else
msg_warn("Table %s: ignoring unknown TLS policy '%s' for %s %s",
var_smtp_tls_per_site, lookup, site_class, site_name);
}
myfree(lookup_key);
}
#endif
/* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, char *host, char *addr)
SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
const char *host, const char *addr,
unsigned port, int flags)
{
SMTP_SESSION *session;
#ifdef USE_TLS
SMTP_TLS_SITE_POLICY host_policy;
SMTP_TLS_SITE_POLICY rcpt_policy;
#endif
session = (SMTP_SESSION *) mymalloc(sizeof(*session));
session->stream = stream;
session->dest = mystrdup(dest);
session->host = mystrdup(host);
session->addr = mystrdup(addr);
session->namaddr = concatenate(host, "[", addr, "]", (char *) 0);
session->best = 1;
session->helo = 0;
session->port = port;
session->features = 0;
session->size_limit = 0;
session->error_mask = 0;
session->buffer = vstring_alloc(100);
session->scratch = vstring_alloc(100);
session->scratch2 = vstring_alloc(100);
smtp_chat_init(session);
session->features = 0;
session->mime_state = 0;
session->sndbufsize = 0;
session->send_proto_helo = 0;
if (flags & SMTP_SESS_FLAG_CACHE)
session->reuse_count = var_smtp_reuse_limit;
else
session->reuse_count = 0;
#ifdef USE_SASL_AUTH
smtp_sasl_connect(session);
#endif
#ifdef USE_TLS
session->tls_use_tls = session->tls_enforce_tls = 0;
session->tls_enforce_peername = 0;
session->tls_context = 0;
session->tls_info = tls_info_zero;
/*
* Override the main.cf TLS policy with an optional per-site policy.
*/
if (smtp_tls_ctx != 0) {
smtp_tls_site_policy(&host_policy, host, "receiving host");
smtp_tls_site_policy(&rcpt_policy, dest, "recipient domain");
/*
* Set up TLS enforcement for this session.
*/
if ((var_smtp_enforce_tls && !host_policy.dont_use && !rcpt_policy.dont_use)
|| host_policy.enforce || rcpt_policy.enforce)
session->tls_enforce_tls = session->tls_use_tls = 1;
/*
* Set up peername checking for this session.
*
* We want to make sure that a MUST* entry in the tls_per_site table
* always has precedence. MUST always must lead to a peername check,
* MUST_NOPEERMATCH must always disable it. Only when no explicit
* setting has been found, the default will be used. There is the
* case left, that both "host" and "recipient" settings conflict. In
* this case, the "host" setting wins.
*/
if (host_policy.enforce && host_policy.enforce_peername)
session->tls_enforce_peername = 1;
else if (rcpt_policy.enforce && rcpt_policy.enforce_peername)
session->tls_enforce_peername = 1;
else if (var_smtp_enforce_tls && var_smtp_tls_enforce_peername)
session->tls_enforce_peername = 1;
else if ((var_smtp_use_tls && !host_policy.dont_use && !rcpt_policy.dont_use) || host_policy.use || rcpt_policy.use)
session->tls_use_tls = 1;
}
#endif
debug_peer_check(host, addr);
return (session);
}
@ -67,9 +281,197 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, char *host, char *addr)
void smtp_session_free(SMTP_SESSION *session)
{
vstream_fclose(session->stream);
#ifdef USE_TLS
if (session->stream) {
vstream_fflush(session->stream);
if (session->tls_context)
tls_client_stop(smtp_tls_ctx, session->stream,
var_smtp_starttls_tmout, 0,
&(session->tls_info));
}
#endif
if (session->stream)
vstream_fclose(session->stream);
myfree(session->dest);
myfree(session->host);
myfree(session->addr);
myfree(session->namaddr);
if (session->helo)
myfree(session->helo);
vstring_free(session->buffer);
vstring_free(session->scratch);
vstring_free(session->scratch2);
if (session->history)
smtp_chat_reset(session);
if (session->mime_state)
mime_state_free(session->mime_state);
#ifdef USE_SASL_AUTH
smtp_sasl_cleanup(session);
#endif
debug_peer_restore();
myfree((char *) session);
}
/* smtp_session_passivate - passivate an SMTP_SESSION object */
int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
VSTRING *endp_prop)
{
int fd;
/*
* Encode the local-to-physical binding properties: whether or not this
* server is best MX host for the next-hop or fall-back logical
* destination (this information is needed for loop handling in
* smtp_proto()).
*
* XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can
* serialize the properties with attr_print() instead of using ad-hoc,
* non-reusable, code and hard-coded format strings.
*/
vstring_sprintf(dest_prop, "%u",
session->features & SMTP_FEATURE_DESTINATION_MASK);
/*
* Encode the physical endpoint properties: all the session properties
* except for "session from cache", "best MX", or "RSET failure".
*
* XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can
* serialize the properties with attr_print() instead of using obscure
* hard-coded format strings.
*
* XXX Should also record an absolute time when a session must be closed,
* how many non-delivering mail transactions there were during this
* session, and perhaps other statistics, so that we don't reuse a
* session too much.
*/
vstring_sprintf(endp_prop, "%s\n%s\n%s\n%u\n%u\n%u\n%u",
session->dest, session->host,
session->addr, session->port,
session->features & SMTP_FEATURE_ENDPOINT_MASK,
session->reuse_count,
session->sndbufsize);
/*
* Append the passivated SASL attributes.
*/
#ifdef USE_SASL
if (smtp_sasl_enable)
smtp_sasl_passivate(endp_prop, session);
#endif
/*
* Salvage the underlying file descriptor, and destroy the session
* object.
*/
fd = vstream_fileno(session->stream);
vstream_fdclose(session->stream);
session->stream = 0;
smtp_session_free(session);
return (fd);
}
/* smtp_session_activate - re-activate a passivated SMTP_SESSION object */
SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
VSTRING *endp_prop)
{
const char *myname = "smtp_session_activate";
SMTP_SESSION *session;
char *dest_props;
char *endp_props;
const char *prop;
const char *dest;
const char *host;
const char *addr;
unsigned port;
unsigned features; /* server features */
unsigned reuse_count; /* how reuses left */
unsigned sndbufsize; /* PIPELINING buffer size */
/*
* XXX it would be nice to have a VSTRING to VSTREAM adapter so that we
* can de-serialize the properties with attr_scan(), instead of using
* ad-hoc, non-reusable code.
*
* XXX As a preliminary solution we use mystrtok(), but that function is not
* suitable for zero-length fields.
*/
endp_props = STR(endp_prop);
if ((dest = mystrtok(&endp_props, "\n")) == 0) {
msg_warn("%s: missing cached session destination property", myname);
return (0);
}
if ((host = mystrtok(&endp_props, "\n")) == 0) {
msg_warn("%s: missing cached session hostname property", myname);
return (0);
}
if ((addr = mystrtok(&endp_props, "\n")) == 0) {
msg_warn("%s: missing cached session address property", myname);
return (0);
}
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached session port property", myname);
return (0);
}
port = atoi(prop);
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached session features property", myname);
return (0);
}
features = atoi(prop);
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached session reuse_count property", myname);
return (0);
}
reuse_count = atoi(prop);
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached session sndbufsize property", myname);
return (0);
}
sndbufsize = atoi(prop);
if (dest_prop && VSTRING_LEN(dest_prop)) {
dest_props = STR(dest_prop);
if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached destination features property", myname);
return (0);
}
features |= atoi(prop);
}
/*
* Allright, bundle up what we have sofar.
*/
session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR),
dest, host, addr, port, SMTP_SESS_FLAG_NONE);
session->features = (features | SMTP_FEATURE_FROM_CACHE);
session->reuse_count = reuse_count - 1;
session->sndbufsize = sndbufsize;
if (msg_verbose)
msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, reuse=%u, sndbuf=%u",
myname, dest, host, addr, ntohs(port), features, reuse_count, sndbufsize);
/*
* Re-activate the SASL attributes.
*/
#ifdef USE_SASL
if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) {
vstream_fdclose(session->stream);
session->stream = 0;
smtp_session_free(session);
return (0);
}
#endif
return (session);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_state.c,v 1.1.1.5 2004/05/31 00:24:47 heas Exp $ */
/* $NetBSD: smtp_state.c,v 1.1.1.6 2005/08/18 21:08:58 rpaulo Exp $ */
/*++
/* NAME
@ -40,12 +40,10 @@
#include <mymalloc.h>
#include <vstring.h>
#include <vstream.h>
/* Global library. */
#include <mail_conf.h>
#include <mime_state.h>
#include <mail_params.h>
/* Application-specific. */
@ -59,21 +57,25 @@ SMTP_STATE *smtp_state_alloc(void)
SMTP_STATE *state = (SMTP_STATE *) mymalloc(sizeof(*state));
state->src = 0;
state->service = 0;
state->request = 0;
state->session = 0;
state->buffer = vstring_alloc(100);
state->scratch = vstring_alloc(100);
state->scratch2 = vstring_alloc(100);
state->status = 0;
state->features = 0;
state->history = 0;
state->error_mask = 0;
#ifdef USE_SASL_AUTH
smtp_sasl_connect(state);
#endif
state->size_limit = 0;
state->space_left = 0;
state->mime_state = 0;
state->nexthop_domain = 0;
if (var_smtp_cache_conn) {
state->dest_label = vstring_alloc(10);
state->dest_prop = vstring_alloc(10);
state->endp_label = vstring_alloc(10);
state->endp_prop = vstring_alloc(10);
state->cache_used = htable_create(1);
} else {
state->dest_label = 0;
state->dest_prop = 0;
state->endp_label = 0;
state->endp_prop = 0;
state->cache_used = 0;
}
return (state);
}
@ -81,13 +83,15 @@ SMTP_STATE *smtp_state_alloc(void)
void smtp_state_free(SMTP_STATE *state)
{
vstring_free(state->buffer);
vstring_free(state->scratch);
vstring_free(state->scratch2);
#ifdef USE_SASL_AUTH
smtp_sasl_cleanup(state);
#endif
if (state->mime_state)
mime_state_free(state->mime_state);
if (state->dest_label)
vstring_free(state->dest_label);
if (state->dest_prop)
vstring_free(state->dest_prop);
if (state->endp_label)
vstring_free(state->endp_label);
if (state->endp_prop)
vstring_free(state->endp_prop);
if (state->cache_used)
htable_free(state->cache_used, (void (*) (char *)) 0);
myfree((char *) state);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp_trouble.c,v 1.1.1.4 2004/05/31 00:24:47 heas Exp $ */
/* $NetBSD: smtp_trouble.c,v 1.1.1.5 2005/08/18 21:08:58 rpaulo Exp $ */
/*++
/* NAME
@ -62,6 +62,7 @@
/* record why the host is being skipped; soft error, final server:
/* defer delivery of all remaining recipients and mark the destination
/* as problematic; hard error: bounce all remaining recipients.
/* The session is marked as "do not cache".
/* The result is non-zero.
/*
/* smtp_mesg_fail() handles the case where the smtp server
@ -88,6 +89,7 @@
/* The policy is: non-final server: log an informational record
/* with the reason why the host is being skipped; final server:
/* defer delivery of all remaining recipients.
/* The session is marked as "do not cache".
/* The result is non-zero.
/* DIAGNOSTICS
/* Panic: unknown exception code.
@ -138,7 +140,7 @@
/* smtp_check_code - check response code */
static void smtp_check_code(SMTP_STATE *state, int code)
static void smtp_check_code(SMTP_SESSION *session, int code)
{
/*
@ -154,7 +156,7 @@ static void smtp_check_code(SMTP_STATE *state, int code)
if ((!SMTP_SOFT(code) && !SMTP_HARD(code))
|| code == 555 /* RFC 1869, section 6.1. */
|| (code >= 500 && code < 510))
state->error_mask |= MAIL_ERROR_PROTOCOL;
session->error_mask |= MAIL_ERROR_PROTOCOL;
}
/* smtp_site_fail - skip site, defer or bounce all recipients */
@ -216,7 +218,14 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
if (soft_error && request->hop_status == 0)
request->hop_status = mystrdup(vstring_str(why));
}
smtp_check_code(state, code);
if (session)
smtp_check_code(session, code);
/*
* Don't cache this session. We can't talk to this server.
*/
if (session)
session->reuse_count = 0;
/*
* Cleanup.
@ -273,15 +282,16 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time,
"%s", vstring_str(why));
session ? session->namaddr : "none",
request->arrival_time, "%s", vstring_str(why));
if (status == 0)
deliver_completed(state->src, rcpt->offset);
SMTP_RCPT_DROP(state, rcpt);
state->status |= status;
}
}
smtp_check_code(state, code);
if (session)
smtp_check_code(session, code);
/*
* Cleanup.
@ -336,14 +346,16 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
status = (soft_error ? vdefer_append : vbounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time, format, ap);
session ? session->namaddr : "none",
request->arrival_time, format, ap);
va_end(ap);
if (status == 0)
deliver_completed(state->src, rcpt->offset);
SMTP_RCPT_DROP(state, rcpt);
state->status |= status;
}
smtp_check_code(state, code);
if (session)
smtp_check_code(session, code);
}
/* smtp_stream_except - defer domain after I/O problem */
@ -356,6 +368,12 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
int nrcpt;
VSTRING *why = vstring_alloc(100);
/*
* Sanity check.
*/
if (session == 0)
msg_panic("smtp_stream_except: no session");
/*
* Initialize.
*/
@ -404,8 +422,16 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
"%s", vstring_str(why));
SMTP_RCPT_DROP(state, rcpt);
}
/* XXX This assumes no fall-back relay. */
if (request->hop_status == 0)
request->hop_status = mystrdup(vstring_str(why));
}
/*
* Don't attempt to cache this session.
*/
session->reuse_count = 0;
/*
* Cleanup.
*/

View File

@ -13,15 +13,18 @@ CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG= smtpd_token smtpd_check
PROG = smtpd
INC_DIR = ../../include
LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libdns.a ../../lib/libutil.a
LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \
../../lib/libglobal.a ../../lib/libutil.a
.c.o:; $(CC) $(CFLAGS) -c $*.c
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
(cat ../../conf/makedefs.out $?) >$@
test: $(TESTPROG)
@ -61,7 +64,7 @@ tidy: clean
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
$(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
@ -149,9 +152,17 @@ smtpd.o: ../../include/quote_flags.h
smtpd.o: ../../include/lex_822.h
smtpd.o: ../../include/namadr_list.h
smtpd.o: ../../include/input_transp.h
smtpd.o: ../../include/is_header.h
smtpd.o: ../../include/anvil_clnt.h
smtpd.o: ../../include/attr_clnt.h
smtpd.o: ../../include/ehlo_mask.h
smtpd.o: ../../include/maps.h
smtpd.o: ../../include/valid_mailhost_addr.h
smtpd.o: ../../include/mail_server.h
smtpd.o: smtpd_token.h
smtpd.o: smtpd.h
smtpd.o: ../../include/myaddrinfo.h
smtpd.o: ../../include/tls.h
smtpd.o: smtpd_check.h
smtpd.o: smtpd_chat.h
smtpd.o: smtpd_sasl_proto.h
@ -180,7 +191,9 @@ smtpd_chat.o: ../../include/cleanup_user.h
smtpd_chat.o: ../../include/mail_error.h
smtpd_chat.o: ../../include/name_mask.h
smtpd_chat.o: smtpd.h
smtpd_chat.o: ../../include/myaddrinfo.h
smtpd_chat.o: ../../include/mail_stream.h
smtpd_chat.o: ../../include/tls.h
smtpd_chat.o: smtpd_chat.h
smtpd_check.o: smtpd_check.c
smtpd_check.o: ../../include/sys_defs.h
@ -201,19 +214,25 @@ smtpd_check.o: ../../include/mac_expand.h
smtpd_check.o: ../../include/mac_parse.h
smtpd_check.o: ../../include/attr_clnt.h
smtpd_check.o: ../../include/attr.h
smtpd_check.o: ../../include/myaddrinfo.h
smtpd_check.o: ../../include/inet_proto.h
smtpd_check.o: ../../include/dns.h
smtpd_check.o: ../../include/sock_addr.h
smtpd_check.o: ../../include/string_list.h
smtpd_check.o: ../../include/match_list.h
smtpd_check.o: ../../include/match_ops.h
smtpd_check.o: ../../include/namadr_list.h
smtpd_check.o: ../../include/domain_list.h
smtpd_check.o: ../../include/mail_params.h
smtpd_check.o: ../../include/canon_addr.h
smtpd_check.o: ../../include/rewrite_clnt.h
smtpd_check.o: ../../include/mail_proto.h
smtpd_check.o: ../../include/iostuff.h
smtpd_check.o: ../../include/resolve_clnt.h
smtpd_check.o: ../../include/mail_error.h
smtpd_check.o: ../../include/name_mask.h
smtpd_check.o: ../../include/resolve_local.h
smtpd_check.o: ../../include/own_inet_addr.h
smtpd_check.o: ../../include/inet_addr_list.h
smtpd_check.o: ../../include/mail_conf.h
smtpd_check.o: ../../include/maps.h
smtpd_check.o: ../../include/mail_addr_find.h
@ -223,33 +242,38 @@ smtpd_check.o: ../../include/virtual8_maps.h
smtpd_check.o: ../../include/cleanup_user.h
smtpd_check.o: ../../include/record.h
smtpd_check.o: ../../include/rec_type.h
smtpd_check.o: ../../include/mail_proto.h
smtpd_check.o: ../../include/iostuff.h
smtpd_check.o: ../../include/mail_addr.h
smtpd_check.o: ../../include/verify_clnt.h
smtpd_check.o: ../../include/deliver_request.h
smtpd_check.o: ../../include/recipient_list.h
smtpd_check.o: ../../include/input_transp.h
smtpd_check.o: ../../include/is_header.h
smtpd_check.o: ../../include/valid_mailhost_addr.h
smtpd_check.o: smtpd.h
smtpd_check.o: ../../include/mail_stream.h
smtpd_check.o: ../../include/tls.h
smtpd_check.o: smtpd_sasl_glue.h
smtpd_check.o: smtpd_check.h
smtpd_peer.o: smtpd_peer.c
smtpd_peer.o: ../../include/sys_defs.h
smtpd_peer.o: ../../include/msg.h
smtpd_peer.o: ../../include/mymalloc.h
smtpd_peer.o: ../../include/valid_hostname.h
smtpd_peer.o: ../../include/stringops.h
smtpd_peer.o: ../../include/vstring.h
smtpd_peer.o: ../../include/vbuf.h
smtpd_peer.o: ../../include/myaddrinfo.h
smtpd_peer.o: ../../include/sock_addr.h
smtpd_peer.o: ../../include/inet_proto.h
smtpd_peer.o: ../../include/mail_proto.h
smtpd_peer.o: ../../include/vstream.h
smtpd_peer.o: ../../include/iostuff.h
smtpd_peer.o: ../../include/attr.h
smtpd_peer.o: ../../include/valid_mailhost_addr.h
smtpd_peer.o: ../../include/valid_hostname.h
smtpd_peer.o: smtpd.h
smtpd_peer.o: ../../include/argv.h
smtpd_peer.o: ../../include/mail_stream.h
smtpd_peer.o: ../../include/tls.h
smtpd_proxy.o: smtpd_proxy.c
smtpd_proxy.o: ../../include/sys_defs.h
smtpd_proxy.o: ../../include/msg.h
@ -270,7 +294,9 @@ smtpd_proxy.o: ../../include/mail_proto.h
smtpd_proxy.o: ../../include/attr.h
smtpd_proxy.o: smtpd.h
smtpd_proxy.o: ../../include/argv.h
smtpd_proxy.o: ../../include/myaddrinfo.h
smtpd_proxy.o: ../../include/mail_stream.h
smtpd_proxy.o: ../../include/tls.h
smtpd_proxy.o: smtpd_proxy.h
smtpd_sasl_glue.o: smtpd_sasl_glue.c
smtpd_sasl_glue.o: ../../include/sys_defs.h
@ -287,7 +313,9 @@ smtpd_sasl_glue.o: ../../include/vbuf.h
smtpd_sasl_glue.o: ../../include/vstream.h
smtpd_sasl_glue.o: smtpd.h
smtpd_sasl_glue.o: ../../include/argv.h
smtpd_sasl_glue.o: ../../include/myaddrinfo.h
smtpd_sasl_glue.o: ../../include/mail_stream.h
smtpd_sasl_glue.o: ../../include/tls.h
smtpd_sasl_glue.o: smtpd_sasl_glue.h
smtpd_sasl_glue.o: smtpd_chat.h
smtpd_sasl_proto.o: smtpd_sasl_proto.c
@ -306,7 +334,9 @@ smtpd_sasl_proto.o: ../../include/mail_error.h
smtpd_sasl_proto.o: ../../include/name_mask.h
smtpd_sasl_proto.o: smtpd.h
smtpd_sasl_proto.o: ../../include/argv.h
smtpd_sasl_proto.o: ../../include/myaddrinfo.h
smtpd_sasl_proto.o: ../../include/mail_stream.h
smtpd_sasl_proto.o: ../../include/tls.h
smtpd_sasl_proto.o: smtpd_token.h
smtpd_sasl_proto.o: smtpd_chat.h
smtpd_sasl_proto.o: smtpd_sasl_proto.h
@ -328,7 +358,9 @@ smtpd_state.o: ../../include/attr.h
smtpd_state.o: smtpd.h
smtpd_state.o: ../../include/vstring.h
smtpd_state.o: ../../include/argv.h
smtpd_state.o: ../../include/myaddrinfo.h
smtpd_state.o: ../../include/mail_stream.h
smtpd_state.o: ../../include/tls.h
smtpd_state.o: smtpd_chat.h
smtpd_state.o: smtpd_sasl_glue.h
smtpd_token.o: smtpd_token.c
@ -350,4 +382,6 @@ smtpd_xforward.o: ../../include/attr.h
smtpd_xforward.o: smtpd.h
smtpd_xforward.o: ../../include/vstring.h
smtpd_xforward.o: ../../include/argv.h
smtpd_xforward.o: ../../include/myaddrinfo.h
smtpd_xforward.o: ../../include/mail_stream.h
smtpd_xforward.o: ../../include/tls.h

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtpd.h,v 1.1.1.6 2004/05/31 00:24:48 heas Exp $ */
/* $NetBSD: smtpd.h,v 1.1.1.7 2005/08/18 21:09:12 rpaulo Exp $ */
/*++
/* NAME
@ -29,12 +29,20 @@
#include <vstream.h>
#include <vstring.h>
#include <argv.h>
#include <myaddrinfo.h>
/*
* Global library.
*/
#include <mail_stream.h>
/*
* Postfix TLS library.
*/
#ifdef USE_TLS
#include <tls.h>
#endif
/*
* Variables that keep track of conversation state. There is only one SMTP
* conversation at a time, so the state variables can be made global. And
@ -52,19 +60,24 @@ typedef struct {
char *name; /* name for access control */
char *addr; /* address for access control */
char *namaddr; /* name[address] */
char *rfc_addr; /* address for RFC 2821 */
char *protocol; /* email protocol */
char *helo_name; /* helo/ehlo parameter */
char *ident; /* message identifier */
char *domain; /* rewrite context */
} SMTPD_XFORWARD_ATTR;
typedef struct SMTPD_STATE {
int err; /* cleanup server/queue file errors */
VSTREAM *client; /* SMTP client handle */
VSTRING *buffer; /* SMTP client buffer */
char *service; /* for event rate control */
time_t time; /* start of MAIL FROM transaction */
char *name; /* client hostname */
char *addr; /* client host address string */
char *namaddr; /* combined name and address */
char *rfc_addr; /* address for RFC 2821 */
struct sockaddr_storage sockaddr; /* binary client endpoint */
int peer_code; /* 2=ok, 4=soft, 5=hard */
int error_count; /* reset after DOT */
int error_mask; /* client errors */
@ -86,8 +99,10 @@ typedef struct SMTPD_STATE {
char *where; /* protocol stage */
int recursion; /* Kellerspeicherpegelanzeiger */
off_t msg_size; /* MAIL FROM message size */
off_t act_size; /* END-OF-DATA message size */
int junk_cmds; /* counter */
int rcpt_overshoot; /* counter */
char *rewrite_context; /* address rewriting context */
/*
* SASL specific.
@ -138,6 +153,18 @@ typedef struct SMTPD_STATE {
* XFORWARD server state.
*/
SMTPD_XFORWARD_ATTR xforward; /* up-stream logging info */
/*
* TLS related state.
*/
#ifdef USE_TLS
int tls_use_tls; /* can use TLS */
int tls_enforce_tls; /* must use TLS */
int tls_auth_only; /* use SASL over TLS only */
TLScontext_t *tls_context; /* TLS session state */
tls_info_t tls_info; /* legacy */
#endif
} SMTPD_STATE;
#define SMTPD_STATE_XFORWARD_INIT (1<<0) /* xforward preset done */
@ -146,12 +173,13 @@ typedef struct SMTPD_STATE {
#define SMTPD_STATE_XFORWARD_PROTO (1<<3) /* protocol received */
#define SMTPD_STATE_XFORWARD_HELO (1<<4) /* client helo received */
#define SMTPD_STATE_XFORWARD_IDENT (1<<5) /* message identifier */
#define SMTPD_STATE_XFORWARD_DOMAIN (1<<6) /* message identifier */
#define SMTPD_STATE_XFORWARD_CLIENT_MASK \
(SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR \
| SMTPD_STATE_XFORWARD_PROTO | SMTPD_STATE_XFORWARD_HELO)
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *, const char *);
extern void smtpd_state_reset(SMTPD_STATE *);
/*
@ -174,6 +202,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
#define CLIENT_HELO_UNKNOWN 0
#define CLIENT_PROTO_UNKNOWN CLIENT_ATTR_UNKNOWN
#define CLIENT_IDENT_UNKNOWN 0
#define CLIENT_DOMAIN_UNKNOWN 0
#define IS_AVAIL_CLIENT_ATTR(v) ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
@ -183,6 +212,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
#define IS_AVAIL_CLIENT_HELO(v) ((v) != 0)
#define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v)
#define IS_AVAIL_CLIENT_IDENT(v) ((v) != 0)
#define IS_AVAIL_CLIENT_DOMAIN(v) ((v) != 0)
/*
* If running in stand-alone mode, do not try to talk to Postfix daemons but
@ -229,16 +259,19 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
(((s)->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK) ? \
(s)->xforward.a : (s)->a)
#define FORWARD_IDENT_ATTR(s) \
(((s)->xforward.flags & SMTPD_STATE_XFORWARD_IDENT) ? \
(s)->queue_id : (s)->ident)
#define FORWARD_ADDR(s) FORWARD_CLIENT_ATTR((s), addr)
#define FORWARD_ADDR(s) FORWARD_CLIENT_ATTR((s), rfc_addr)
#define FORWARD_NAME(s) FORWARD_CLIENT_ATTR((s), name)
#define FORWARD_NAMADDR(s) FORWARD_CLIENT_ATTR((s), namaddr)
#define FORWARD_PROTO(s) FORWARD_CLIENT_ATTR((s), protocol)
#define FORWARD_HELO(s) FORWARD_CLIENT_ATTR((s), helo_name)
#define FORWARD_IDENT(s) FORWARD_IDENT_ATTR(s)
#define FORWARD_IDENT(s) \
(((s)->xforward.flags & SMTPD_STATE_XFORWARD_IDENT) ? \
(s)->queue_id : (s)->ident)
#define FORWARD_DOMAIN(s) \
(((s)->xforward.flags & SMTPD_STATE_XFORWARD_DOMAIN) ? \
(s)->xforward.domain : (s)->rewrite_context)
extern void smtpd_xforward_init(SMTPD_STATE *);
extern void smtpd_xforward_preset(SMTPD_STATE *);
@ -259,4 +292,11 @@ extern int smtpd_input_transp_mask;
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* TLS support originally by:
/* Lutz Jaenicke
/* BTU Cottbus
/* Allgemeine Elektrotechnik
/* Universitaetsplatz 3-4
/* D-03044 Cottbus, Germany
/*--*/

View File

@ -0,0 +1,20 @@
#
# Initialize.
#
#! ../bin/postmap smtpd_check_access
#msg_verbose 1
smtpd_delay_reject 0
mynetworks 127.0.0.0/8,168.100.189.0/28
#
# MX backup
#
mydestination wzv.porcupine.org,localhost.porcupine.org
inet_interfaces 168.100.189.7,127.0.0.1
recipient_restrictions permit_mx_backup,reject
rcpt wietse@wzv.porcupine.org
rcpt wietse@fist.porcupine.org
rcpt wietse@porcupine.org
permit_mx_backup_networks 168.100.189.5
rcpt wietse@fist.porcupine.org
permit_mx_backup_networks 168.100.189.4
rcpt wietse@fist.porcupine.org

View File

@ -0,0 +1,34 @@
>>> #
>>> # Initialize.
>>> #
>>> #! ../bin/postmap smtpd_check_access
>>> #msg_verbose 1
>>> smtpd_delay_reject 0
OK
>>> mynetworks 127.0.0.0/8,168.100.189.0/28
OK
>>> #
>>> # MX backup
>>> #
>>> mydestination wzv.porcupine.org,localhost.porcupine.org
OK
>>> inet_interfaces 168.100.189.7,127.0.0.1
OK
>>> recipient_restrictions permit_mx_backup,reject
OK
>>> rcpt wietse@wzv.porcupine.org
OK
>>> rcpt wietse@fist.porcupine.org
OK
>>> rcpt wietse@porcupine.org
./smtpd_check: <queue id>: reject: RCPT from localhost[127.0.0.1]: 554 <wietse@porcupine.org>: Recipient address rejected: Access denied; to=<wietse@porcupine.org> proto=SMTP
554 <wietse@porcupine.org>: Recipient address rejected: Access denied
>>> permit_mx_backup_networks 168.100.189.5
OK
>>> rcpt wietse@fist.porcupine.org
./smtpd_check: <queue id>: reject: RCPT from localhost[127.0.0.1]: 554 <wietse@fist.porcupine.org>: Recipient address rejected: Access denied; to=<wietse@fist.porcupine.org> proto=SMTP
554 <wietse@fist.porcupine.org>: Recipient address rejected: Access denied
>>> permit_mx_backup_networks 168.100.189.4
OK
>>> rcpt wietse@fist.porcupine.org
OK

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtpd_check.h,v 1.1.1.5 2004/05/31 00:24:49 heas Exp $ */
/* $NetBSD: smtpd_check.h,v 1.1.1.6 2005/08/18 21:09:26 rpaulo Exp $ */
/*++
/* NAME
@ -16,6 +16,7 @@
*/
extern void smtpd_check_init(void);
extern int smtpd_check_addr(const char *);
extern void smtpd_check_rewrite(SMTPD_STATE *);
extern char *smtpd_check_client(SMTPD_STATE *);
extern char *smtpd_check_helo(SMTPD_STATE *, char *);
extern char *smtpd_check_mail(SMTPD_STATE *, char *);
@ -23,6 +24,7 @@ extern char *smtpd_check_size(SMTPD_STATE *, off_t);
extern char *smtpd_check_rcpt(SMTPD_STATE *, char *);
extern char *smtpd_check_etrn(SMTPD_STATE *, char *);
extern char *smtpd_check_data(SMTPD_STATE *);
extern char *smtpd_check_eod(SMTPD_STATE *);
extern char *smtpd_check_policy(SMTPD_STATE *, char *);
/* LICENSE

View File

@ -34,6 +34,10 @@ helo random.bad.domain
helo friend.bad.domain
helo_restrictions reject_invalid_hostname,reject_unknown_hostname
helo 123.123.123.123
helo [123.123.123.123]
helo [::]
helo [ipv6:::]
helo [ipv6::::]
helo_restrictions permit_naked_ip_address,reject_invalid_hostname,reject_unknown_hostname
helo 123.123.123.123
#

View File

@ -69,6 +69,16 @@ OK
>>> helo 123.123.123.123
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <123.123.123.123>: Helo command rejected: Host not found; proto=SMTP helo=<123.123.123.123>
450 <123.123.123.123>: Helo command rejected: Host not found
>>> helo [123.123.123.123]
OK
>>> helo [::]
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 501 <[::]>: Helo command rejected: invalid ip address; proto=SMTP helo=<[::]>
501 <[::]>: Helo command rejected: invalid ip address
>>> helo [ipv6:::]
OK
>>> helo [ipv6::::]
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 501 <[ipv6::::]>: Helo command rejected: invalid ip address; proto=SMTP helo=<[ipv6::::]>
501 <[ipv6::::]>: Helo command rejected: invalid ip address
>>> helo_restrictions permit_naked_ip_address,reject_invalid_hostname,reject_unknown_hostname
OK
>>> helo 123.123.123.123

Some files were not shown because too many files have changed in this diff Show More