The edit is done on a copy, and the copy is renamed into
the place of the original. File: postconf/postconf.c,
util/readlline.[hc].
+
+19991117
+
+ Feature: on systems with h_errno, the "reject_unknown_client"
+ restriction now distinguishes between soft errors (always
+ reply with 450) and hard errors (use the user-specified
+ reply code). This should lessen the load by broken mailers
+ that re-connect once a minute.
+
+ Feature: forward/reverse name/address check for SMTP client
+ hostnames. This fends off some hypothetical attacks by
+ spammers who are in control of their own reverse mapping.
+
+ Robustness: postconf no longer aborts when it can't figure
+ out the local domain name; it prints a warning instead.
+ This allows you to use "postconf -e" to fix the problem.
PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc
umask 022
-# Workaround, should edit main.cf in place.
-trap 'rm -f ./main.cf; exit' 0 1 2 3 15
+# Default settings, edit to taste or change interactively. Once this
+# script has run it saves settings to $config_directory/install.cf.
+
+config_directory=/etc/postfix
+daemon_directory=/usr/libexec/postfix
+command_directory=/usr/sbin
+queue_directory=/var/spool/postfix
+sendmail_path=/usr/sbin/sendmail
+newaliases_path=/usr/bin/newaliases
+mailq_path=/usr/bin/mailq
+mail_owner=postfix
+setgid=no
+manpages=no
+
+# Load defaults from existing installation.
+
+test -f $config_directory/main.cf && {
+ for name in daemon_directory command_directory queue_directory mail_owner
+ do
+ eval "$name=\"\`bin/postconf -h $name || kill \$\$\`\""
+ done
+}
+
+test -f $config_directory/install.cf && . $config_directory/install.cf
cat <<EOF
Warning: this script replaces existing sendmail or Postfix programs.
Make backups if you want to be able to recover.
-Otherwise, the script should be safe for installing or upgrading
-Postfix. Existing configuration and queue files are left alone;
-existing program files and scripts are replaced, not overwritten.
-This is safe unless you are sharing files over NFS.
-
-In particular, this script can be used to change Postfix from using
-a world-writable maildrop to a group-writable one.
+In addition to doing a fresh install, this script can change an
+existing installation from using a world-writable maildrop to a
+group-writable one. It cannot be used to change Postfix queue
+ownership.
Before installing files, this script prompts you for some definitions.
You can either edit this script ahead of time, or you can specify
newaliases_path - full pathname of the Postfix newaliases command.
mailq_path - full pathname of the Postfix mailq command.
- owner - owner of Postfix queue files.
+ mail_owner - owner of Postfix queue files.
setgid - groupname, e.g., postdrop (default: no). See INSTALL section 12.
manpages - path to man tree (default: no). Example: /usr/local/man.
EOF
-# Default settings, edit to taste or change interactively. Once this
-# script has run it saves settings to $config_directory/install.cf.
-
-# *BSD, LINUX
-config_directory=/etc/postfix
-daemon_directory=/usr/libexec/postfix
-command_directory=/usr/sbin
-queue_directory=/var/spool/postfix
-sendmail_path=/usr/sbin/sendmail
-newaliases_path=/usr/bin/newaliases
-mailq_path=/usr/bin/mailq
-owner=postfix
-setgid=no
-manpages=no
-
-# Solaris, System V.4
-#config_directory=/etc/postfix
-#daemon_directory=/usr/lib/postfix
-#command_directory=/usr/sbin
-#queue_directory=/var/spool/postfix
-#sendmail_path=/usr/lib/sendmail
-#newaliases_path=/usr/bin/newaliases
-#mailq_path=/usr/bin/mailq
-#owner=postfix
-#setgid=no
-#manpages=no
-
-# SunOS 4
-#config_directory=/etc/postfix
-#daemon_directory=/usr/lib/postfix
-#command_directory=/usr/etc
-#queue_directory=/var/spool/postfix
-#sendmail_path=/usr/lib/sendmail
-#newaliases_path=/usr/ucb/newaliases
-#mailq_path=/usr/ucb/mailq
-#owner=postfix
-#setgid=no
-#manpages=no
-
-test -f $config_directory/install.cf && . $config_directory/install.cf
-
# By now, shells must have functions. Ultrix users must use sh5 or lose.
compare_or_replace() {
esac
for name in config_directory daemon_directory command_directory \
- queue_directory sendmail_path newaliases_path mailq_path owner \
+ queue_directory sendmail_path newaliases_path mailq_path mail_owner \
setgid manpages
do
while :
esac
done
-# Workaround, should edit main.cf in place.
-test -f $config_directory/main.cf || {
- echo "mail_owner = $owner" >./main.cf
- echo "myhostname = xx.yy" >>./main.cf
- alt_main="-c ."
-}
-
-bin/postmap $alt_main -q "$owner" unix:passwd.byname >/dev/null || {
- echo "$owner needs an entry in the passwd file" 1>&2
- echo "Remember, $owner must have a dedicated user id and group id." 1>&2
- exit 1
-}
-
-case $setgid in
-no) ;;
- *) bin/postmap $alt_main -q "$setgid" unix:group.byname >/dev/null || {
- echo "$setgid needs an entry in the group file" 1>&2
- echo "Remember, $setgid must have a dedicated group id." 1>&2
- exit 1
- }
-esac
-
# Create any missing directories.
test -d $config_directory || mkdir -p $config_directory || exit 1
test -d $command_directory || mkdir -p $command_directory || exit 1
test -d $queue_directory || mkdir -p $queue_directory || exit 1
-# Save settings.
-
-(echo "# This file was generated by $0"
-for name in config_directory daemon_directory command_directory \
- queue_directory sendmail_path newaliases_path mailq_path owner \
- setgid manpages
-do
- eval echo $name=\$$name
-done) >junk || exit 1
-compare_or_move a+x,go-w junk $config_directory/install.cf || exit 1
-rm -f junk
-
# Install files. Be careful to not copy over running programs.
for file in `ls libexec`
test -f $config_directory/main.cf || {
cp conf/* $config_directory || exit 1
chmod a+r,go-w $config_directory/* || exit 1
- sed "
- s;^daemon_directory .*;daemon_directory = $daemon_directory;
- s;^command_directory .*;command_directory = $command_directory;
- s;^queue_directory .*;queue_directory = $queue_directory;
- s;^mail_owner .*;mail_owner = $owner;
- " conf/main.cf >$config_directory/main.cf || exit 1
echo "Warning: you still need to edit myorigin/mydestination in" 1>&2
echo "$config_directory/main.cf. See also html/faq.html for dialup" 1>&2
echo "for root and postmaster, then run the newaliases command." 1>&2
}
+# Save settings.
+
+postconf -e \
+ "daemon_directory = $daemon_directory" \
+ "command_directory = $command_directory" \
+ "queue_directory = $queue_directory" \
+ "mail_owner = $mail_owner" \
+|| exit 1
+
+(echo "# This file was generated by $0"
+for name in config_directory sendmail_path newaliases_path mailq_path \
+ setgid manpages
+do
+ eval echo $name=\$$name
+done) >junk || exit 1
+compare_or_move a+x,go-w junk $config_directory/install.cf || exit 1
+rm -f junk
+
# Use set-gid privileges instead of writable maildrop (optional).
test -d $queue_directory/maildrop || {
cleanup.o: ../include/mymalloc.h
cleanup.o: ../include/iostuff.h
cleanup.o: ../include/dict.h
+cleanup.o: ../include/argv.h
cleanup.o: ../include/mail_conf.h
cleanup.o: ../include/cleanup_user.h
cleanup.o: ../include/mail_queue.h
cleanup.o: ../include/ext_prop.h
cleanup.o: ../include/mail_server.h
cleanup.o: cleanup.h
-cleanup.o: ../include/argv.h
cleanup.o: ../include/maps.h
cleanup.o: ../include/tok822.h
cleanup.o: ../include/resolve_clnt.h
cleanup_map11.o: ../include/vbuf.h
cleanup_map11.o: ../include/dict.h
cleanup_map11.o: ../include/vstream.h
+cleanup_map11.o: ../include/argv.h
cleanup_map11.o: ../include/mymalloc.h
cleanup_map11.o: ../include/cleanup_user.h
cleanup_map11.o: ../include/mail_addr_map.h
-cleanup_map11.o: ../include/argv.h
cleanup_map11.o: ../include/maps.h
cleanup_map11.o: ../include/quote_822_local.h
cleanup_map11.o: cleanup.h
(cp) += 4; \
}
+#endif
+
+ /*
+ * SunOS 4 needs this.
+ */
+#ifndef T_TXT
+#define T_TXT 16
#endif
/*
mail_addr_find.o: ../include/dict.h
mail_addr_find.o: ../include/vstream.h
mail_addr_find.o: ../include/vbuf.h
+mail_addr_find.o: ../include/argv.h
mail_addr_find.o: ../include/stringops.h
mail_addr_find.o: ../include/mymalloc.h
mail_addr_find.o: ../include/vstring.h
mail_conf.o: ../include/vbuf.h
mail_conf.o: ../include/vstring.h
mail_conf.o: ../include/dict.h
+mail_conf.o: ../include/argv.h
mail_conf.o: ../include/safe.h
mail_conf.o: ../include/stringops.h
mail_conf.o: mail_params.h
mail_conf_bool.o: ../include/dict.h
mail_conf_bool.o: ../include/vstream.h
mail_conf_bool.o: ../include/vbuf.h
+mail_conf_bool.o: ../include/argv.h
mail_conf_bool.o: mail_conf.h
mail_conf_int.o: mail_conf_int.c
mail_conf_int.o: ../include/sys_defs.h
mail_conf_int.o: ../include/dict.h
mail_conf_int.o: ../include/vstream.h
mail_conf_int.o: ../include/vbuf.h
+mail_conf_int.o: ../include/argv.h
mail_conf_int.o: ../include/stringops.h
mail_conf_int.o: mail_conf.h
mail_conf_raw.o: mail_conf_raw.c
mkmap_db.o: ../include/dict.h
mkmap_db.o: ../include/vstream.h
mkmap_db.o: ../include/vbuf.h
+mkmap_db.o: ../include/argv.h
mkmap_db.o: ../include/dict_db.h
mkmap_db.o: mkmap.h
mkmap_dbm.o: mkmap_dbm.c
mkmap_dbm.o: ../include/dict.h
mkmap_dbm.o: ../include/vstream.h
mkmap_dbm.o: ../include/vbuf.h
+mkmap_dbm.o: ../include/argv.h
mkmap_dbm.o: ../include/dict_dbm.h
mkmap_dbm.o: mkmap.h
mkmap_open.o: mkmap_open.c
mkmap_open.o: ../include/dict.h
mkmap_open.o: ../include/vstream.h
mkmap_open.o: ../include/vbuf.h
+mkmap_open.o: ../include/argv.h
mkmap_open.o: ../include/sigdelay.h
mkmap_open.o: ../include/mymalloc.h
mkmap_open.o: ../include/myflock.h
/* const char *transport;
/* DESCRIPTION
/* This module uses the information kept in the "local_transports"
-/* configuration parameter, which lists the names of the default
-/* local transport followed by zero or more other transports that
+/* configuration parameter, which lists the name of the default
+/* local transport, followed by zero or more other transports that
/* deliver locally.
/*
/* def_local_transport() returns the name of the default local
/*
* Initialize on the fly.
*/
- if (local_transport_list == 0)
+ if (local_transport_name == 0)
local_transport_init();
/*
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19991116"
+#define DEF_MAIL_VERSION "Snapshot-19991117"
extern char *var_mail_version;
/* LICENSE
local.o: ../include/name_mask.h
local.o: ../include/set_eugid.h
local.o: ../include/dict.h
+local.o: ../include/argv.h
local.o: ../include/recipient_list.h
local.o: ../include/deliver_request.h
local.o: ../include/deliver_completed.h
recipient.o: ../include/dict.h
recipient.o: ../include/vstream.h
recipient.o: ../include/vbuf.h
+recipient.o: ../include/argv.h
recipient.o: ../include/bounce.h
recipient.o: ../include/mail_params.h
recipient.o: ../include/split_addr.h
postalias.o: ../include/mail_params.h
postalias.o: ../include/mkmap.h
postalias.o: ../include/dict.h
+postalias.o: ../include/argv.h
postconf.o: ../include/stringops.h
postconf.o: ../include/htable.h
postconf.o: ../include/dict.h
+postconf.o: ../include/argv.h
postconf.o: ../include/safe.h
postconf.o: ../include/mymalloc.h
-postconf.o: ../include/line_wrap.h
+postconf.o: ../include/split_at.h
+postconf.o: ../include/readlline.h
+postconf.o: ../include/vstring.h
+postconf.o: ../include/myflock.h
postconf.o: ../include/mynetworks.h
postconf.o: ../include/mail_conf.h
postconf.o: ../include/mail_proto.h
*/
name = get_hostname();
if ((mode & SHOW_DEFS) == 0 && (dot = strchr(name, '.')) == 0) {
- if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
- msg_fatal("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
- name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
- name = concatenate(name, ".", domain, (char *) 0);
+ if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0) {
+ msg_warn("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
+ name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
+ } else {
+ name = concatenate(name, ".", domain, (char *) 0);
+ }
}
return (name);
}
if ((value = split_at(cp, '=')) == 0
|| *(cp += strspn(cp, " \t\r\n")) == 0)
msg_fatal("edit requires \"key = value\" arguments");
+ while (*value && ISSPACE(*value))
+ value++;
cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue));
cvalue->value = value;
cvalue->found = 0;
postmap.o: ../include/mail_params.h
postmap.o: ../include/mkmap.h
postmap.o: ../include/dict.h
+postmap.o: ../include/argv.h
qmgr.o: ../include/vstream.h
qmgr.o: ../include/vbuf.h
qmgr.o: ../include/dict.h
+qmgr.o: ../include/argv.h
qmgr.o: ../include/mail_queue.h
qmgr.o: ../include/vstring.h
qmgr.o: ../include/recipient_list.h
qmgr_active.o: ../include/scan_dir.h
qmgr_active.o: ../include/maps.h
qmgr_active.o: ../include/dict.h
+qmgr_active.o: ../include/argv.h
qmgr_bounce.o: qmgr_bounce.c
qmgr_bounce.o: ../include/sys_defs.h
qmgr_bounce.o: ../include/bounce.h
qmgr_bounce.o: ../include/scan_dir.h
qmgr_bounce.o: ../include/maps.h
qmgr_bounce.o: ../include/dict.h
+qmgr_bounce.o: ../include/argv.h
qmgr_defer.o: qmgr_defer.c
qmgr_defer.o: ../include/sys_defs.h
qmgr_defer.o: ../include/msg.h
qmgr_defer.o: ../include/scan_dir.h
qmgr_defer.o: ../include/maps.h
qmgr_defer.o: ../include/dict.h
+qmgr_defer.o: ../include/argv.h
qmgr_deliver.o: qmgr_deliver.c
qmgr_deliver.o: ../include/sys_defs.h
qmgr_deliver.o: ../include/msg.h
qmgr_deliver.o: ../include/scan_dir.h
qmgr_deliver.o: ../include/maps.h
qmgr_deliver.o: ../include/dict.h
+qmgr_deliver.o: ../include/argv.h
qmgr_enable.o: qmgr_enable.c
qmgr_enable.o: ../include/sys_defs.h
qmgr_enable.o: ../include/msg.h
qmgr_enable.o: ../include/scan_dir.h
qmgr_enable.o: ../include/maps.h
qmgr_enable.o: ../include/dict.h
+qmgr_enable.o: ../include/argv.h
qmgr_entry.o: qmgr_entry.c
qmgr_entry.o: ../include/sys_defs.h
qmgr_entry.o: ../include/msg.h
qmgr_entry.o: ../include/scan_dir.h
qmgr_entry.o: ../include/maps.h
qmgr_entry.o: ../include/dict.h
+qmgr_entry.o: ../include/argv.h
qmgr_message.o: qmgr_message.c
qmgr_message.o: ../include/sys_defs.h
qmgr_message.o: ../include/msg.h
qmgr_message.o: ../include/mail_addr_find.h
qmgr_message.o: ../include/maps.h
qmgr_message.o: ../include/opened.h
+qmgr_message.o: ../include/local_transport.h
qmgr_message.o: ../include/resolve_clnt.h
qmgr_message.o: qmgr.h
qmgr_message.o: ../include/scan_dir.h
qmgr_move.o: qmgr.h
qmgr_move.o: ../include/maps.h
qmgr_move.o: ../include/dict.h
+qmgr_move.o: ../include/argv.h
qmgr_queue.o: qmgr_queue.c
qmgr_queue.o: ../include/sys_defs.h
qmgr_queue.o: ../include/msg.h
qmgr_queue.o: ../include/scan_dir.h
qmgr_queue.o: ../include/maps.h
qmgr_queue.o: ../include/dict.h
+qmgr_queue.o: ../include/argv.h
qmgr_rcpt_list.o: qmgr_rcpt_list.c
qmgr_rcpt_list.o: ../include/sys_defs.h
qmgr_rcpt_list.o: ../include/mymalloc.h
qmgr_rcpt_list.o: ../include/scan_dir.h
qmgr_rcpt_list.o: ../include/maps.h
qmgr_rcpt_list.o: ../include/dict.h
+qmgr_rcpt_list.o: ../include/argv.h
qmgr_scan.o: qmgr_scan.c
qmgr_scan.o: ../include/sys_defs.h
qmgr_scan.o: ../include/msg.h
qmgr_scan.o: ../include/vbuf.h
qmgr_scan.o: ../include/maps.h
qmgr_scan.o: ../include/dict.h
+qmgr_scan.o: ../include/argv.h
qmgr_transport.o: qmgr_transport.c
qmgr_transport.o: ../include/sys_defs.h
qmgr_transport.o: ../include/msg.h
qmgr_transport.o: ../include/scan_dir.h
qmgr_transport.o: ../include/maps.h
qmgr_transport.o: ../include/dict.h
+qmgr_transport.o: ../include/argv.h
trigger_server_main(argc, argv, qmgr_trigger_event,
MAIL_SERVER_INT_TABLE, int_table,
MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_BOOL_TABLE, bool_table,
MAIL_SERVER_PRE_INIT, qmgr_pre_init,
MAIL_SERVER_POST_INIT, qmgr_post_init,
MAIL_SERVER_LOOP, qmgr_loop,
smtp.o: ../include/dict.h
smtp.o: ../include/vstream.h
smtp.o: ../include/vbuf.h
+smtp.o: ../include/argv.h
smtp.o: ../include/msg.h
smtp.o: ../include/mymalloc.h
smtp.o: ../include/name_mask.h
smtp.o: ../include/iostuff.h
smtp.o: ../include/mail_server.h
smtp.o: smtp.h
-smtp.o: ../include/argv.h
smtp_addr.o: smtp_addr.c
smtp_addr.o: ../include/sys_defs.h
smtp_addr.o: ../include/msg.h
SHELL = /bin/sh
-SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c
-OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o
+SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
+ smtpd_peer.c
+OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
+ smtpd_peer.o
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h
TESTSRC = smtpd_token_test.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
../libexec/$(PROG): $(PROG)
cp $(PROG) ../libexec
-SMTPD_CHECK_OBJ = smtpd_state.o
+SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o
smtpd_token: smtpd_token.c $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
smtpd.o: ../include/smtp_stream.h
smtpd.o: ../include/valid_hostname.h
smtpd.o: ../include/dict.h
-smtpd.o: ../include/peer_name.h
+smtpd.o: ../include/argv.h
smtpd.o: ../include/mail_params.h
smtpd.o: ../include/record.h
smtpd.o: ../include/rec_type.h
smtpd.o: ../include/mail_server.h
smtpd.o: smtpd_token.h
smtpd.o: smtpd.h
-smtpd.o: ../include/argv.h
smtpd.o: smtpd_check.h
smtpd.o: smtpd_chat.h
smtpd_chat.o: smtpd_chat.c
smtpd_check.o: smtpd.h
smtpd_check.o: ../include/mail_stream.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: smtpd.h
+smtpd_peer.o: ../include/vstream.h
+smtpd_peer.o: ../include/vbuf.h
+smtpd_peer.o: ../include/vstring.h
+smtpd_peer.o: ../include/argv.h
+smtpd_peer.o: ../include/mail_stream.h
smtpd_state.o: smtpd_state.c
smtpd_state.o: ../include/sys_defs.h
smtpd_state.o: ../include/events.h
smtpd_state.o: ../include/vstream.h
smtpd_state.o: ../include/vbuf.h
smtpd_state.o: ../include/name_mask.h
-smtpd_state.o: ../include/stringops.h
smtpd_state.o: ../include/cleanup_user.h
smtpd_state.o: ../include/mail_params.h
smtpd_state.o: ../include/mail_error.h
/* Global library. */
-#include <peer_name.h>
#include <mail_params.h>
#include <record.h>
#include <rec_type.h>
static void smtpd_service(VSTREAM *stream, char *unused_service, char **argv)
{
SMTPD_STATE state;
- PEER_NAME *peer;
/*
* Sanity check. This service takes no command-line arguments.
* take a while. This is why I always run a local name server on critical
* machines.
*/
- peer = peer_name(vstream_fileno(stream));
- smtpd_state_init(&state, stream, peer->name, peer->addr);
+ smtpd_state_init(&state, stream);
/*
* See if we need to turn on verbose logging for this client.
char *name;
char *addr;
char *namaddr;
+ int peer_code; /* 2=ok, 4=soft, 5=hard */
int error_count;
int error_mask;
int notify_mask;
char *where;
} SMTPD_STATE;
-extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *,
- const char *, const char *);
+extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
extern void smtpd_state_reset(SMTPD_STATE *);
/*
#define SMTPD_STAND_ALONE(state) \
(state->client == VSTREAM_IN && getuid() != var_owner_uid)
+ /*
+ * SMPTD peer information lookup.
+ */
+void smtpd_peer_init(SMTPD_STATE *state);
+void smtpd_peer_reset(SMTPD_STATE *state);
+
/* LICENSE
/* .ad
/* .fi
if (strcasecmp(state->name, "unknown") == 0)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d Client host rejected: cannot find your hostname, [%s]",
- var_unk_client_code, state->addr));
+ state->peer_code == 5 ?
+ var_unk_client_code : 450,
+ state->addr));
return (SMTPD_CHECK_DUNNO);
}
/* permit_auth_destination - OK for message relaying */
-static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
+static int permit_auth_destination(char *recipient)
{
char *myname = "permit_auth_destination";
char *domain;
status = permit_mx_backup(state, state->recipient);
} else if (strcasecmp(name, PERMIT_AUTH_DEST) == 0) {
if (state->recipient)
- status = permit_auth_destination(state, state->recipient);
+ status = permit_auth_destination(state->recipient);
} else if (strcasecmp(name, REJECT_UNAUTH_DEST) == 0) {
if (state->recipient)
status = reject_unauth_destination(state, state->recipient);
char *var_mydest;
char *var_inet_interfaces;
char *var_rest_classes;
+char *var_local_transports;
typedef struct {
char *name;
VAR_MYDEST, DEF_MYDEST, &var_mydest,
VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces,
VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes,
+ VAR_LOCAL_TRANSP, DEF_LOCAL_TRANSP, &var_local_transports,
0,
};
string_init();
int_init();
smtpd_check_init();
- smtpd_state_init(&state, VSTREAM_IN, "", "");
+ smtpd_state_init(&state, VSTREAM_IN);
state.queue_id = "<queue id>";
/*
/*
* Special case: client identity.
*/
+ case 4:
case 3:
#define UPDATE_STRING(ptr,val) { if (ptr) myfree(ptr); ptr = mystrdup(val); }
state.where = "CONNECT";
UPDATE_STRING(state.name, args->argv[1]);
UPDATE_STRING(state.addr, args->argv[2]);
+ if (args->argc == 4)
+ state.peer_code = atoi(args->argv[3]);
+ else
+ state.peer_code = 2;
if (state.namaddr)
myfree(state.namaddr);
state.namaddr = concatenate(state.name, "[", state.addr,
*/
default:
resp = "Commands...\n\
- client <name> <address>\n\
+ client <name> <address> [<code>]\n\
helo <hostname>\n\
sender <address>\n\
recipient <address>\n\
recipient_restrictions reject_unauth_destination,permit
rcpt user@foo.org
rcpt user@foo.com
+#
+# unknown client tests
+#
+unknown_client_reject_code 550
+client_restrictions reject_unknown_client
+client spike.porcupine.org 160.100.189.2 2
+client unknown 1.1.1.1 4
+client unknown 1.1.1.1 5
554 <user@foo.org>: Relay access denied
>>> rcpt user@foo.com
OK
+>>> #
+>>> # unknown client tests
+>>> #
+>>> unknown_client_reject_code 550
+OK
+>>> client_restrictions reject_unknown_client
+OK
+>>> client spike.porcupine.org 160.100.189.2 2
+OK
+>>> client unknown 1.1.1.1 4
+./smtpd_check: reject: CONNECT from unknown[1.1.1.1]: 450 Client host rejected: cannot find your hostname, [1.1.1.1]; from=<user@some.where>
+450 Client host rejected: cannot find your hostname, [1.1.1.1]
+>>> client unknown 1.1.1.1 5
+./smtpd_check: reject: CONNECT from unknown[1.1.1.1]: 550 Client host rejected: cannot find your hostname, [1.1.1.1]; from=<user@some.where>
+550 Client host rejected: cannot find your hostname, [1.1.1.1]
--- /dev/null
+/*++
+/* NAME
+/* smtpd_peer 3
+/* SUMMARY
+/* look up peer name/address information
+/* SYNOPSIS
+/* #include "smtpd.h"
+/*
+/* void smtpd_peer_init(state)
+/* SMTPD_STATE *state;
+/*
+/* void smtpd_peer_reset(state)
+/* SMTPD_STATE *state;
+/* DESCRIPTION
+/* The smtpd_peer_init() routine attempts to produce a printable
+/* version of the peer name and address of the specified socket.
+/* Where information is unavailable, the name and/or address
+/* are set to "unknown".
+/*
+/* smtpd_peer_init() updates the following fields:
+/* .IP name
+/* The client hostname. An unknown name is represented by the
+/* string "unknown".
+/* .IP addr
+/* Printable representation of the client address.
+/* .IP namaddr
+/* String of the form: "name[addr]".
+/* .IP peer_code
+/* The peer_code result field specifies how the client name
+/* information should be interpreted:
+/* .RS
+/* .IP 2
+/* Both name lookup and name verification succeeded.
+/* .IP 4
+/* The name lookup or name verification failed with a recoverable
+/* error (no address->name mapping or no name->address mapping).
+/* .IP 5
+/* The name lookup or verification failed with an unrecoverable
+/* error (no address->name mapping, bad hostname syntax, no
+/* name->address mapping, client address not listed for hostname).
+/* .RE
+/* .PP
+/* smtpd_peer_reset() releases memory allocate by smtpd_peer_init().
+/* 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 <netdb.h>
+#include <string.h>
+
+#ifdef NO_HERRNO
+static int h_errno = TRY_AGAIN;
+define hstrerror(x) "Host not found"
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <valid_hostname.h>
+#include <stringops.h>
+
+/* Global library. */
+
+
+/* Application-specific. */
+
+#include "smtpd.h"
+
+/* smtpd_peer_init - initialize peer information */
+
+void smtpd_peer_init(SMTPD_STATE *state)
+{
+ struct sockaddr_in sin;
+ SOCKADDR_SIZE len = sizeof(sin);
+ struct hostent *hp;
+ int i;
+
+ /*
+ * If it's not networked assume local.
+ */
+ if (getpeername(vstream_fileno(state->client),
+ (struct sockaddr *) & sin, &len) < 0)
+ sin.sin_family = AF_UNSPEC;
+
+ switch (sin.sin_family) {
+
+ /*
+ * If it's not Internet, assume the client is local, and avoid using
+ * the naming service because that can hang when the machine is
+ * disconnected.
+ */
+ default:
+ state->name = mystrdup("localhost");
+ state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
+ state->peer_code = 2;
+ break;
+
+ /*
+ * Look up and "verify" the client hostname.
+ */
+ case 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("unknown");
+ state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
+ break;
+ }
+ if (!valid_hostname(hp->h_name)) {
+ state->name = mystrdup("unknown");
+ state->peer_code = 5;
+ break;
+ }
+ state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
+ state->peer_code = 2;
+
+ /*
+ * Reject the hostname if it does not list the peer address.
+ */
+ hp = gethostbyname(state->name); /* clobbers hp->name!! */
+ if (hp == 0) {
+ msg_warn("hostname %s verification failed: %s",
+ state->name, hstrerror(h_errno));
+ myfree(state->name);
+ state->name = mystrdup("unknown");
+ state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
+ break;
+ }
+ if (hp->h_length != sizeof(sin.sin_addr)) {
+ msg_warn("hostname %s verification failed: bad address size %d",
+ state->name, hp->h_length);
+ myfree(state->name);
+ state->name = mystrdup("unknown");
+ state->peer_code = 5;
+ break;
+ }
+ for (i = 0; hp->h_addr_list[i]; i++) {
+ if (memcmp(hp->h_addr_list[i],
+ (char *) &sin.sin_addr,
+ sizeof(sin.sin_addr)) == 0)
+ break;
+ }
+ if (hp->h_addr_list[i] == 0) {
+ msg_warn("address %s not listed for name %s",
+ state->addr, state->name);
+ myfree(state->name);
+ state->name = mystrdup("unknown");
+ state->peer_code = 5;
+ break;
+ }
+ break;
+ }
+ state->namaddr =
+ concatenate(state->name, "[", state->addr, "]", (char *) 0);
+}
+
+/* smtpd_peer_reset - destroy peer information */
+
+void smtpd_peer_reset(SMTPD_STATE *state)
+{
+ if (state->name)
+ myfree(state->name);
+ if (state->addr)
+ myfree(state->addr);
+ if (state->namaddr)
+ myfree(state->namaddr);
+}
/* SYNOPSIS
/* #include "smtpd.h"
/*
-/* void smtpd_state_init(state, stream, name, addr)
+/* void smtpd_state_init(state, stream)
/* SMTPD_STATE *state;
/* VSTREAM *stream;
-/* const char *name;
-/* const char *addr;
/*
/* void smtpd_state_reset(state)
/* SMTPD_STATE *state;
/* Session context.
/* .IP stream
/* Stream connected to peer. The stream is not copied.
-/* .IP name
-/* Printable representation of the peer host name. The
-/* name is copied.
-/* .IP addr
-/* Printable representation of the peer host address. The
-/* address is copied.
/* DIAGNOSTICS
/* All errors are fatal.
/* LICENSE
#include <mymalloc.h>
#include <vstream.h>
#include <name_mask.h>
-#include <stringops.h>
/* Global library. */
/* smtpd_state_init - initialize after connection establishment */
-void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
- const char *name, const char *addr)
+void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
{
/*
state->err = CLEANUP_STAT_OK;
state->client = stream;
state->buffer = vstring_alloc(100);
- state->name = mystrdup(name);
- state->addr = mystrdup(addr);
- state->namaddr = concatenate(name, "[", addr, "]", (char *) 0);
state->error_count = 0;
state->error_mask = 0;
state->notify_mask = name_mask(mail_error_masks, var_notify_classes);
state->protocol = "SMTP";
state->where = SMTPD_AFTER_CONNECT;
+ /*
+ * Initialize peer information.
+ */
+ smtpd_peer_init(state);
+
/*
* Initialize the conversation history.
*/
*/
if (state->buffer)
vstring_free(state->buffer);
- if (state->name)
- myfree(state->name);
- if (state->addr)
- myfree(state->addr);
- if (state->namaddr)
- myfree(state->namaddr);
+ smtpd_peer_reset(state);
}
/*
/* typedef struct {
/* .in +4
+/* int tokval;
/* char *strval;
/* /* other stuff... */
/* .in -4
break;
} else { /* other */
if (c == '\\') {
+ VSTRING_ADDCH(arg->vstrval, c);
if ((c = *cp) == 0)
break;
cp++;
Token type: other
Token value: from:
Token type: other
-Token value: wietse venema@porcupine.org
+Token value: wietse\ venema@porcupine.org
mail to:<"wietse venema>
Token type: other
Token value: mail
resolve.o: ../include/quote_822_local.h
resolve.o: ../include/tok822.h
resolve.o: ../include/resolve_clnt.h
+resolve.o: ../include/local_transport.h
resolve.o: trivial-rewrite.h
resolve.o: transport.h
rewrite.o: rewrite.c
transport.o: ../include/split_at.h
transport.o: ../include/dict.h
transport.o: ../include/vstream.h
+transport.o: ../include/argv.h
transport.o: ../include/mail_params.h
transport.o: ../include/maps.h
transport.o: transport.h
trivial-rewrite.o: ../include/split_at.h
trivial-rewrite.o: ../include/stringops.h
trivial-rewrite.o: ../include/dict.h
+trivial-rewrite.o: ../include/argv.h
trivial-rewrite.o: ../include/mail_params.h
trivial-rewrite.o: ../include/mail_proto.h
trivial-rewrite.o: ../include/iostuff.h
/*
* Make sure the resolved envelope recipient has the user@domain form. If
* no domain was specified in the address, assume the local machine. See
- * above for what happens with an empty localpart.
+ * above for what happens with an empty address.
*/
if (domain == 0) {
if (saved_domain) {
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
/*
- * The transport map overrides the default transport and next-hop host
- * info that was set up just moments ago. For a long time, it was not
- * possible to override routing of mail that resolves locally, because
- * Postfix used a zero-length next-hop hostname result to indicate local
- * delivery, and transport maps cannot return zero-length hostnames.
+ * The transport map overrides any transport and next-hop host info that
+ * is set up below. For a long time, it was not possible to override
+ * routing of mail that resolves locally, because Postfix used a
+ * zero-length next-hop hostname result to indicate local delivery, and
+ * transport maps cannot return zero-length hostnames.
*/
if (*var_transport_maps
&& transport_lookup(strrchr(STR(nextrcpt), '@') + 1, channel, nexthop)) {
/*
* Local delivery. Set up the default local transport and the default
- * next-hop hostname.
+ * next-hop hostname (myself).
*/
else {
vstring_strcpy(channel, def_local_transport());
dict.o: readlline.h
dict.o: mac_parse.h
dict.o: dict.h
+dict.o: argv.h
dict.o: dict_ht.h
dict_db.o: dict_db.c
dict_db.o: sys_defs.h
dict_db.o: myflock.h
dict_db.o: dict.h
dict_db.o: vstream.h
+dict_db.o: argv.h
dict_db.o: dict_db.h
dict_dbm.o: dict_dbm.c
dict_dbm.o: sys_defs.h
dict_env.o: dict.h
dict_env.o: vstream.h
dict_env.o: vbuf.h
+dict_env.o: argv.h
dict_env.o: dict_env.h
dict_ht.o: dict_ht.c
dict_ht.o: sys_defs.h
dict_ht.o: dict.h
dict_ht.o: vstream.h
dict_ht.o: vbuf.h
+dict_ht.o: argv.h
dict_ht.o: dict_ht.h
dict_ldap.o: dict_ldap.c
dict_ldap.o: sys_defs.h
dict_nis.o: vbuf.h
dict_nis.o: dict.h
dict_nis.o: vstream.h
+dict_nis.o: argv.h
dict_nis.o: dict_nis.h
dict_nisplus.o: dict_nisplus.c
dict_nisplus.o: sys_defs.h
dict_nisplus.o: dict.h
dict_nisplus.o: vstream.h
dict_nisplus.o: vbuf.h
+dict_nisplus.o: argv.h
dict_nisplus.o: dict_nisplus.h
dict_open.o: dict_open.c
dict_open.o: sys_defs.h
dict_regexp.o: stringops.h
dict_regexp.o: readlline.h
dict_regexp.o: dict.h
+dict_regexp.o: argv.h
dict_regexp.o: dict_regexp.h
dict_regexp.o: mac_parse.h
dict_unix.o: dict_unix.c
dict_unix.o: vbuf.h
dict_unix.o: dict.h
dict_unix.o: vstream.h
+dict_unix.o: argv.h
dict_unix.o: dict_unix.h
dir_forest.o: dir_forest.c
dir_forest.o: sys_defs.h
match_ops.o: dict.h
match_ops.o: vstream.h
match_ops.o: vbuf.h
+match_ops.o: argv.h
match_ops.o: match_ops.h
match_ops.o: stringops.h
msg.o: msg.c
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
-/**INDENT** Error@47: Unmatched #endif */
#endif
#define S_ISSOCK(mode) (((mode) & (S_IFMT)) == (S_IFSOCK))
#define DUP2_DUPS_CLOSE_ON_EXEC
#define MISSING_USLEEP
+#define NO_HERRNO
#endif
#ifdef OSF1
#define USE_STATFS
#define STATFS_IN_SYS_VFS_H
#define memmove(d,s,l) bcopy(s,d,l)
+#define NO_HERRNO
#endif
#ifdef SUNOS5
wp->saved_watchdog = watchdog_curr;
wp->saved_time = alarm(0);
sigemptyset(&sig_action.sa_mask);
+#ifdef SA_RESTART
sig_action.sa_flags = SA_RESTART;
+#else
+ sig_action.sa_flags = 0;
+#endif
sig_action.sa_handler = watchdog_event;
if (sigaction(SIGALRM, &sig_action, &wp->saved_action) < 0)
msg_fatal("%s: sigaction(SIGALRM): %m", myname);