From d69f7e550da692e92222d36e1f0815d1ac8ff6ed Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Fri, 21 Apr 2000 00:00:00 +0000 Subject: [PATCH] snapshot-20000421 --- postfix/HISTORY | 6 + postfix/conf/sample-auth.cf | 70 ++++++-- postfix/global/Makefile.in | 11 +- postfix/global/mail_params.h | 19 ++- postfix/global/mail_version.h | 2 +- postfix/global/tok822.h | 3 +- postfix/global/tok822_node.c | 5 +- postfix/global/tok822_parse.c | 110 ++++++++----- postfix/global/tok822_parse.in | 13 ++ postfix/global/tok822_parse.ref | 266 +++++++++++++++++++++++++++++++ postfix/html/faq.html | 38 +++++ postfix/local/Makefile.in | 1 + postfix/smtp/Makefile.in | 2 + postfix/smtp/smtp.c | 29 ++-- postfix/smtp/smtp_sasl_glue.c | 64 ++++++-- postfix/smtpd/Makefile.in | 1 + postfix/smtpd/smtpd.c | 16 ++ postfix/smtpd/smtpd_check.c | 15 +- postfix/smtpd/smtpd_sasl_glue.c | 19 ++- postfix/smtpd/smtpd_sasl_glue.h | 1 + postfix/smtpd/smtpd_sasl_proto.c | 21 +++ 21 files changed, 607 insertions(+), 105 deletions(-) create mode 100644 postfix/global/tok822_parse.in create mode 100644 postfix/global/tok822_parse.ref diff --git a/postfix/HISTORY b/postfix/HISTORY index 5f17ecb36..3c10bba81 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/conf/sample-auth.cf b/postfix/conf/sample-auth.cf index a9b8f7c17..eaf66feec 100644 --- a/postfix/conf/sample-auth.cf +++ b/postfix/conf/sample-auth.cf @@ -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 diff --git a/postfix/global/Makefile.in b/postfix/global/Makefile.in index 0b207fe35..724159e88 100644 --- a/postfix/global/Makefile.in +++ b/postfix/global/Makefile.in @@ -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.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 diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index 130cdd8a7..22b8c6d96 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -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" diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index 4999f7b1c..17ef9f8b6 100644 --- a/postfix/global/mail_version.h +++ b/postfix/global/mail_version.h @@ -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 diff --git a/postfix/global/tok822.h b/postfix/global/tok822.h index 316dfb198..a39f40d82 100644 --- a/postfix/global/tok822.h +++ b/postfix/global/tok822.h @@ -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 diff --git a/postfix/global/tok822_node.c b/postfix/global/tok822_node.c index f0456d03f..797deb342 100644 --- a/postfix/global/tok822_node.c +++ b/postfix/global/tok822_node.c @@ -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); diff --git a/postfix/global/tok822_parse.c b/postfix/global/tok822_parse.c index cd745cf96..69827e846 100644 --- a/postfix/global/tok822_parse.c +++ b/postfix/global/tok822_parse.c @@ -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); - if ((ch = *(unsigned char *) str) == 0) - break; - VSTRING_ADDCH(tp->vstr, ch); - str++; + } else { + if (ch == '\\') { + if ((ch = *(unsigned char *) str) == 0) + break; + 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,25 +538,36 @@ TOK822 *tok822_scan_addr(const char *addr) #ifdef TEST +#include #include #include /* tok822_print - display token */ -static void tok822_print(TOK822 *tp, int indent) +static void tok822_print(TOK822 *list, int indent) { - 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"); - } else { - vstream_printf("%*s %s \"%s\"\n", indent, "", - tp->type == TOK822_COMMENT ? "comment" : - tp->type == TOK822_ATOM ? "atom" : - tp->type == TOK822_QSTRING ? "quoted string" : - tp->type == TOK822_DOMLIT ? "domain literal" : - tp->type == TOK822_ADDR ? "address" : - "unknown\n", vstring_str(tp->vstr)); + 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_COMMTEXT ? "text" : + tp->type == TOK822_ATOM ? "atom" : + tp->type == TOK822_QSTRING ? "quoted string" : + tp->type == TOK822_DOMLIT ? "domain literal" : + tp->type == TOK822_ADDR ? "address" : + "unknown\n", vstring_str(tp->vstr)); + } } } @@ -537,22 +575,14 @@ 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", diff --git a/postfix/global/tok822_parse.in b/postfix/global/tok822_parse.in new file mode 100644 index 000000000..ebc564c75 --- /dev/null +++ b/postfix/global/tok822_parse.in @@ -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 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; diff --git a/postfix/global/tok822_parse.ref b/postfix/global/tok822_parse.ref new file mode 100644 index 000000000..debfc9c3b --- /dev/null +++ b/postfix/global/tok822_parse.ref @@ -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" <<< + +Parse tree: + quoted string "wietse venema" + OP "<" + address + atom "wietse" + OP "@" + atom "porcupine" + OP "." + atom "org" + OP ">" + +Internalized: +wietse venema + +Externalized, no newlines inserted: +"wietse venema" + +Externalized, newlines inserted: +"wietse venema" + +>>>"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; + diff --git a/postfix/html/faq.html b/postfix/html/faq.html index ddd7fad14..acad8c3af 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -119,6 +119,8 @@ domains with "relay access denied"
  • Restricting what users can send mail to off-site destinations +
  • Configuring Postfix as backup MX host +

    Remote delivery

    @@ -1154,6 +1156,42 @@ host.
    +

    Configuring Postfix as backup MX host

    + +When you are SECONDARY MX for some other domain this is all you need: + +

    + +

    +    DNS:
    +        the.backed-up.domain.name        IN      MX 100 your.machine.name
    +
    +    /etc/postfix/main.cf:
    +        relay_domains = the.backed-up.domain.name
    +
    + +

    + +When you are PRIMARY MX for some other domain you also need: + +

    + +

    +    /etc/postfix/main.cf:
    +        transport_maps = hash:/etc/postfix/transport
    +
    +    /etc/postfix/transport:
    +        the.backed-up.domain.name       smtp:[their.mail.host.name]
    +
    + +

    + +Specify dbm instead of hash if your system uses +dbm files instead of db files. To find out what map +types Postfix supports, use the command postconf -m. + +


    +

    Mail fails consistently with timeout or lost connection

    Every now and then, mail fails with "timed out while sending end diff --git a/postfix/local/Makefile.in b/postfix/local/Makefile.in index f367ef9c1..4d9338529 100644 --- a/postfix/local/Makefile.in +++ b/postfix/local/Makefile.in @@ -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 diff --git a/postfix/smtp/Makefile.in b/postfix/smtp/Makefile.in index 4db9cb944..48239ba6b 100644 --- a/postfix/smtp/Makefile.in +++ b/postfix/smtp/Makefile.in @@ -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 diff --git a/postfix/smtp/smtp.c b/postfix/smtp/smtp.c index 00d5ac1f7..27a577d94 100644 --- a/postfix/smtp/smtp.c +++ b/postfix/smtp/smtp.c @@ -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, }; diff --git a/postfix/smtp/smtp_sasl_glue.c b/postfix/smtp/smtp_sasl_glue.c index 105904379..f58410965 100644 --- a/postfix/smtp/smtp_sasl_glue.c +++ b/postfix/smtp/smtp_sasl_glue.c @@ -91,6 +91,7 @@ #include #include #include +#include /* * 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. @@ -207,12 +231,12 @@ int smtp_sasl_passwd_lookup(SMTP_STATE *state) msg_info("%s: host `%s' user `%s' pass `%s'", myname, state->session->host, state->sasl_username, state->sasl_passwd); - return(1); + return (1); } else { if (msg_verbose) msg_info("%s: host `%s' no auth info found", myname, state->session->host); - return(0); + return (0); } } @@ -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; @@ -352,7 +380,7 @@ int smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why) if (result != SASL_OK && result != SASL_CONTINUE) { vstring_sprintf(why, "cannot SASL authenticate to server %s: %s", state->session->namaddr, - sasl_errstring(result, NO_SASL_LANGLIST, + sasl_errstring(result, NO_SASL_LANGLIST, NO_SASL_OUTLANG)); return (-1); } @@ -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); diff --git a/postfix/smtpd/Makefile.in b/postfix/smtpd/Makefile.in index 67b36092c..3f2c7fc9f 100644 --- a/postfix/smtpd/Makefile.in +++ b/postfix/smtpd/Makefile.in @@ -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 diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index d1f5c2c74..7b3c436e2 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -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, }; diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index 8677106dc..a1d6eaa5b 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -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) diff --git a/postfix/smtpd/smtpd_sasl_glue.c b/postfix/smtpd/smtpd_sasl_glue.c index 5372e5c31..a1ed45b5e 100644 --- a/postfix/smtpd/smtpd_sasl_glue.c +++ b/postfix/smtpd/smtpd_sasl_glue.c @@ -90,6 +90,7 @@ #include #include #include +#include /* 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; diff --git a/postfix/smtpd/smtpd_sasl_glue.h b/postfix/smtpd/smtpd_sasl_glue.h index 89dce7643..9bd793690 100644 --- a/postfix/smtpd/smtpd_sasl_glue.h +++ b/postfix/smtpd/smtpd_sasl_glue.h @@ -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 diff --git a/postfix/smtpd/smtpd_sasl_proto.c b/postfix/smtpd/smtpd_sasl_proto.c index 05febfdb9..5fc374d56 100644 --- a/postfix/smtpd/smtpd_sasl_proto.c +++ b/postfix/smtpd/smtpd_sasl_proto.c @@ -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