2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 05:38:06 +00:00

snapshot-20000421

This commit is contained in:
Wietse Venema 2000-04-21 00:00:00 +00:00
parent 17d46ec1c0
commit d69f7e550d
21 changed files with 607 additions and 105 deletions

View File

@ -3827,3 +3827,9 @@ Apologies for any names omitted.
Added LMTP support to the smtp-source and smtp-sink utilities
so that I don't have to install Cyrus IMAP just to test
LMTP.
20000419
Bugfix: removed the () from the tokenized representation
of RFC 822 comments, so that comments with \( or \) can be
unparsed correctly. Problem reported by Bodo Moeller.

View File

@ -2,31 +2,59 @@
# HERE JUST SERVES AS AN EXAMPLE.
#
# This file contains example settings of Postfix configuration
# parameters that control SMTP authentication
# parameters that control SASL authentication.
# As of now, SASL authentication support uses the Cyrus SASL library
# which is known to work on Linux and Solaris.
# SMTP SERVER CONTROLS
# The smtpd_sasl_auth_enable parameter controls whether authentication
# is enabled in the Postfix SMTP server.
#
# If a client is authenticated, then it matches the permit_sasl_authenticated
# UCE restriction, which can be used to grant mail relay access.
# If a client is authenticated, then the permit_sasl_authenticated
# can be used to permit relay access.
#
# In order to enable server-side authentication, build Postfix with
# SASL support, and install a configuration file /usr/lib/sasl/smtpd.conf
# with as contents, for example,
#
# pwcheck_method: PAM
# pwcheck_method: sasldb
#
# or whatever is suitable for your environment. The PAM service name
# for SASL authentication is "smtp".
# or whatever method is suitable for your environment: PAM, shadow,
# whatever. If you use sasldb, you can add users with the "saslpasswd"
# command that is part of the SASL library. If you use PAM, The PAM
# service name for SASL authentication is "smtp", and adding users
# depends entirely on how PAM is set up.
#
# If you run your SMTP server chrooted, then you need to copy the
# PAM and SASL support libraries and data files into the chroot jail.
# If you run your SMTP server chrooted, then you need to copy PAM
# and/or SASL support libraries and data files into the chroot jail.
#
smtpd_sasl_auth_enable = yes
# The smtpd_sasl_security_options parameter controls what authentication
# mechanisms the Postfix SMTP server will offer to the client. The
# list of available authentication mechanisms is system dependent.
#
# Specify zero or more of the following:
#
# noplaintext: disallow methods that use plaintext passwords
# noactive: disallow methods subject to active (non-dictionary) attack
# nodictionary: disallow methods subject to passive (dictionary) attack
# noanonymous: disallow methods that allow anonymous authentication
#
# By default, the Postfix SMTP server accepts plaintext passwords but
# not anonymous logins.
#
# Horror! It appears that clients try authentication methods in the
# order as advertised by the server (PLAIN ANONYMOUS CRAM-MD5
# ...) which means that if you disable plaintext passwords, clients
# will log in anonymously even when they would be able to use CRAM-MD5.
# So, if you disable plaintext logins, disable anonymous logins too.
# Postfix treats anonymous login as no authentication.
#
#smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_security_options = noanonymous
# SMTP CLIENT CONTROLS
# The smtp_sasl_auth_enable parameter controls whether authentication
# is enabled in the Postfix SMTP client.
#
@ -34,10 +62,26 @@ smtp_sasl_auth_enable = yes
# The smtp_sasl_password_maps parameter specifies the names of lookup
# tables with one username:password entry per remote hostname. If a
# remote host has no username:password entry, then Postfix will not
# attempt to authenticate to the host.
# remote host has no username:password entry, then the Postfix SMTP
# client will not attempt to authenticate to the remote host.
#
# The Postifx SMTP client opens the lookup table before going to
# The Postfix SMTP client opens the lookup table before going to
# chroot jail, so you can keep the password file in /etc/postfix.
#
smtp_auth_passwd_map = hash:/etc/postfix/saslpass
# The smtp_sasl_security_options parameter controls what authentication
# mechanisms the local Postfix SMTP client is allowed to use. The
# list of available authentication mechanisms is system dependent.
#
# Specify zero or more of the following:
#
# noplaintext: disallow methods that use plaintext passwords
# noactive: disallow methods subject to active (non-dictionary) attack
# nodictionary: disallow methods subject to passive (dictionary) attack
# noanonymous: disallow methods that allow anonymous authentication
#
# By default, the Postfix SMTP client will not use plaintext passwords.
#
#smtpd_sasl_security_options =
smtpd_sasl_security_options = noplaintext

View File

@ -63,8 +63,7 @@ LIB = libglobal.a
TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
off_cvt quote_822_local rec2stream recdump resolve_clnt \
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
local_transport
resolve_local rewrite_clnt stream2rec string_list tok822_parse
LIBS = ../lib/libutil.a
LIB_DIR = ../lib
@ -194,6 +193,13 @@ local_transport: $(LIB) $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
mv junk $@.o
tests: tok822_test
tok822_test: tok822_parse tok822_parse.in tok822_parse.ref
./tok822_parse <tok822_parse.in >tok822_parse.tmp
diff tok822_parse.ref tok822_parse.tmp
rm -f tok822_parse.tmp
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@ -559,6 +565,7 @@ mail_queue.o: ../include/argv.h
mail_queue.o: ../include/dir_forest.h
mail_queue.o: ../include/make_dirs.h
mail_queue.o: ../include/split_at.h
mail_queue.o: ../include/sane_fsops.h
mail_queue.o: file_id.h
mail_queue.o: mail_params.h
mail_queue.o: mail_queue.h

View File

@ -643,19 +643,30 @@ extern int var_smtpd_err_sleep;
extern int var_smtpd_junk_cmd_limit;
/*
* SASL authentication support.
* SASL authentication support, server side.
*/
#define VAR_SMTPD_SASL_ENABLE "smtpd_sasl_auth_enable"
#define DEF_SMTPD_SASL_ENABLE 0
extern bool var_smtpd_sasl_enable;
#define VAR_SMTPD_SASL_OPTS "smtpd_sasl_security_options"
#define DEF_SMTPD_SASL_OPTS "noanonymous"
extern char *var_smtpd_sasl_opts;
/*
* SASL authentication support, client side.
*/
#define VAR_SMTP_SASL_ENABLE "smtp_sasl_auth_enable"
#define DEF_SMTP_SASL_ENABLE 0
extern bool var_smtp_sasl_enable;
#define VAR_SMTP_SASL_PWD_MAPS "smtp_sasl_password_maps"
#define DEF_SMTP_SASL_PWD_MAPS ""
extern char *var_smtp_sasl_pwd_maps;
#define VAR_SMTP_SASL_PASSWD "smtp_sasl_password_maps"
#define DEF_SMTP_SASL_PASSWD ""
extern char *var_smtp_sasl_passwd;
#define VAR_SMTP_SASL_OPTS "smtp_sasl_security_options"
#define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous"
extern char *var_smtp_sasl_opts;
#define PERMIT_SASL_AUTH "permit_sasl_authenticated"

View File

@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20000418"
#define DEF_MAIL_VERSION "Snapshot-20000421"
extern char *var_mail_version;
/* LICENSE

View File

@ -45,7 +45,8 @@ typedef struct TOK822 {
#define TOK822_DOMLIT 259 /* stuff between [] not nesting */
#define TOK822_ADDR 260 /* actually a token group */
#define TOK822_STARTGRP 261 /* start of named group */
#define TOK822_MAXTOK 261
#define TOK822_COMMTEXT 262 /* comment text */
#define TOK822_MAXTOK 262
/*
* tok822_node.c

View File

@ -56,10 +56,13 @@ TOK822 *tok822_alloc(int type, const char *strval)
{
TOK822 *tp;
#define CONTAINER_TOKEN(x) \
((x) == TOK822_ADDR || (x) == TOK822_COMMENT || (x) == TOK822_STARTGRP)
tp = (TOK822 *) mymalloc(sizeof(*tp));
tp->type = type;
tp->next = tp->prev = tp->head = tp->tail = tp->owner = 0;
tp->vstr = (type < TOK822_MINTOK ? 0 :
tp->vstr = (type < TOK822_MINTOK || CONTAINER_TOKEN(type) ? 0 :
strval == 0 ? vstring_alloc(10) :
vstring_strcpy(vstring_alloc(strlen(strval) + 1), strval));
return (tp);

View File

@ -191,8 +191,13 @@ VSTRING *tok822_internalize(VSTRING *vp, TOK822 *tree, int flags)
case TOK822_ADDR:
tok822_internalize(vp, tp->head, TOK822_STR_NONE);
break;
case TOK822_ATOM:
case TOK822_COMMENT:
VSTRING_ADDCH(vp, '(');
tok822_internalize(vp, tp->head, TOK822_STR_NONE);
VSTRING_ADDCH(vp, ')');
break;
case TOK822_ATOM:
case TOK822_COMMTEXT:
case TOK822_QSTRING:
vstring_strcat(vp, vstring_str(tp->vstr));
break;
@ -242,7 +247,12 @@ VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags)
vstring_strcat(vp, vstring_str(tp->vstr));
break;
case TOK822_COMMENT:
tok822_copy_quoted(vp, vstring_str(tp->vstr), "\\\r\n");
VSTRING_ADDCH(vp, '(');
tok822_externalize(vp, tp->head, TOK822_STR_NONE);
VSTRING_ADDCH(vp, ')');
break;
case TOK822_COMMTEXT:
tok822_copy_quoted(vp, vstring_str(tp->vstr), "()\\\r\n");
break;
case TOK822_QSTRING:
VSTRING_ADDCH(vp, '"');
@ -251,7 +261,7 @@ VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags)
break;
case TOK822_DOMLIT:
VSTRING_ADDCH(vp, '[');
tok822_copy_quoted(vp, vstring_str(tp->vstr), "\"\\\r\n");
tok822_copy_quoted(vp, vstring_str(tp->vstr), "\\\r\n");
VSTRING_ADDCH(vp, ']');
break;
case TOK822_STARTGRP:
@ -316,7 +326,6 @@ TOK822 *tok822_scan(const char *str, TOK822 **tailp)
continue;
if (ch == '(') {
tp = tok822_alloc(TOK822_COMMENT, (char *) 0);
VSTRING_ADDCH(tp->vstr, ch);
str = tok822_comment(tp, str);
} else if (ch == '[') {
tp = tok822_alloc(TOK822_DOMLIT, (char *) 0);
@ -332,7 +341,13 @@ TOK822 *tok822_scan(const char *str, TOK822 **tailp)
COLLECT(tp, str, ch, !ISSPACE(ch) && !strchr(tok822_opchar, ch));
tok822_quote_atom(tp);
}
tail = (head == 0 ? head = tp : tok822_append(tail, tp));
if (head == 0) {
head = tail = tp;
while (tail->next)
tail = tail->next;
} else {
tail = tok822_append(tail, tp);
}
}
if (tailp)
*tailp = tail;
@ -451,24 +466,36 @@ static void tok822_quote_atom(TOK822 *tp)
const char *tok822_comment(TOK822 *tp, const char *str)
{
TOK822 *tc = 0;
int ch;
#define COMMENT_TEXT_TOKEN(t) ((t) && (t)->type == TOK822_COMMTEXT)
#define APPEND_NEW_TOKEN(tp, type, strval) \
tok822_sub_append(tp, tok822_alloc(type, strval))
while ((ch = *(unsigned char *) str) != 0) {
VSTRING_ADDCH(tp->vstr, ISSPACE(ch) ? ' ' : ch);
str++;
if (ch == '(') { /* comments can nest! */
str = tok822_comment(tp, str);
if (COMMENT_TEXT_TOKEN(tc))
VSTRING_TERMINATE(tc->vstr);
tc = APPEND_NEW_TOKEN(tp, TOK822_COMMENT, (char *) 0);
str = tok822_comment(tc, str);
} else if (ch == ')') {
break;
} else if (ch == '\\') {
vstring_truncate(tp->vstr, VSTRING_LEN(tp->vstr) - 1);
} else {
if (ch == '\\') {
if ((ch = *(unsigned char *) str) == 0)
break;
VSTRING_ADDCH(tp->vstr, ch);
str++;
}
if (!COMMENT_TEXT_TOKEN(tc))
tc = APPEND_NEW_TOKEN(tp, TOK822_COMMTEXT, (char *) 0);
VSTRING_ADDCH(tc->vstr, ch);
}
VSTRING_TERMINATE(tp->vstr);
}
if (COMMENT_TEXT_TOKEN(tc))
VSTRING_TERMINATE(tc->vstr);
return (str);
}
@ -511,20 +538,30 @@ TOK822 *tok822_scan_addr(const char *addr)
#ifdef TEST
#include <unistd.h>
#include <vstream.h>
#include <vstring_vstream.h>
/* tok822_print - display token */
static void tok822_print(TOK822 *tp, int indent)
static void tok822_print(TOK822 *list, int indent)
{
TOK822 *tp;
for (tp = list; tp; tp = tp->next) {
if (tp->type < TOK822_MINTOK) {
vstream_printf("%*s %s \"%c\"\n", indent, "", "OP", tp->type);
} else if (tp->type == TOK822_ADDR) {
vstream_printf("%*s %s\n", indent, "", "address");
tok822_print(tp->head, indent + 2);
} else if (tp->type == TOK822_COMMENT) {
vstream_printf("%*s %s\n", indent, "", "comment");
tok822_print(tp->head, indent + 2);
} else if (tp->type == TOK822_STARTGRP) {
vstream_printf("%*s %s\n", indent, "", "group \":\"");
} else {
vstream_printf("%*s %s \"%s\"\n", indent, "",
tp->type == TOK822_COMMENT ? "comment" :
tp->type == TOK822_COMMTEXT ? "text" :
tp->type == TOK822_ATOM ? "atom" :
tp->type == TOK822_QSTRING ? "quoted string" :
tp->type == TOK822_DOMLIT ? "domain literal" :
@ -532,27 +569,20 @@ static void tok822_print(TOK822 *tp, int indent)
"unknown\n", vstring_str(tp->vstr));
}
}
}
int main(int unused_argc, char **unused_argv)
{
VSTRING *vp = vstring_alloc(100);
TOK822 *list;
TOK822 *tp;
TOK822 *ap;
int indent = 0;
VSTRING *buf = vstring_alloc(100);
while (vstring_fgets(buf, VSTREAM_IN)) {
while (vstring_fgets_nonl(buf, VSTREAM_IN)) {
if (!isatty(vstream_fileno(VSTREAM_IN)))
vstream_printf(">>>%s<<<\n\n", vstring_str(buf));
list = tok822_parse(vstring_str(buf));
for (tp = list; tp; tp = tp->next) {
tok822_print(tp, indent);
if (tp->type == TOK822_ADDR) {
indent += 2;
for (ap = tp->head; ap; ap = ap->next)
tok822_print(ap, indent);
indent -= 2;
}
}
vstream_printf("Parse tree:\n");
tok822_print(list, 0);
vstream_printf("\n");
vstream_printf("Internalized:\n%s\n\n",

View File

@ -0,0 +1,13 @@
wietse@porcupine.org
"wietse venema"@porcupine.org
wietse@porcupine.org
wietse @ porcupine.org
"wietse venema"@porcupine.org ("wietse ) venema")
"wietse venema" <wietse@porcupine.org>
"wietse venema"@porcupine.org ( ("wietse ) venema") )
"wietse venema"@porcupine.org
wietse\ venema@porcupine.org
"wietse venema
wietse@[stuff
wietse@["stuff]
named group: foo@bar, baz@barf;

View File

@ -0,0 +1,266 @@
>>>wietse@porcupine.org<<<
Parse tree:
address
atom "wietse"
OP "@"
atom "porcupine"
OP "."
atom "org"
Internalized:
wietse@porcupine.org
Externalized, no newlines inserted:
wietse@porcupine.org
Externalized, newlines inserted:
wietse@porcupine.org
>>>"wietse venema"@porcupine.org<<<
Parse tree:
address
quoted string "wietse venema"
OP "@"
atom "porcupine"
OP "."
atom "org"
Internalized:
wietse venema@porcupine.org
Externalized, no newlines inserted:
"wietse venema"@porcupine.org
Externalized, newlines inserted:
"wietse venema"@porcupine.org
>>>wietse@porcupine.org<<<
Parse tree:
address
atom "wietse"
OP "@"
atom "porcupine"
OP "."
atom "org"
Internalized:
wietse@porcupine.org
Externalized, no newlines inserted:
wietse@porcupine.org
Externalized, newlines inserted:
wietse@porcupine.org
>>>wietse @ porcupine.org<<<
Parse tree:
address
atom "wietse"
OP "@"
atom "porcupine"
OP "."
atom "org"
Internalized:
wietse@porcupine.org
Externalized, no newlines inserted:
wietse@porcupine.org
Externalized, newlines inserted:
wietse@porcupine.org
>>>"wietse venema"@porcupine.org ("wietse ) venema")<<<
Parse tree:
address
quoted string "wietse venema"
OP "@"
atom "porcupine"
OP "."
atom "org"
OP ","
address
atom "venema"
comment
text ""wietse "
OP ","
address
quoted string ")"
Internalized:
wietse venema@porcupine.org, venema ("wietse ), )
Externalized, no newlines inserted:
"wietse venema"@porcupine.org, venema ("wietse ), ")"
Externalized, newlines inserted:
"wietse venema"@porcupine.org,
venema ("wietse ),
")"
>>>"wietse venema" <wietse@porcupine.org><<<
Parse tree:
quoted string "wietse venema"
OP "<"
address
atom "wietse"
OP "@"
atom "porcupine"
OP "."
atom "org"
OP ">"
Internalized:
wietse venema <wietse@porcupine.org>
Externalized, no newlines inserted:
"wietse venema" <wietse@porcupine.org>
Externalized, newlines inserted:
"wietse venema" <wietse@porcupine.org>
>>>"wietse venema"@porcupine.org ( ("wietse ) venema") )<<<
Parse tree:
address
quoted string "wietse venema"
OP "@"
atom "porcupine"
OP "."
atom "org"
OP ")"
comment
text " "
comment
text ""wietse "
text " venema""
Internalized:
wietse venema@porcupine.org) ( ("wietse ) venema")
Externalized, no newlines inserted:
"wietse venema"@porcupine.org) ( ("wietse ) venema")
Externalized, newlines inserted:
"wietse venema"@porcupine.org) ( ("wietse ) venema")
>>>"wietse venema"@porcupine.org<<<
Parse tree:
address
quoted string "wietse venema"
OP "@"
atom "porcupine"
OP "."
atom "org"
Internalized:
wietse venema@porcupine.org
Externalized, no newlines inserted:
"wietse venema"@porcupine.org
Externalized, newlines inserted:
"wietse venema"@porcupine.org
>>>wietse\ venema@porcupine.org<<<
Parse tree:
address
quoted string "wietse venema"
OP "@"
atom "porcupine"
OP "."
atom "org"
Internalized:
wietse venema@porcupine.org
Externalized, no newlines inserted:
"wietse venema"@porcupine.org
Externalized, newlines inserted:
"wietse venema"@porcupine.org
>>>"wietse venema<<<
Parse tree:
address
quoted string "wietse venema"
Internalized:
wietse venema
Externalized, no newlines inserted:
"wietse venema"
Externalized, newlines inserted:
"wietse venema"
>>>wietse@[stuff<<<
Parse tree:
address
atom "wietse"
OP "@"
domain literal "stuff"
Internalized:
wietse@[stuff]
Externalized, no newlines inserted:
wietse@[stuff]
Externalized, newlines inserted:
wietse@[stuff]
>>>wietse@["stuff]<<<
Parse tree:
address
atom "wietse"
OP "@"
domain literal ""stuff"
Internalized:
wietse@["stuff]
Externalized, no newlines inserted:
wietse@["stuff]
Externalized, newlines inserted:
wietse@["stuff]
>>>named group: foo@bar, baz@barf;<<<
Parse tree:
atom "named"
atom "group"
group ":"
address
atom "foo"
OP "@"
atom "bar"
OP ","
address
atom "baz"
OP "@"
atom "barf"
OP ";"
Internalized:
named group: foo@bar, baz@barf;
Externalized, no newlines inserted:
named group: foo@bar, baz@barf;
Externalized, newlines inserted:
named group: foo@bar,
baz@barf;

View File

@ -119,6 +119,8 @@ domains with "relay access denied"</a>
<li><a href="#relay_restrict">Restricting what users can send mail to off-site destinations</a>
<li><a href="#backup">Configuring Postfix as backup MX host</a>
</ul>
<a name="remote_delivery"><h3>Remote delivery</h3>
@ -1154,6 +1156,42 @@ host.
<hr>
<a name="backup"><h3>Configuring Postfix as backup MX host</h3></a>
When you are SECONDARY MX for some other domain this is all you need:
<p>
<pre>
DNS:
the.backed-up.domain.name IN MX 100 your.machine.name
/etc/postfix/main.cf:
relay_domains = the.backed-up.domain.name
</pre>
<p>
When you are PRIMARY MX for some other domain you also need:
<p>
<pre>
/etc/postfix/main.cf:
transport_maps = hash:/etc/postfix/transport
/etc/postfix/transport:
the.backed-up.domain.name smtp:[their.mail.host.name]
</pre>
<p>
Specify <B>dbm</b> instead of <b>hash</b> if your system uses
<b>dbm</b> files instead of <b>db</b> files. To find out what map
types Postfix supports, use the command <b>postconf -m</b>.
<hr>
<a name="timeouts"><h3>Mail fails consistently with timeout or lost connection</h3></a>
Every now and then, mail fails with "timed out while sending end

View File

@ -331,6 +331,7 @@ maildir.o: ../include/vstring.h
maildir.o: ../include/make_dirs.h
maildir.o: ../include/set_eugid.h
maildir.o: ../include/get_hostname.h
maildir.o: ../include/sane_fsops.h
maildir.o: ../include/mail_copy.h
maildir.o: ../include/bounce.h
maildir.o: ../include/sent.h

View File

@ -177,6 +177,7 @@ smtp_sasl_glue.o: ../include/msg.h
smtp_sasl_glue.o: ../include/mymalloc.h
smtp_sasl_glue.o: ../include/stringops.h
smtp_sasl_glue.o: ../include/split_at.h
smtp_sasl_glue.o: ../include/name_mask.h
smtp_sasl_glue.o: ../include/mail_params.h
smtp_sasl_glue.o: ../include/string_list.h
smtp_sasl_glue.o: ../include/maps.h
@ -193,6 +194,7 @@ 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/mail_params.h
smtp_sasl_proto.o: smtp.h
smtp_sasl_proto.o: ../include/vstream.h
smtp_sasl_proto.o: ../include/vbuf.h

View File

@ -100,6 +100,20 @@
/* .IP \fBsmtp_sasl_password_maps\fR
/* Lookup tables with per-host \fIname\fR:\fIpassword\fR entries.
/* No entry for a host means no attempt to authenticate.
/* .IP \fBsmtp_sasl_security_options\fR
/* Zero or more of the following.
/* .RS
/* .IP \fBnoplaintext\fR
/* Disallow authentication methods that use plaintext passwords.
/* .IP \fBnoactive\fR
/* Disallow authentication methods that are vulnerable to non-dictionary
/* active attacks.
/* .IP \fBnodictionary\fR
/* Disallow authentication methods that are vulnerable to passive
/* dictionary attack.
/* .IP \fBnoanonymous\fR
/* Disallow anonymous logins.
/* .RE
/* .SH "Resource controls"
/* .ad
/* .fi
@ -218,14 +232,10 @@ char *var_fallback_relay;
char *var_bestmx_transp;
char *var_error_rcpt;
int var_smtp_always_ehlo;
#ifdef USE_SASL_AUTH
char *var_smtp_sasl_pwd_maps;
char *var_smtp_sasl_opts;
char *var_smtp_sasl_passwd;
bool var_smtp_sasl_enable;
#endif
/*
* Global variables. smtp_errno is set by the address lookup routines and by
* the connection management routines.
@ -370,9 +380,8 @@ int main(int argc, char **argv)
VAR_FALLBACK_RELAY, DEF_FALLBACK_RELAY, &var_fallback_relay, 0, 0,
VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
#ifdef USE_SASL_AUTH
VAR_SMTP_SASL_PWD_MAPS, DEF_SMTP_SASL_PWD_MAPS, &var_smtp_sasl_pwd_maps, 0, 0,
#endif
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,
0,
};
static CONFIG_INT_TABLE int_table[] = {
@ -393,9 +402,7 @@ int main(int argc, char **argv)
VAR_IGN_MX_LOOKUP_ERR, DEF_IGN_MX_LOOKUP_ERR, &var_ign_mx_lookup_err,
VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
#ifdef USE_SASL_AUTH
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
#endif
0,
};

View File

@ -91,6 +91,7 @@
#include <mymalloc.h>
#include <stringops.h>
#include <split_at.h>
#include <name_mask.h>
/*
* Global library
@ -107,6 +108,19 @@
#ifdef USE_SASL_AUTH
/*
* Authentication security options.
*/
static NAME_MASK smtp_sasl_sec_mask[] = {
"noplaintext", SASL_SEC_NOPLAINTEXT,
"noactive", SASL_SEC_NOACTIVE,
"nodictionary", SASL_SEC_NODICTIONARY,
"noanonymous", SASL_SEC_NOANONYMOUS,
0,
};
static int smtp_sasl_sec_opts;
/*
* Silly little macros.
*/
@ -142,10 +156,17 @@ static int smtp_sasl_log(void *unused_context, int priority,
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;
if (msg_verbose)
msg_info("smtp_sasl_get_user: %s", state->sasl_username);
msg_info("%s: %s", myname, state->sasl_username);
/*
* Sanity check.
*/
if (state->sasl_passwd == 0)
msg_panic("%s: no username looked up", myname);
*result = state->sasl_username;
if (len)
@ -158,17 +179,20 @@ static int smtp_sasl_get_user(void *context, int unused_id, const char **result,
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;
int len;
if (msg_verbose)
msg_info("smtp_sasl_get_passwd: %s", state->sasl_passwd);
msg_info("%s: %s", myname, state->sasl_passwd);
/*
* Sanity check.
*/
if (!conn || !psecret || id != SASL_CB_PASS)
return (SASL_BADPARAM);
if (state->sasl_passwd == 0)
msg_panic("%s: no password looked up", myname);
/*
* Convert the password into a counted string.
@ -234,18 +258,23 @@ void smtp_sasl_initialize(void)
*/
if (smtp_sasl_passwd_map)
msg_panic("smtp_sasl_initialize: repeated call");
if (*var_smtp_sasl_pwd_maps == 0)
msg_fatal("specify password table via the `%s' configuration parameter",
VAR_SMTP_SASL_PWD_MAPS);
if (*var_smtp_sasl_passwd == 0)
msg_fatal("specify a password table via the `%s' configuration parameter",
VAR_SMTP_SASL_PASSWD);
/*
* Open the per-host password table and initialize the SASL library. Use
* shared locks for reading, just in case someone updates the table.
*/
smtp_sasl_passwd_map = maps_create("smtp_sasl_passwd",
var_smtp_sasl_pwd_maps, DICT_FLAG_LOCK);
var_smtp_sasl_passwd, DICT_FLAG_LOCK);
if (sasl_client_init(callbacks) != SASL_OK)
msg_fatal("SASL library initialization");
/*
* Configuration parameters.
*/
smtp_sasl_sec_opts = name_mask(smtp_sasl_sec_mask, var_smtp_sasl_opts);
}
/* smtp_sasl_connect - per-session client initialization */
@ -291,7 +320,6 @@ void smtp_sasl_start(SMTP_STATE *state)
state->sasl_callbacks, NULL_SECFLAGS,
(sasl_conn_t **) &state->sasl_conn) != SASL_OK)
msg_fatal("per-session SASL client initialization");
smtp_sasl_passwd_lookup(state);
/*
* Per-session security properties. XXX This routine is not sufficiently
@ -301,7 +329,7 @@ void smtp_sasl_start(SMTP_STATE *state)
sec_props.min_ssf = 0;
sec_props.max_ssf = 1; /* don't allow real SASL
* security layer */
sec_props.security_flags = 0;
sec_props.security_flags = smtp_sasl_sec_opts;
sec_props.maxbufsize = 0;
sec_props.property_names = 0;
sec_props.property_values = 0;
@ -384,7 +412,7 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
* 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(state))->code / 100 == 3) {
/*
* Process a server challenge.
@ -395,7 +423,7 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
VSTRING_SPACE(state->sasl_decoded, serverinlen);
if (sasl_decode64(line, serverinlen,
STR(state->sasl_decoded), &enc_length) != SASL_OK) {
vstring_sprintf(why, "unable to decode SASL challenge from %s",
vstring_sprintf(why, "malformed SASL challenge from server %s",
state->session->namaddr);
return (-1);
}
@ -407,8 +435,10 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
STR(state->sasl_decoded), enc_length,
NO_SASL_INTERACTION, &clientout, &clientoutlen);
if (result != SASL_OK && result != SASL_CONTINUE)
msg_warn("%s: smtp SASL authentication step failed",
state->session->namaddr);
msg_warn("SASL authentication failed to server %s: %s",
state->session->namaddr,
sasl_errstring(result, NO_SASL_LANGLIST,
NO_SASL_OUTLANG));
/*
* Send a client response.
@ -434,8 +464,8 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
* We completed the authentication protocol.
*/
if (resp->code / 100 != 2) {
vstring_sprintf(why, "unable to SASL authenticate with %s",
state->session->namaddr);
vstring_sprintf(why, "SASL authentication failed; server %s said: %s",
state->session->namaddr, resp->str);
return (0);
}
return (1);

View File

@ -202,6 +202,7 @@ smtpd_sasl_glue.o: ../include/sys_defs.h
smtpd_sasl_glue.o: ../include/msg.h
smtpd_sasl_glue.o: ../include/mymalloc.h
smtpd_sasl_glue.o: ../include/namadr_list.h
smtpd_sasl_glue.o: ../include/name_mask.h
smtpd_sasl_glue.o: ../include/mail_params.h
smtpd_sasl_glue.o: ../include/smtp_stream.h
smtpd_sasl_glue.o: ../include/vstring.h

View File

@ -64,6 +64,20 @@
/* Enable per-session authentication as per RFC 2554 (SASL).
/* This functionality is available only when explicitly selected
/* at program build time and explicitly enabled at runtime.
/* .IP \fBsmtpd_sasl_security_options\fR
/* Zero or more of the following.
/* .RS
/* .IP \fBnoplaintext\fR
/* Disallow authentication methods that use plaintext passwords.
/* .IP \fBnoactive\fR
/* Disallow authentication methods that are vulnerable to non-dictionary
/* active attacks.
/* .IP \fBnodictionary\fR
/* Disallow authentication methods that are vulnerable to passive
/* dictionary attack.
/* .IP \fBnoanonymous\fR
/* Disallow anonymous logins.
/* .RE
/* .SH Miscellaneous
/* .ad
/* .fi
@ -320,6 +334,7 @@ char *var_local_rcpt_maps;
bool var_allow_untrust_route;
int var_smtpd_junk_cmd_limit;
bool var_smtpd_sasl_enable;
char *var_smtpd_sasl_opts;
/*
* Global state, for stand-alone mode queue file cleanup. When this is
@ -1403,6 +1418,7 @@ int main(int argc, char **argv)
VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, 0, 0,
VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, 0, 0,
VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0,
VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts, 0, 0,
0,
};

View File

@ -768,19 +768,6 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, char *name,
return (SMTPD_CHECK_DUNNO);
}
#ifdef USE_SASL_AUTH
/* permit_sasl_auth - OK for authenticated connection */
static int permit_sasl_auth(SMTPD_STATE *state)
{
if (state->sasl_username)
return (SMTPD_CHECK_OK);
return (SMTPD_CHECK_DUNNO);
}
#endif
/* check_relay_domains - OK/FAIL for message relaying */
static int check_relay_domains(SMTPD_STATE *state, char *recipient,
@ -1680,7 +1667,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
cpp[1], CHECK_RELAY_DOMAINS);
#ifdef USE_SASL_AUTH
} else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) {
status = permit_sasl_auth(state);
status = permit_sasl_auth(state, SMTPD_CHECK_OK, SMTPD_CHECK_DUNNO);
#endif
} else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
if (state->recipient)

View File

@ -90,6 +90,7 @@
#include <msg.h>
#include <mymalloc.h>
#include <namadr_list.h>
#include <name_mask.h>
/* Global library. */
@ -140,6 +141,17 @@ static sasl_callback_t callbacks[] = {
{SASL_CB_LIST_END, 0, 0}
};
static NAME_MASK smtpd_sasl_mask[] = {
"noplaintext", SASL_SEC_NOPLAINTEXT,
"noactive", SASL_SEC_NOACTIVE,
"nodictionary", SASL_SEC_NODICTIONARY,
"noanonymous", SASL_SEC_NOANONYMOUS,
0,
};
static int smtpd_sasl_opts;
/* smtpd_sasl_initialize - per-process initialization */
void smtpd_sasl_initialize(void)
@ -150,6 +162,11 @@ void smtpd_sasl_initialize(void)
*/
if (sasl_server_init(callbacks, "smtpd") != SASL_OK)
msg_fatal("SASL per-process initialization failed");
/*
* Configuration parameters.
*/
smtpd_sasl_opts = name_mask(smtpd_sasl_mask, var_smtpd_sasl_opts);
}
/* smtpd_sasl_connect - per-connection initialization */
@ -195,7 +212,7 @@ void smtpd_sasl_connect(SMTPD_STATE *state)
sec_props.min_ssf = 0;
sec_props.max_ssf = 1; /* don't allow real SASL
* security layer */
sec_props.security_flags = SASL_SEC_NOANONYMOUS;
sec_props.security_flags = smtpd_sasl_opts;
sec_props.maxbufsize = 0;
sec_props.property_names = 0;
sec_props.property_values = 0;

View File

@ -16,6 +16,7 @@ extern void smtpd_sasl_connect(SMTPD_STATE *);
extern void smtpd_sasl_disconnect(SMTPD_STATE *);
extern char *smtpd_sasl_authenticate(SMTPD_STATE *, const char *, const char *);
extern void smtpd_sasl_logout(SMTPD_STATE *);
extern int permit_sasl_auth(SMTPD_STATE *, int, int);
/* LICENSE
/* .ad

View File

@ -24,6 +24,11 @@
/*
/* void smtpd_sasl_mail_reset(state)
/* SMTPD_STATE *state;
/*
/* static int permit_sasl_auth(state, authenticated, unauthenticated)
/* SMTPD_STATE *state;
/* int authenticated;
/* int unauthenticated;
/* DESCRIPTION
/* This module contains random chunks of code that implement
/* the SMTP protocol interface for SASL negotiation. The goal
@ -43,6 +48,9 @@
/* smtpd_sasl_mail_reset() performs cleanup for the SASL-specific
/* AUTH=sender option to the MAIL FROM command.
/*
/* permit_sasl_auth() permits access from an authenticated client.
/* This test fails for clients that use anonymous authentication.
/*
/* Arguments:
/* .IP state
/* SMTP session context.
@ -53,6 +61,10 @@
/* .IP sender
/* Sender address from the AUTH=sender option in the MAIL FROM
/* command.
/* .IP authenticated
/* Result for authenticated client.
/* .IP unauthenticated
/* Result for unauthenticated client.
/* DIAGNOSTICS
/* All errors are fatal.
/* LICENSE
@ -201,4 +213,13 @@ void smtpd_sasl_mail_reset(SMTPD_STATE *state)
}
}
/* permit_sasl_auth - OK for authenticated connection */
int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
{
if (state->sasl_method && strcasecmp(state->sasl_method, "anonymous"))
return (ifyes);
return (ifnot);
}
#endif