diff options
author | 2002-07-10 20:17:22 +0000 | |
---|---|---|
committer | 2002-07-10 20:17:22 +0000 | |
commit | f19c2612a850737b616d503da75f2025087eee75 (patch) | |
tree | 550cf135ce8b0d3fbb9ffafc7a63203cc9684d46 /net-mail/postfix/files | |
parent | make kde-base packages depend on the exact version of kdelibs they're distrib... (diff) | |
download | historical-f19c2612a850737b616d503da75f2025087eee75.tar.gz historical-f19c2612a850737b616d503da75f2025087eee75.tar.bz2 historical-f19c2612a850737b616d503da75f2025087eee75.zip |
added initial support for cyrus-sasl-2.x in postfix.
Diffstat (limited to 'net-mail/postfix/files')
-rw-r--r-- | net-mail/postfix/files/postfix-1.1.11-saslv2.diff | 764 |
1 files changed, 764 insertions, 0 deletions
diff --git a/net-mail/postfix/files/postfix-1.1.11-saslv2.diff b/net-mail/postfix/files/postfix-1.1.11-saslv2.diff new file mode 100644 index 000000000000..e8caa5c4e73e --- /dev/null +++ b/net-mail/postfix/files/postfix-1.1.11-saslv2.diff @@ -0,0 +1,764 @@ +diff -Naur postfix-1.1.11/conf/sample-auth.cf postfix-1.1.11-20020602/conf/sample-auth.cf +--- postfix-1.1.11/conf/sample-auth.cf 2001-11-06 16:19:40.000000000 +0100 ++++ postfix-1.1.11-20020602/conf/sample-auth.cf 2002-03-29 22:36:53.000000000 +0100 +@@ -23,7 +23,8 @@ + # + # 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, ++# (SASL version 1) or /usr/lib/sasl2/smtpd.conf (SASL version 2) with ++# as contents, for example, + # + # pwcheck_method: sasldb + # +@@ -51,6 +52,10 @@ + # nodictionary: disallow methods subject to passive (dictionary) attack + # noanonymous: disallow methods that allow anonymous authentication + # ++# An additional option is available in SASL version 2: ++# ++# mutual_auth: only allow methods that provide mutual authentication ++# + # By default, the Postfix SMTP server accepts plaintext passwords but + # not anonymous logins. + # +@@ -104,6 +109,10 @@ + # nodictionary: disallow methods subject to passive (dictionary) attack + # noanonymous: disallow methods that allow anonymous authentication + # ++# An additional option is available in SASL version 2: ++# ++# mutual_auth: only allow methods that provide mutual authentication ++# + # By default, the Postfix SMTP client will not use plaintext passwords. + # + #smtp_sasl_security_options = +diff -Naur postfix-1.1.11/README_FILES/SASL_README postfix-1.1.11-20020602/README_FILES/SASL_README +--- postfix-1.1.11/README_FILES/SASL_README 2002-05-28 23:25:35.000000000 +0200 ++++ postfix-1.1.11-20020602/README_FILES/SASL_README 2002-05-28 23:22:32.000000000 +0200 +@@ -26,13 +26,22 @@ + Note that this seems to be related to the auto_transition switch in + SASL. Note also that the Cyrus SASL documentation says that it is + pointless to enable that if you use "sasldb" for "pwcheck_method". ++Later versions of the SASL 1.5.x series should also work. ++ ++Postfix+SASL 2.1.1 appears to work on Mandrake Linux 8.1 (pwcheck_method ++set to saslauthd or auxprop). Note that the 'auxprop' pwcheck_method ++replaces the 'sasldb' method from SASL 1.5.x. Postfix may need ++write access to /etc/sasldb2 if you use the auto_transition feature, ++or if you use an authentication mechanism such as OTP (one-time ++passwords) that needs to update secrets in the database. + + Introduction + ============ + + The Postfix SASL support (RFC 2554) was originally implemented by + Till Franke of SuSE Rhein/Main AG. The present code is a trimmed-down +-version with only the bare necessities. ++version with only the bare necessities. Support for SASL version 2 ++was contributed by Jason Hoos. + + When receiving mail, Postfix logs the client-provided username, + authentication method, and sender address to the maillog file, and +@@ -50,21 +59,20 @@ + Building the SASL library + ========================= + +-Postfix appears to work with cyrus-sasl-1.5.5, which is available +-from: ++Postfix appears to work with cyrus-sasl-1.5.5 or cyrus-sasl-2.1.1, ++which are available from: + + ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/ + +-IMPORTANT: if you install the Cyrus SASL libraries as per the default, +-you will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl. ++IMPORTANT: if you install the Cyrus SASL libraries as per the ++default, you will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl ++for version 1.5.5 or /usr/lib/sasl2 -> /usr/local/lib/sasl2 for ++version 2.1.1. + + Reportedly, Microsoft Internet Explorer version 5 requires the + non-standard SASL LOGIN authentication method. To enable this + authentication method, specify ``./configure --enable-login''. + +-If you install the Cyrus SASL libraries as per the default, you +-will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl. +- + Building Postfix with SASL authentication support + ================================================= + +@@ -74,17 +82,29 @@ + + On some systems this generates the necessary Makefile definitions: + ++(for SASL version 1.5.5): + % make tidy # if you have left-over files from a previous build + % make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include" \ + AUXLIBS="-L/usr/local/lib -lsasl" + ++(for SASL version 2.1.1): ++ % make tidy # if you have left-over files from a previous build ++ % make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include/sasl" \ ++ AUXLIBS="-L/usr/local/lib -lsasl2" ++ + On Solaris 2.x you need to specify run-time link information, + otherwise ld.so will not find the SASL shared library: + ++(for SASL version 1.5.5): + % make tidy # if you have left-over files from a previous build + % make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include" \ + AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lsasl" + ++(for SASL version 2.1.1): ++ % make tidy # if you have left-over files from a previous build ++ % make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include/sasl" \ ++ AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lsasl2" ++ + Enabling SASL authentication in the Postfix SMTP server + ======================================================= + +@@ -101,23 +121,49 @@ + smtpd_recipient_restrictions = + permit_mynetworks permit_sasl_authenticated ... + +-In /usr/local/lib/sasl/smtpd.conf you need to specify how the server +-should validate client passwords. ++In /usr/local/lib/sasl/smtpd.conf (SASL version 1.5.5) or ++/usr/local/lib/sasl2/smtpd.conf (SASL version 2.1.1) you need to ++specify how the server should validate client passwords. + + In order to authenticate against the UNIX password database, try: + ++(SASL version 1.5.5) + /usr/local/lib/sasl/smtpd.conf: + pwcheck_method: pwcheck + ++(SASL version 2.1.1) ++ /usr/local/lib/sasl2/smtpd.conf: ++ pwcheck_method: pwcheck ++ + The pwcheck daemon is contained in the cyrus-sasl source tarball. + ++Alternately, in SASL 1.5.27 and later (including 2.1.1), try: ++ ++(SASL version 1.5.5) ++ /usr/local/lib/sasl/smtpd.conf: ++ pwcheck_method: saslauthd ++ ++(SASL version 2.1.1) ++ /usr/local/lib/sasl2/smtpd.conf: ++ pwcheck_method: saslauthd ++ ++The saslauthd daemon is also contained in the cyrus-sasl source ++tarball. It is more flexible than the pwcheck daemon, in that it ++can authenticate against PAM and various other sources. ++ + In order to authenticate against SASL's own password database: + ++(SASL version 1.5.5) + /usr/local/lib/sasl/smtpd.conf: + pwcheck_method: sasldb + +-This will use the SASL password file (default: /etc/sasldb), which +-is maintained with the saslpasswd command (part of the Cyrus SASL ++(SASL version 2.1.1) ++ /usr/local/lib/sasl2/smtpd.conf: ++ pwcheck_method: auxprop ++ ++This will use the SASL password file (default: /etc/sasldb in ++version 1.5.5, or /etc/sasldb2 in version 2.1.1), which is maintained ++with the saslpasswd or saslpasswd2 command (part of the Cyrus SASL + software). On some poorly-supported systems the saslpasswd command + needs to be run multiple times before it stops complaining. The + Postfix SMTP server needs read access to the sasldb file - you may +diff -Naur postfix-1.1.11/src/lmtp/lmtp_sasl_glue.c postfix-1.1.11-20020602/src/lmtp/lmtp_sasl_glue.c +--- postfix-1.1.11/src/lmtp/lmtp_sasl_glue.c 2001-01-19 22:46:44.000000000 +0100 ++++ postfix-1.1.11-20020602/src/lmtp/lmtp_sasl_glue.c 2002-03-29 23:24:17.000000000 +0100 +@@ -116,6 +116,9 @@ + "noactive", SASL_SEC_NOACTIVE, + "nodictionary", SASL_SEC_NODICTIONARY, + "noanonymous", SASL_SEC_NOANONYMOUS, ++#if SASL_VERSION_MAJOR >= 2 ++ "mutual_auth", SASL_SEC_MUTUAL_AUTH, ++#endif + 0, + }; + +@@ -127,6 +130,47 @@ + #define STR(x) vstring_str(x) + + /* ++ * Macros to handle API differences between SASLv1 and SASLv2. Specifics: ++ * ++ * The SASL_LOG_* constants were renamed in SASLv2. ++ * ++ * SASLv2's sasl_client_new takes two new parameters to specify local and ++ * remote IP addresses for auth mechs that use them. ++ * ++ * SASLv2's sasl_client_start function no longer takes the secret parameter. ++ * ++ * SASLv2's sasl_decode64 function takes an extra parameter for the length of ++ * the output buffer. ++ * ++ * The other major change is that SASLv2 now takes more responsibility for ++ * deallocating memory that it allocates internally. Thus, some of the ++ * function parameters are now 'const', to make sure we don't try to free ++ * them too. This is dealt with in the code later on. ++ */ ++ ++#if SASL_VERSION_MAJOR < 2 ++/* SASL version 1.x */ ++#define SASL_LOG_WARN SASL_LOG_WARNING ++#define SASL_LOG_NOTE SASL_LOG_INFO ++#define SASL_CLIENT_NEW(srv, fqdn, lport, rport, prompt, secflags, pconn) \ ++ sasl_client_new(srv, fqdn, prompt, secflags, pconn) ++#define SASL_CLIENT_START(conn, mechlst, secret, prompt, clout, cllen, mech) \ ++ sasl_client_start(conn, mechlst, secret, prompt, clout, cllen, mech) ++#define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \ ++ sasl_decode64(in, inlen, out, outlen) ++#endif ++ ++#if SASL_VERSION_MAJOR >= 2 ++/* SASL version > 2.x */ ++#define SASL_CLIENT_NEW(srv, fqdn, lport, rport, prompt, secflags, pconn) \ ++ sasl_client_new(srv, fqdn, lport, rport, prompt, secflags, pconn) ++#define SASL_CLIENT_START(conn, mechlst, secret, prompt, clout, cllen, mech) \ ++ sasl_client_start(conn, mechlst, prompt, clout, cllen, mech) ++#define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \ ++ sasl_decode64(in, inlen, out, outmaxlen, outlen) ++#endif ++ ++ /* + * Per-host login/password information. + */ + static MAPS *lmtp_sasl_passwd_map; +@@ -137,14 +181,18 @@ + const char *message) + { + switch (priority) { +- case SASL_LOG_ERR: +- case SASL_LOG_WARNING: +- msg_warn("%s", message); ++ case SASL_LOG_ERR: /* unusual errors */ ++ case SASL_LOG_WARN: /* non-fatal warnings */ ++ msg_warn("SASL authentication problem: %s", message); + break; +- case SASL_LOG_INFO: ++ case SASL_LOG_NOTE: /* other info */ + if (msg_verbose) +- msg_info("%s", message); ++ msg_info("SASL authentication info: %s", message); + break; ++#if SASL_VERSION_MAJOR >= 2 ++ case SASL_LOG_FAIL: /* authentication failures */ ++ msg_warn("SASL authentication failure: %s", message); ++#endif + } + return (SASL_OK); + } +@@ -317,7 +365,12 @@ + memcpy((char *) state->sasl_callbacks, callbacks, sizeof(callbacks)); + for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++) + cp->context = (void *) state; +- if (sasl_client_new("smtp", state->session->host, ++ ++#define NULL_SERVER_ADDR ((char *) 0) ++#define NULL_CLIENT_ADDR ((char *) 0) ++ ++ if (SASL_CLIENT_NEW("smtp", state->session->host, ++ NULL_CLIENT_ADDR, NULL_SERVER_ADDR, + state->sasl_callbacks, NULL_SECFLAGS, + (sasl_conn_t **) &state->sasl_conn) != SASL_OK) + msg_fatal("per-session SASL client initialization"); +@@ -354,7 +407,14 @@ + char *myname = "lmtp_sasl_authenticate"; + unsigned enc_length; + unsigned enc_length_out; ++ ++#if SASL_VERSION_MAJOR >= 2 ++ const char *clientout; ++ ++#else + char *clientout; ++ ++#endif + unsigned clientoutlen; + unsigned serverinlen; + LMTP_RESP *resp; +@@ -374,7 +434,7 @@ + /* + * Start the client side authentication protocol. + */ +- result = sasl_client_start((sasl_conn_t *) state->sasl_conn, ++ result = SASL_CLIENT_START((sasl_conn_t *) state->sasl_conn, + state->sasl_mechanism_list, + NO_SASL_SECRET, NO_SASL_INTERACTION, + &clientout, &clientoutlen, &mechanism); +@@ -404,7 +464,10 @@ + STR(state->sasl_encoded), enc_length, + &enc_length_out) != SASL_OK) + msg_panic("%s: sasl_encode64 botch", myname); ++#if SASL_VERSION_MAJOR < 2 ++ /* SASL version 1 doesn't free memory that it allocates. */ + free(clientout); ++#endif + lmtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded)); + } else { + lmtp_chat_cmd(state, "AUTH %s", mechanism); +@@ -423,8 +486,8 @@ + (void) mystrtok(&line, "- \t\n"); /* skip over result code */ + serverinlen = strlen(line); + VSTRING_SPACE(state->sasl_decoded, serverinlen); +- if (sasl_decode64(line, serverinlen, +- STR(state->sasl_decoded), &enc_length) != SASL_OK) { ++ if (SASL_DECODE64(line, serverinlen, STR(state->sasl_decoded), ++ serverinlen, &enc_length) != SASL_OK) { + vstring_sprintf(why, "malformed SASL challenge from server %s", + state->session->namaddr); + return (-1); +@@ -456,7 +519,10 @@ + STR(state->sasl_encoded), enc_length, + &enc_length_out) != SASL_OK) + msg_panic("%s: sasl_encode64 botch", myname); ++#if SASL_VERSION_MAJOR < 2 ++ /* SASL version 1 doesn't free memory that it allocates. */ + free(clientout); ++#endif + } else { + vstring_strcat(state->sasl_encoded, ""); + } +@@ -487,7 +553,8 @@ + state->sasl_passwd = 0; + } + if (state->sasl_mechanism_list) { +- myfree(state->sasl_mechanism_list); /* allocated in lmtp_helo */ ++ /* allocated in lmtp_sasl_helo_auth */ ++ myfree(state->sasl_mechanism_list); + state->sasl_mechanism_list = 0; + } + if (state->sasl_conn) { +diff -Naur postfix-1.1.11/src/smtp/smtp_sasl_glue.c postfix-1.1.11-20020602/src/smtp/smtp_sasl_glue.c +--- postfix-1.1.11/src/smtp/smtp_sasl_glue.c 2001-07-02 21:12:54.000000000 +0200 ++++ postfix-1.1.11-20020602/src/smtp/smtp_sasl_glue.c 2002-03-29 23:24:22.000000000 +0100 +@@ -116,6 +116,9 @@ + "noactive", SASL_SEC_NOACTIVE, + "nodictionary", SASL_SEC_NODICTIONARY, + "noanonymous", SASL_SEC_NOANONYMOUS, ++#if SASL_VERSION_MAJOR >= 2 ++ "mutual_auth", SASL_SEC_MUTUAL_AUTH, ++#endif + 0, + }; + +@@ -127,6 +130,47 @@ + #define STR(x) vstring_str(x) + + /* ++ * Macros to handle API differences between SASLv1 and SASLv2. Specifics: ++ * ++ * The SASL_LOG_* constants were renamed in SASLv2. ++ * ++ * SASLv2's sasl_client_new takes two new parameters to specify local and ++ * remote IP addresses for auth mechs that use them. ++ * ++ * SASLv2's sasl_client_start function no longer takes the secret parameter. ++ * ++ * SASLv2's sasl_decode64 function takes an extra parameter for the length of ++ * the output buffer. ++ * ++ * The other major change is that SASLv2 now takes more responsibility for ++ * deallocating memory that it allocates internally. Thus, some of the ++ * function parameters are now 'const', to make sure we don't try to free ++ * them too. This is dealt with in the code later on. ++ */ ++ ++#if SASL_VERSION_MAJOR < 2 ++/* SASL version 1.x */ ++#define SASL_LOG_WARN SASL_LOG_WARNING ++#define SASL_LOG_NOTE SASL_LOG_INFO ++#define SASL_CLIENT_NEW(srv, fqdn, lport, rport, prompt, secflags, pconn) \ ++ sasl_client_new(srv, fqdn, prompt, secflags, pconn) ++#define SASL_CLIENT_START(conn, mechlst, secret, prompt, clout, cllen, mech) \ ++ sasl_client_start(conn, mechlst, secret, prompt, clout, cllen, mech) ++#define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \ ++ sasl_decode64(in, inlen, out, outlen) ++#endif ++ ++#if SASL_VERSION_MAJOR >= 2 ++/* SASL version > 2.x */ ++#define SASL_CLIENT_NEW(srv, fqdn, lport, rport, prompt, secflags, pconn) \ ++ sasl_client_new(srv, fqdn, lport, rport, prompt, secflags, pconn) ++#define SASL_CLIENT_START(conn, mechlst, secret, prompt, clout, cllen, mech) \ ++ sasl_client_start(conn, mechlst, prompt, clout, cllen, mech) ++#define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \ ++ sasl_decode64(in, inlen, out, outmaxlen, outlen) ++#endif ++ ++ /* + * Per-host login/password information. + */ + static MAPS *smtp_sasl_passwd_map; +@@ -137,14 +181,18 @@ + const char *message) + { + switch (priority) { +- case SASL_LOG_ERR: +- case SASL_LOG_WARNING: ++ case SASL_LOG_ERR: /* unusual errors */ ++ case SASL_LOG_WARN: /* non-fatal warnings */ + msg_warn("SASL authentication problem: %s", message); + break; +- case SASL_LOG_INFO: ++ case SASL_LOG_NOTE: /* other info */ + if (msg_verbose) + msg_info("SASL authentication info: %s", message); + break; ++#if SASL_VERSION_MAJOR >= 2 ++ case SASL_LOG_FAIL: /* authentication failures */ ++ msg_warn("SASL authentication failure: %s", message); ++#endif + } + return (SASL_OK); + } +@@ -317,7 +365,12 @@ + memcpy((char *) state->sasl_callbacks, callbacks, sizeof(callbacks)); + for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++) + cp->context = (void *) state; +- if (sasl_client_new("smtp", state->session->host, ++ ++#define NULL_SERVER_ADDR ((char *) 0) ++#define NULL_CLIENT_ADDR ((char *) 0) ++ ++ if (SASL_CLIENT_NEW("smtp", state->session->host, ++ NULL_CLIENT_ADDR, NULL_SERVER_ADDR, + state->sasl_callbacks, NULL_SECFLAGS, + (sasl_conn_t **) &state->sasl_conn) != SASL_OK) + msg_fatal("per-session SASL client initialization"); +@@ -354,7 +407,14 @@ + char *myname = "smtp_sasl_authenticate"; + unsigned enc_length; + unsigned enc_length_out; ++ ++#if SASL_VERSION_MAJOR >= 2 ++ const char *clientout; ++ ++#else + char *clientout; ++ ++#endif + unsigned clientoutlen; + unsigned serverinlen; + SMTP_RESP *resp; +@@ -374,7 +434,7 @@ + /* + * Start the client side authentication protocol. + */ +- result = sasl_client_start((sasl_conn_t *) state->sasl_conn, ++ result = SASL_CLIENT_START((sasl_conn_t *) state->sasl_conn, + state->sasl_mechanism_list, + NO_SASL_SECRET, NO_SASL_INTERACTION, + &clientout, &clientoutlen, &mechanism); +@@ -404,7 +464,10 @@ + STR(state->sasl_encoded), enc_length, + &enc_length_out) != SASL_OK) + msg_panic("%s: sasl_encode64 botch", myname); ++#if SASL_VERSION_MAJOR < 2 ++ /* SASL version 1 doesn't free memory that it allocates. */ + free(clientout); ++#endif + smtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded)); + } else { + smtp_chat_cmd(state, "AUTH %s", mechanism); +@@ -423,8 +486,8 @@ + (void) mystrtok(&line, "- \t\n"); /* skip over result code */ + serverinlen = strlen(line); + VSTRING_SPACE(state->sasl_decoded, serverinlen); +- if (sasl_decode64(line, serverinlen, +- STR(state->sasl_decoded), &enc_length) != SASL_OK) { ++ if (SASL_DECODE64(line, serverinlen, STR(state->sasl_decoded), ++ serverinlen, &enc_length) != SASL_OK) { + vstring_sprintf(why, "malformed SASL challenge from server %s", + state->session->namaddr); + return (-1); +@@ -456,7 +519,10 @@ + STR(state->sasl_encoded), enc_length, + &enc_length_out) != SASL_OK) + msg_panic("%s: sasl_encode64 botch", myname); ++#if SASL_VERSION_MAJOR < 2 ++ /* SASL version 1 doesn't free memory that it allocates. */ + free(clientout); ++#endif + } else { + vstring_strcat(state->sasl_encoded, ""); + } +@@ -487,7 +553,8 @@ + state->sasl_passwd = 0; + } + if (state->sasl_mechanism_list) { +- myfree(state->sasl_mechanism_list); /* allocated in smtp_helo */ ++ /* allocated in smtp_sasl_helo_auth */ ++ myfree(state->sasl_mechanism_list); + state->sasl_mechanism_list = 0; + } + if (state->sasl_conn) { +diff -Naur postfix-1.1.11/src/smtpd/smtpd.h postfix-1.1.11-20020602/src/smtpd/smtpd.h +--- postfix-1.1.11/src/smtpd/smtpd.h 2001-11-06 18:35:29.000000000 +0100 ++++ postfix-1.1.11-20020602/src/smtpd/smtpd.h 2002-03-29 22:10:13.000000000 +0100 +@@ -68,7 +68,11 @@ + off_t msg_size; + int junk_cmds; + #ifdef USE_SASL_AUTH ++#if SASL_VERSION_MAJOR >= 2 ++ const char *sasl_mechanism_list; ++#else + char *sasl_mechanism_list; ++#endif + char *sasl_method; + char *sasl_username; + char *sasl_sender; +diff -Naur postfix-1.1.11/src/smtpd/smtpd_sasl_glue.c postfix-1.1.11-20020602/src/smtpd/smtpd_sasl_glue.c +--- postfix-1.1.11/src/smtpd/smtpd_sasl_glue.c 2001-11-26 01:14:01.000000000 +0100 ++++ postfix-1.1.11-20020602/src/smtpd/smtpd_sasl_glue.c 2002-03-31 01:04:21.000000000 +0100 +@@ -110,6 +110,52 @@ + */ + #define STR(s) vstring_str(s) + ++ /* ++ * Macros to handle API differences between SASLv1 and SASLv2. Specifics: ++ * ++ * The SASL_LOG_* constants were renamed in SASLv2. ++ * ++ * SASLv2's sasl_server_new takes two new parameters to specify local and ++ * remote IP addresses for auth mechs that use them. ++ * ++ * SASLv2's sasl_server_start and sasl_server_step no longer have the errstr ++ * parameter. ++ * ++ * SASLv2's sasl_decode64 function takes an extra parameter for the length of ++ * the output buffer. ++ * ++ * The other major change is that SASLv2 now takes more responsibility for ++ * deallocating memory that it allocates internally. Thus, some of the ++ * function parameters are now 'const', to make sure we don't try to free ++ * them too. This is dealt with in the code later on. ++ */ ++ ++#if SASL_VERSION_MAJOR < 2 ++/* SASL version 1.x */ ++#define SASL_LOG_WARN SASL_LOG_WARNING ++#define SASL_LOG_NOTE SASL_LOG_INFO ++#define SASL_SERVER_NEW(srv, fqdn, rlm, lport, rport, cb, secflags, pconn) \ ++ sasl_server_new(srv, fqdn, rlm, cb, secflags, pconn) ++#define SASL_SERVER_START(conn, mech, clin, clinlen, srvout, srvoutlen, err) \ ++ sasl_server_start(conn, mech, clin, clinlen, srvout, srvoutlen, err) ++#define SASL_SERVER_STEP(conn, clin, clinlen, srvout, srvoutlen, err) \ ++ sasl_server_step(conn, clin, clinlen, srvout, srvoutlen, err) ++#define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \ ++ sasl_decode64(in, inlen, out, outlen) ++#endif ++ ++#if SASL_VERSION_MAJOR >= 2 ++/* SASL version > 2.x */ ++#define SASL_SERVER_NEW(srv, fqdn, rlm, lport, rport, cb, secflags, pconn) \ ++ sasl_server_new(srv, fqdn, rlm, lport, rport, cb, secflags, pconn) ++#define SASL_SERVER_START(conn, mech, clin, clinlen, srvout, srvoutlen, err) \ ++ sasl_server_start(conn, mech, clin, clinlen, srvout, srvoutlen) ++#define SASL_SERVER_STEP(conn, clin, clinlen, srvout, srvoutlen, err) \ ++ sasl_server_step(conn, clin, clinlen, srvout, srvoutlen) ++#define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \ ++ sasl_decode64(in, inlen, out, outmaxlen, outlen) ++#endif ++ + /* smtpd_sasl_log - SASL logging callback */ + + static int smtpd_sasl_log(void *unused_context, int priority, +@@ -117,13 +163,18 @@ + { + switch (priority) { + case SASL_LOG_ERR: +- case SASL_LOG_WARNING: ++ case SASL_LOG_WARN: + msg_warn("SASL authentication problem: %s", message); + break; +- case SASL_LOG_INFO: ++ case SASL_LOG_NOTE: + if (msg_verbose) + msg_info("SASL authentication info: %s", message); + break; ++#if SASL_VERSION_MAJOR >= 2 ++ case SASL_LOG_FAIL: ++ msg_warn("SASL authentication failure: %s", message); ++ break; ++#endif + } + return SASL_OK; + } +@@ -144,12 +195,14 @@ + "noactive", SASL_SEC_NOACTIVE, + "nodictionary", SASL_SEC_NODICTIONARY, + "noanonymous", SASL_SEC_NOANONYMOUS, ++#if SASL_VERSION_MAJOR >= 2 ++ "mutual_auth", SASL_SEC_MUTUAL_AUTH, ++#endif + 0, + }; + + static int smtpd_sasl_opts; + +- + /* smtpd_sasl_initialize - per-process initialization */ + + void smtpd_sasl_initialize(void) +@@ -172,8 +225,16 @@ + + void smtpd_sasl_connect(SMTPD_STATE *state) + { ++#if SASL_VERSION_MAJOR < 2 + unsigned sasl_mechanism_count; ++ ++#else ++ int sasl_mechanism_count; ++ ++#endif + sasl_security_properties_t sec_props; ++ char *server_address; ++ char *client_address; + + /* + * Initialize SASL-specific state variables. Use long-lived storage for +@@ -195,7 +256,25 @@ + #define NO_SECURITY_LAYERS (0) + #define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0) + +- if (sasl_server_new("smtp", var_myhostname, var_smtpd_sasl_realm, ++#if SASL_VERSION_MAJOR >= 2 && defined(USE_SASL_IP_AUTH) ++ ++ /* ++ * Get IP addresses of local and remote endpoints for SASL. ++ */ ++#error "USE_SASL_IP_AUTH is not implemented" ++ ++#else ++ ++ /* ++ * Don't give any IP address information to SASL. SASLv1 doesn't use it, ++ * and in SASLv2 this will disable any mechaniams that do. ++ */ ++ server_address = 0; ++ client_address = 0; ++#endif ++ ++ if (SASL_SERVER_NEW("smtp", var_myhostname, var_smtpd_sasl_realm, ++ server_address, client_address, + NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS, + &state->sasl_conn) != SASL_OK) + msg_fatal("SASL per-connection server initialization"); +@@ -239,7 +318,10 @@ + void smtpd_sasl_disconnect(SMTPD_STATE *state) + { + if (state->sasl_mechanism_list) { ++#if SASL_VERSION_MAJOR < 2 ++ /* SASL version 1 doesn't free memory that it allocates. */ + free(state->sasl_mechanism_list); ++#endif + state->sasl_mechanism_list = 0; + } + if (state->sasl_conn) { +@@ -262,11 +344,22 @@ + unsigned enc_length; + unsigned enc_length_out; + unsigned reply_len; +- char *serverout = 0; + unsigned serveroutlen; + int result; ++ ++#if SASL_VERSION_MAJOR < 2 ++ char *serverout = 0; ++ ++#else ++ const char *serverout = 0; ++ ++#endif ++ ++#if SASL_VERSION_MAJOR < 2 + const char *errstr = 0; + ++#endif ++ + #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3)) + + if (msg_verbose) +@@ -288,8 +381,8 @@ + reply_len = strlen(init_response); + VSTRING_SPACE(state->sasl_decoded, reply_len); + dec_buffer = STR(state->sasl_decoded); +- if (sasl_decode64(init_response, reply_len, +- dec_buffer, &dec_length) != SASL_OK) ++ if (SASL_DECODE64(init_response, reply_len, ++ dec_buffer, reply_len, &dec_length) != SASL_OK) + return ("501 Authentication failed: malformed initial response"); + if (msg_verbose) + msg_info("%s: decoded initial response %s", myname, dec_buffer); +@@ -297,7 +390,7 @@ + dec_buffer = 0; + dec_length = 0; + } +- result = sasl_server_start(state->sasl_conn, sasl_method, dec_buffer, ++ result = SASL_SERVER_START(state->sasl_conn, sasl_method, dec_buffer, + dec_length, &serverout, &serveroutlen, &errstr); + + /* +@@ -327,7 +420,10 @@ + if (sasl_encode64(serverout, serveroutlen, STR(state->sasl_encoded), + enc_length, &enc_length_out) != SASL_OK) + msg_panic("%s: sasl_encode64 botch", myname); ++#if SASL_VERSION_MAJOR < 2 ++ /* SASL version 1 doesn't free memory that it allocates. */ + free(serverout); ++#endif + serverout = 0; + smtpd_chat_reply(state, "334 %s", STR(state->sasl_encoded)); + +@@ -342,21 +438,24 @@ + return ("501 Authentication aborted"); /* XXX */ + reply_len = VSTRING_LEN(state->buffer); + VSTRING_SPACE(state->sasl_decoded, reply_len); +- if (sasl_decode64(vstring_str(state->buffer), reply_len, +- STR(state->sasl_decoded), &dec_length) != SASL_OK) ++ if (SASL_DECODE64(vstring_str(state->buffer), reply_len, ++ STR(state->sasl_decoded), reply_len, ++ &dec_length) != SASL_OK) + return ("501 Error: malformed authentication response"); + if (msg_verbose) + msg_info("%s: decoded response: %.*s", + myname, (int) dec_length, STR(state->sasl_decoded)); +- result = sasl_server_step(state->sasl_conn, STR(state->sasl_decoded), ++ result = SASL_SERVER_STEP(state->sasl_conn, STR(state->sasl_decoded), + dec_length, &serverout, &serveroutlen, &errstr); + } + + /* + * Cleanup. What an awful interface. + */ ++#if SASL_VERSION_MAJOR < 2 + if (serverout) + free(serverout); ++#endif + + /* + * The authentication protocol was completed. +@@ -369,8 +468,13 @@ + * accounting purposes. For the sake of completeness we also record the + * authentication method that was used. XXX Do not free(serverout). + */ ++#if SASL_VERSION_MAJOR >= 2 ++ result = sasl_getprop(state->sasl_conn, SASL_USERNAME, ++ (const void **) &serverout); ++#else + result = sasl_getprop(state->sasl_conn, SASL_USERNAME, + (void **) &serverout); ++#endif + if (result != SASL_OK || serverout == 0) + msg_panic("%s: sasl_getprop SASL_USERNAME botch", myname); + state->sasl_username = mystrdup(serverout); |