From: Wietse Venema Date: Tue, 20 Dec 2005 05:00:00 +0000 (-0500) Subject: postfix-2.3-20051220 X-Git-Tag: v2.3-RC1~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8216a9e46519a412b11b4b62b919a13243da735b;p=thirdparty%2Fpostfix.git postfix-2.3-20051220 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 1dea5debd..785f16784 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -44,6 +44,9 @@ -TCRYPTO_EX_DATA -TCTABLE -TCTABLE_ENTRY +-TXSASL_CYRUS_CLIENT +-TXSASL_CYRUS_ERROR_INFO +-TXSASL_CYRUS_SERVER -TDELIVER_ATTR -TDELIVER_REQUEST -TDELTA_TIME @@ -235,6 +238,12 @@ -TX509 -TX509_NAME -TX509_STORE_CTX +-TXSASL_CLIENT +-TXSASL_CLIENT_IMPL +-TXSASL_CLIENT_IMPL_INFO +-TXSASL_SERVER +-TXSASL_SERVER_IMPL +-TXSASL_SERVER_IMPL_INFO -Tregex_t -Tregmatch_t -Tsasl_conn_t diff --git a/postfix/HISTORY b/postfix/HISTORY index ebce17863..08c78ebbd 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -11549,7 +11549,7 @@ Apologies for any names omitted. logic for address list and fallback relay processing. Still need to simplify deferred recipient handling. -20051210 +20051212 Bugfix: after a failed TLS session, the 20051210 SMTP client code cleanup broke sessions with backup servers, causing the @@ -11559,8 +11559,71 @@ Apologies for any names omitted. was Ralf Hildebrandt, detectives Victor Duchovni and Wietse. File: smtp/smtp_proto.c. +20051213 + + Bugfix: *SQL, proxy and LDAP map types were not defined in + user-land commands such as postqueue. Leandro Santi. File: + postqueue/postqueue.c. + +20051212-14 + + Server-side plug-in interface for SASL authentication. This + uses Cyrus SASL by default, so nothing has changed except + error messages may be more informative. Files: + smtpd/smtpd_sasl_proto.c smtpd/smtpd_sasl_glue.c, + xsasl/xsasl_server.[hc], xsasl/cyrus_server.[hc] + xsasl/cyrus_strerror.c, xsasl/cyrus_log.c, xsasl/cyrus_security.c. + +20051215 + + Portability: IRIX 6.5.28 defines sa_len as a macro, so it + can't be used as a variable identifier. Zach McDanel. Files: + dns/dns_rr_to_sa.c, smtpd/smtpd_peer.c, qmqpd/qmqpd_peer.c. + +20051216 + + Cleanup: removed some scar tissue that was introduced with + server-side SASL plug-in support. Files: smtpd_sasl_proto.c, + smtpd_sasl_glue.c. + + Client-side plug-in interface for SASL authentication. This + uses Cyrus SASL by default, so nothing has changed except + error messages may be more informative. Files: smtp_sasl_glue.c, + xsasl/xsasl_client.[hc], xsasl/cyrus_client.[hc]. + +20051217 + + Bugfix: when a SASL client password is required by a specific + server, defer delivery when no server-announced mechanism + survives the smtp_sasl_mechanism_filter, instead of ignoring + the SASL announcement and trying to deliver the mail over + an unauthenticated connection and risking that mail will + be rejected. File: smtp/smtp_sasl_proto.c, smtp/smtp_proto.c. + + Portability: zero the "struct msg" just in case. Both purify + (Linux) and valgrind (FreeBSD) complain about uninitialized + bits. Files: util/unix_{send,recv}_fd.c. + +20051219 + + Cleanup: generic smtpd_sasl_path, smtp_sasl_path and + lmtp_sasl_path configuration parameters; simplified the + SASL plug-in API, and made initial provisions for SASL + session encryption. Files: xsasl/*.[hc]. + + Feature: "postconf -a" lists the available SASL server + plug-in types, and "postconf -A" does the same for the + client. Files: postconf.c, xsasl_{client,server}.c. + + Feature: new SMTPD policy attributes "encryption_protocol", + "encryption_cypher" and "encryption_keysize", to distinguish + plaintext from encrypted connections. + Open problems: + Reject numeric domains only when strict envelope syntax is + turned on. + "postsuper -r" no longer resets the message arrival time, because pickup(8) no longer overrides queue file time stamp information. This can be a problem when mail "on hold" is diff --git a/postfix/Makefile.in b/postfix/Makefile.in index a5a7ecdd4..9c9c7b38b 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -1,7 +1,7 @@ SHELL = /bin/sh WARN = -Wmissing-prototypes -Wformat OPTS = 'CC=$(CC)' -DIRS = src/util src/global src/dns src/tls src/master src/postfix src/smtpstone \ +DIRS = src/util src/global src/dns src/tls src/xsasl src/master src/postfix src/smtpstone \ src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \ src/trivial-rewrite src/qmgr src/oqmgr src/smtp src/bounce \ src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \ diff --git a/postfix/README_FILES/SASL_README b/postfix/README_FILES/SASL_README index 86e0bfee6..da0e31b7d 100644 --- a/postfix/README_FILES/SASL_README +++ b/postfix/README_FILES/SASL_README @@ -6,9 +6,8 @@ WWAARRNNIINNGG People who go to the trouble of installing Postfix may have the expectation that Postfix is more secure than some other mailers. The Cyrus SASL library is -a lot of code. With SASL authentication enabled in the Postfix SMTP client and -SMTP server, Postfix becomes as secure as other mail systems that use the Cyrus -SASL library. +a lot of code. With this, Postfix becomes as secure as other mail systems that +use the Cyrus SASL library. HHooww PPoossttffiixx uusseess SSAASSLL aauutthheennttiiccaattiioonn iinnffoorrmmaattiioonn @@ -21,14 +20,16 @@ method, and sender address to the maillog file, and optionally grants mail access via the permit_sasl_authenticated UCE restriction. When sending mail, Postfix can look up the server hostname or destination -domain (the address right-hand part) in a table, and if a username/password is -found, it will use that username and password to authenticate to the server. +domain (the address right-hand part) in a Postfix SASL password table, and if a +username/password is found, it will use that username and password to +authenticate to the server. And as of version 2.3, Postfix can be configured to +search its SASL password table by the sender email address. This document covers the following topics: * What SASL versions are supported - * Building the SASL library - * Building Postfix with SASL authentication support + * Building the Cyrus SASL library + * Building Postfix with Cyrus SASL support * Enabling SASL authentication in the Postfix SMTP server * Testing SASL authentication in the Postfix SMTP server * Trouble shooting the SASL internals @@ -37,27 +38,17 @@ This document covers the following topics: WWhhaatt SSAASSLL vveerrssiioonnss aarree ssuuppppoorrtteedd -Postfix+SASL 1.5.5 was seen working on RedHat 6.1 (pwcheck_method set to shadow -or sasldb), Solaris 2.7 (pwcheck_method set to shadow or sasldb), and FreeBSD -3.4 (pwcheck_method set to sasldb). On RedHat 6.1, SASL 1.5.5 insisted on write -access to /etc/sasldb. 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. +This document describes Postfix with Cyrus SASL version 1 and Cyrus SASL +version 2. Postfix version 2.3 introduces has a plug-in mechanism for other +SASL implementations. Support for other implementations is currently not part +of the Postfix distribution and will be described elsewhere. -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. - -BBuuiillddiinngg tthhee SSAASSLL lliibbrraarryy +BBuuiillddiinngg tthhee CCyyrruuss SSAASSLL lliibbrraarryy 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/. + 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 for version 1.5.5 or /usr/ @@ -67,7 +58,7 @@ Reportedly, Microsoft Internet Explorer version 5 requires the non-standard SASL LOGIN authentication method. To enable this authentication method, specify ``./configure --enable-login''. -BBuuiillddiinngg PPoossttffiixx wwiitthh SSAASSLL aauutthheennttiiccaattiioonn ssuuppppoorrtt +BBuuiillddiinngg PPoossttffiixx wwiitthh CCyyrruuss SSAASSLL ssuuppppoorrtt To build Postfix with SASL authentication support, the following assumes that the Cyrus SASL include files are in /usr/local/include, and that the Cyrus SASL @@ -75,32 +66,34 @@ libraries are in /usr/local/lib. On some systems this generates the necessary Makefile definitions: -(for SASL version 1.5.5): +(for Cyrus 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" + % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ + -I/usr/local/include" AUXLIBS="-L/usr/local/lib -lsasl" -(for SASL version 2.1.1): +(for Cyrus 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" + % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ + -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): +(for Cyrus 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" + % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ + -I/usr/local/include" AUXLIBS="-L/usr/local/lib \ + -R/usr/local/lib -lsasl" -(for SASL version 2.1.1): +(for Cyrus 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" + % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ + -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib \ + -R/usr/local/lib -lsasl2" EEnnaabblliinngg SSAASSLL aauutthheennttiiccaattiioonn iinn tthhee PPoossttffiixx SSMMTTPP sseerrvveerr @@ -123,76 +116,101 @@ and later): Note: the SASL login names will be shared with the entire world. -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 /usr/local/lib/sasl/smtpd.conf (Cyrus SASL version 1.5.5) or /usr/local/lib/ +sasl2/smtpd.conf (Cyrus SASL version 2.1.1) you need to specify how the server +should validate client passwords. Note: some Postfix distributions are modified and look for the smtpd.conf file in /etc/postfix. -Note: some Cyrus SASL distributions are modified and look for the smtpd.conf -file in /etc/sasl2. +Note: some Cyrus SASL distributions look for the smtpd.conf file in /etc/sasl2. -In order to authenticate against the UNIX password database, try: + * To authenticate against the UNIX password database, try: -(SASL version 1.5.5) + (Cyrus SASL version 1.5.5) - /usr/local/lib/sasl/smtpd.conf: - pwcheck_method: pwcheck + /usr/local/lib/sasl/smtpd.conf: + pwcheck_method: pwcheck -(SASL version 2.1.1) + (Cyrus SASL version 2.1.1) - /usr/local/lib/sasl2/smtpd.conf: - pwcheck_method: pwcheck + /usr/local/lib/sasl2/smtpd.conf: + pwcheck_method: pwcheck -The name of the file in /usr/local/lib/sasl (SASL version 1.5.5) or /usr/local/ -lib/sasl2 (SASL version 2.1.1) used by the SASL library for configuration can -be set with: + The name of the file in /usr/local/lib/sasl (Cyrus SASL version 1.5.5) or / + usr/local/lib/sasl2 (Cyrus SASL version 2.1.1) used by the SASL library for + configuration can be set with: - /etc/postfix/main.cf: - smtpd_sasl_application_name = smtpd + /etc/postfix/main.cf: + smtpd_sasl_application_name = smtpd + + The pwcheck daemon is contained in the cyrus-sasl source tarball. + + IMPORTANT: postfix processes need to have group read+execute permission for + the /var/pwcheck directory, otherwise authentication attempts will fail. + + * Alternately, in Cyrus SASL 1.5.26 and later (including 2.1.1), try: + + (Cyrus SASL version 1.5.26) + + /usr/local/lib/sasl/smtpd.conf: + pwcheck_method: saslauthd + + (Cyrus SASL version 2.1.1) -The pwcheck daemon is contained in the cyrus-sasl source tarball. + /usr/local/lib/sasl2/smtpd.conf: + pwcheck_method: saslauthd -IMPORTANT: postfix processes need to have group read+execute permission for the -/var/pwcheck directory, otherwise authentication attempts will fail. + 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. To use PAM, start saslauthd with "- + a pam". -Alternately, in SASL 1.5.26 and later (including 2.1.1), try: + * To authenticate against Cyrus SASL's own password database: -(SASL version 1.5.26) + (Cyrus SASL version 1.5.5) - /usr/local/lib/sasl/smtpd.conf: - pwcheck_method: saslauthd + /usr/local/lib/sasl/smtpd.conf: + pwcheck_method: sasldb -(SASL version 2.1.1) + (Cyrus SASL version 2.1.1) - /usr/local/lib/sasl2/smtpd.conf: - pwcheck_method: saslauthd + /usr/local/lib/sasl2/smtpd.conf: + pwcheck_method: auxprop -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. To use PAM, start saslauthd with "-a pam". + This will use the Cyrus 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 have to play games with group + access permissions. With the OTP authentication mechanism, the SMTP server + also needs WRITE access to /etc/sasldb2 or /etc/sasldb (or the back end SQL + database, if used). -In order to authenticate against SASL's own password database: + IMPORTANT: To get sasldb running, make sure that you set the SASL domain + (realm) to a fully qualified domain name. -(SASL version 1.5.5) + EXAMPLE: - /usr/local/lib/sasl/smtpd.conf: - pwcheck_method: sasldb + (Cyrus SASL version 1.5.5) -(SASL version 2.1.1) + % saslpasswd -c -u `postconf -h myhostname` exampleuser - /usr/local/lib/sasl2/smtpd.conf: - pwcheck_method: auxprop + (Cyrus SASL version 2.1.1) -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 have to play games with group access permissions. With the OTP -authentication mechanism, the SMTP server also needs write access to /etc/ -sasldb2 or /etc/sasldb (or the back end SQL database, if used). + % saslpasswd2 -c -u `postconf -h myhostname` exampleuser + + You can find out SASL's idea about the realms of the users in sasldb with + sasldblistusers (Cyrus SASL version 1.5.5) or sasldblistusers2 (Cyrus SASL + version 2.1.1). + + On the Postfix side, you can have only one realm per smtpd instance, and + only the users belonging to that realm would be able to authenticate. The + Postfix variable smtpd_sasl_local_domain controls the realm used by smtpd: + + /etc/postfix/main.cf: + smtpd_sasl_local_domain = $myhostname IMPORTANT: all users must be able to authenticate using ALL authentication mechanisms advertised by Postfix, otherwise the negotiation might end up with @@ -203,42 +221,27 @@ stand a chance to succeed, yet the SASL library would also advertise other mechanisms, such as DIGEST-MD5. This happens because those mechanisms are made available by other plugins, and the SASL library have no way to know that your only valid authentication source is PAM. Thus you might need to limit the list -of mechanisms advertised by Postfix. This is only possible with SASL version -2.1.1 or later: - - /usr/local/lib/sasl2/smtpd.conf: - mech_list: plain login - -For the same reasons you might want to limit the list of plugins used for -authentication. With SASL version 1.5.5 your only choice is to delete the -corresponding libraries from /usr/local/lib/sasl. With SASL version 2.1.1: - - /usr/local/lib/sasl2/smtpd.conf: - pwcheck_method: auxprop - auxprop_plugin: sql - -IMPORTANT: To get sasldb running, make sure that you set the SASL domain -(realm) to a fully qualified domain name. +of mechanisms advertised by Postfix. -EXAMPLE: + * With older Cyrus SASL versions you remove the corresponding library files + from the SASL plug-in directory (and again whenever the system is updated). -(SASL version 1.5.5) + * With Cyrus SASL version 2.1.1 or later: - % saslpasswd -c -u `postconf -h myhostname` exampleuser + /usr/local/lib/sasl2/smtpd.conf: + mech_list: plain login -(SASL version 2.1.1) - - % saslpasswd2 -c -u `postconf -h myhostname` exampleuser +For the same reasons you might want to limit the list of plugins used for +authentication. -You can find out SASL's idea about the realms of the users in sasldb with -sasldblistusers (SASL version 1.5.5) or sasldblistusers2 (SASL version 2.1.1). + * With Cyrus SASL version 1.5.5 your only choice is to delete the + corresponding library files from the SASL plug-in directory. -On the Postfix side, you can have only one realm per smtpd instance, and only -the users belonging to that realm would be able to authenticate. The Postfix -variable smtpd_sasl_local_domain controls the realm used by smtpd: + * With SASL version 2.1.1: - /etc/postfix/main.cf: - smtpd_sasl_local_domain = $myhostname + /usr/local/lib/sasl2/smtpd.conf: + pwcheck_method: auxprop + auxprop_plugin: sql To run software chrooted with SASL support is an interesting exercise. It probably is not worth the trouble. @@ -317,6 +320,20 @@ that is specified with the relayhost parameter or with a transport(5) table. [mail.myisp.net] username:password [mail.myisp.net]:submission username:password +Postfix version 2.3 supports-per-sender SASL password information. To search +the Postfix SASL password by sender before it searches by destination, specify: + + /etc/postfix/main.cf: + smtp_sender_dependent_authentication = yes + smtp_sasl_auth_enable = yes + smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd + + /etc/postfix/sasl_passwd: + user@example.com username:password + bar.com username + [mail.myisp.net] username:password + [mail.myisp.net]:submission username:password + Note: some SMTP servers support PLAIN or LOGIN authentication only. By default, the Postfix SMTP client does not use authentication methods that send plaintext passwords, and defers delivery with the following error message: @@ -324,16 +341,22 @@ passwords, and defers delivery with the following error message: plaintext authentication specify, for example: /etc/postfix/main.cf: - smtp_sasl_security_options = + smtp_sasl_security_options = noanonymous -The SASL client password file is opened before the SMTP server enters the -optional chroot jail, so you can keep the file in /etc/postfix. +The Postfix SASL client password file is opened before the SMTP server enters +the optional chroot jail, so you can keep the file in /etc/postfix. Note: Some SMTP servers support authentication mechanisms that, although available on the client system, may not in practice work or possess the appropriate credentials to authenticate to the server. It is possible via the smtp_sasl_mechanism_filter parameter to further restrict the list of server -mechanisms that the smtp(8) client will take into consideration. +mechanisms that the smtp(8) client will take into consideration: + + /etc/postfix/main.cf: + smtp_sasl_mechanism_filter = !gssapi, !external, static:all + +In the above example, Postfix will decline to use mechanisms that require +special infrastructure such as Kerberos. The Postfix SMTP client is backwards compatible with SMTP servers that use the non-standard "AUTH=method..." syntax in response to the EHLO command; there is @@ -344,9 +367,11 @@ CCrreeddiittss * Postfix SASL support was originally implemented by Till Franke of SuSE Rhein/Main AG. * Wietse trimmed down the code to only the bare necessities. - * Support for SASL version 2 was contributed by Jason Hoos. + * Support for Cyrus SASL version 2 was contributed by Jason Hoos. * Liviu Daia added smtpd_sasl_application_name, split reject_sender_login_mismatch into reject_authenticated_sender_login_mismatch and reject_unauthenticated_sender_login_mismatch, and revised the docs. + * Wietse made another iteration through the code to add plug-in support for + multiple implementations. diff --git a/postfix/README_FILES/SMTPD_POLICY_README b/postfix/README_FILES/SMTPD_POLICY_README index 0a21779cb..2bfbef504 100644 --- a/postfix/README_FILES/SMTPD_POLICY_README +++ b/postfix/README_FILES/SMTPD_POLICY_README @@ -51,13 +51,18 @@ a delegated SMTPD access policy request: client_name=another.domain.tld reverse_client_name=another.domain.tld instance=123.456.7 + PPoossttffiixx vveerrssiioonn 22..22 aanndd llaatteerr:: sasl_method=plain sasl_username=you sasl_sender= + size=12345 ccert_subject=solaris9.porcupine.org ccert_issuer=Wietse Venema ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 - size=12345 + PPoossttffiixx vveerrssiioonn 22..33 aanndd llaatteerr:: + encryption_protocol=TLSv1/SSLv3 + encryption_cipher=DHE-RSA-AES256-SHA + encryption_keysize=256 [empty line] Notes: @@ -93,10 +98,16 @@ Notes: sends the END-OF-DATA command. * The "sasl_*" attributes (Postfix 2.2 and later) specify information about - how the client was authenticated via SASL. + how the client was authenticated via SASL. These attributes are empty in + case of no SASL authentication. * The "ccert_*" attributes (Postfix 2.2 and later) specify information about - how the client was authenticated via TLS. + how the client was authenticated via TLS. These attributes are empty in + case of no certificate authentication. + + * The "encryption_*" attributes (Postfix 2.3 and later) specify information + about how the connection is encrypted. With plaintext connections the + protocol and cypher attributes are empty and the keysize is zero. The following is specific to SMTPD delegated policy requests: diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index c479bb594..df9b5f944 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -17,6 +17,42 @@ Incompatibility with Postfix 2.1 and earlier If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2 before proceeding. +Incompatibility with snapshot 20051220 +====================================== + +The Postfix-with-Cyrus-SASL build procedure has changed. You now +need to specify -DUSE_CYRUS_SASL in addition to -DUSE_SASL_AUTH or +else you end up without any Cyrus SASL support. The error messages +are: + + unsupported SASL server implementation: cyrus + unsupported SASL client implementation: cyrus + +Major changes with snapshot 20051220 +==================================== + +Plug-in support for SASL authentication in the SMTP server and in +the SMTP+LMTP client. With this, Postfix can support multiple SASL +implementations without source code patches. Some distributors may +even make SASL support a run-time linking option, just like they +do with Postfix lookup tables. + +Hints and tips for plug-in developers are in the xsasl/README file. + +For backwards compatibility the default plug-in type is Cyrus SASL, +so everything should behave like it did before. Some error messages +are slightly different, but these are generally improvements. + +The "postconf -a" command shows what plug-in implementations are +available for the SMTP server, and "postconf -A" does the same for +the SMTP+LMTP client. Plug-in implementations are selected with +the smtpd_sasl_type, smtp_sasl_type and lmtp_sasl_type configuration +parameters. + +Other new configuration parameters are smtpd_sasl_path, smtp_sasl_path +and lmtp_sasl_path. These are better left alone; they are introduced +for the convenience of other SASL implementations. + Incompatibility with snapshot 20051208 ====================================== diff --git a/postfix/html/SASL_README.html b/postfix/html/SASL_README.html index 438709dac..4a720afc9 100644 --- a/postfix/html/SASL_README.html +++ b/postfix/html/SASL_README.html @@ -19,10 +19,9 @@

WARNING

-

People who go to the trouble of installing Postfix may have -the expectation that Postfix is more secure than some other mailers. -The Cyrus SASL library is a lot of code. With SASL authentication -enabled in the Postfix SMTP client and SMTP server, Postfix becomes +

People who go to the trouble of installing Postfix may have the +expectation that Postfix is more secure than some other mailers. +The Cyrus SASL library is a lot of code. With this, Postfix becomes as secure as other mail systems that use the Cyrus SASL library.

@@ -38,9 +37,11 @@ optionally grants mail access via the What SASL versions are supported -
  • Building the SASL library +
  • Building the Cyrus SASL library -
  • Building Postfix with SASL authentication +
  • Building Postfix with Cyrus SASL support
  • Enabling SASL authentication in the @@ -70,31 +71,20 @@ Postfix SMTP client
  • What SASL versions are supported

    -

    Postfix+SASL 1.5.5 was seen working on RedHat 6.1 (pwcheck_method -set to shadow or sasldb), Solaris 2.7 (pwcheck_method set to shadow -or sasldb), and FreeBSD 3.4 (pwcheck_method set to sasldb). On -RedHat 6.1, SASL 1.5.5 insisted on write access to /etc/sasldb. -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.

    - -

    Building the SASL library

    +

    This document describes Postfix with Cyrus SASL version 1 and +Cyrus SASL version 2. Postfix version 2.3 introduces has a plug-in +mechanism for other SASL implementations. Support for other +implementations is currently not part of the Postfix distribution +and will be described elsewhere.

    + +

    Building the Cyrus SASL library

    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/.
    +ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/
     
    @@ -107,8 +97,7 @@ version 2.1.1.

    non-standard SASL LOGIN authentication method. To enable this authentication method, specify ``./configure --enable-login''.

    -

    Building Postfix with SASL authentication -support

    +

    Building Postfix with Cyrus SASL support

    To build Postfix with SASL authentication support, the following assumes that the Cyrus SASL include files are in /usr/local/include, @@ -119,20 +108,20 @@ and that the Cyrus SASL libraries are in /usr/local/lib.

    -
    (for SASL version 1.5.5): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include" AUXLIBS="-L/usr/local/lib -lsasl"
     
    -
    (for SASL version 2.1.1): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib -lsasl2"
     
    @@ -142,20 +131,22 @@ otherwise ld.so will not find the SASL shared library:

    -
    (for SASL version 1.5.5): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include" AUXLIBS="-L/usr/local/lib \
    +    -R/usr/local/lib -lsasl"
     
    -
    (for SASL version 2.1.1): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib \
    +    -R/usr/local/lib -lsasl2"
     
    @@ -195,20 +186,22 @@ SMTP server

    Note: the SASL login names will be shared with the entire world.

    -

    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 +

    In /usr/local/lib/sasl/smtpd.conf (Cyrus SASL version 1.5.5) or +/usr/local/lib/sasl2/smtpd.conf (Cyrus SASL version 2.1.1) you need to specify how the server should validate client passwords.

    Note: some Postfix distributions are modified and look for the smtpd.conf file in /etc/postfix.

    -

    Note: some Cyrus SASL distributions are modified and look for -the smtpd.conf file in /etc/sasl2.

    +

    Note: some Cyrus SASL distributions look for the smtpd.conf +file in /etc/sasl2.

    + + + +

    IMPORTANT: all users must be able to authenticate using ALL +authentication mechanisms advertised by Postfix, otherwise the +negotiation might end up with an unsupported mechanism, and +authentication would fail. For example if you configure SASL to +use saslauthd for authentication against PAM (pluggable +authentication modules), only the PLAIN and LOGIN mechanisms are +supported and stand a chance to succeed, yet the SASL library would also +advertise other mechanisms, such as DIGEST-MD5. This happens because +those mechanisms are made available by other plugins, and the SASL +library have no way to know that your only valid authentication source +is PAM. Thus you might need to limit the list of mechanisms advertised +by Postfix.

    + + + +

    For the same reasons you might want to limit the list of plugins +used for authentication.

    + + +

    To run software chrooted with SASL support is an interesting exercise. It probably is not worth the trouble.

    @@ -470,6 +484,25 @@ table.

    +

    Postfix version 2.3 supports-per-sender SASL password +information. To search the Postfix SASL password by sender +before it searches by destination, specify:

    + +
    +
    +/etc/postfix/main.cf:
    +    smtp_sender_dependent_authentication = yes
    +    smtp_sasl_auth_enable = yes
    +    smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
    +
    +/etc/postfix/sasl_passwd:
    +    user@example.com            username:password
    +    bar.com                     username
    +    [mail.myisp.net]            username:password
    +    [mail.myisp.net]:submission username:password
    +
    +
    +

    Note: some SMTP servers support PLAIN or LOGIN authentication only. By default, the Postfix SMTP client does not use authentication methods that send plaintext passwords, and defers delivery with @@ -480,11 +513,11 @@ for example:

     /etc/postfix/main.cf:
    -    smtp_sasl_security_options = 
    +    smtp_sasl_security_options = noanonymous
     
    -

    The SASL client password file is opened before the SMTP server +

    The Postfix SASL client password file is opened before the SMTP server enters the optional chroot jail, so you can keep the file in /etc/postfix.

    @@ -493,7 +526,17 @@ although available on the client system, may not in practice work or possess the appropriate credentials to authenticate to the server. It is possible via the smtp_sasl_mechanism_filter parameter to further restrict the list of server mechanisms that the smtp(8) client will take -into consideration.

    +into consideration:

    + +
    +
    +/etc/postfix/main.cf:
    +    smtp_sasl_mechanism_filter = !gssapi, !external, static:all
    +
    +
    + +

    In the above example, Postfix will decline to use mechanisms +that require special infrastructure such as Kerberos.

    The Postfix SMTP client is backwards compatible with SMTP servers that use the non-standard "AUTH=method..." syntax in response @@ -509,13 +552,16 @@ of SuSE Rhein/Main AG.

  • Wietse trimmed down the code to only the bare necessities. -
  • Support for SASL version 2 was contributed by Jason Hoos. +
  • Support for Cyrus SASL version 2 was contributed by Jason Hoos. -
  • Liviu Daia added smtpd_sasl_application_name, split +
  • Liviu Daia added smtpd_sasl_application_name, split reject_sender_login_mismatch into reject_authenticated_sender_login_mismatch and reject_unauthenticated_sender_login_mismatch, and revised the docs. +
  • Wietse made another iteration through the code to add +plug-in support for multiple implementations. + diff --git a/postfix/html/SMTPD_POLICY_README.html b/postfix/html/SMTPD_POLICY_README.html index a6e075d3e..d495262b1 100644 --- a/postfix/html/SMTPD_POLICY_README.html +++ b/postfix/html/SMTPD_POLICY_README.html @@ -83,13 +83,18 @@ client_address=1.2.3.4 client_name=another.domain.tld reverse_client_name=another.domain.tld instance=123.456.7 +Postfix version 2.2 and later: sasl_method=plain sasl_username=you sasl_sender= +size=12345 ccert_subject=solaris9.porcupine.org ccert_issuer=Wietse Venema ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 -size=12345 +Postfix version 2.3 and later: +encryption_protocol=TLSv1/SSLv3 +encryption_cipher=DHE-RSA-AES256-SHA +encryption_keysize=256 [empty line] @@ -137,12 +142,19 @@ size=12345
  • The "sasl_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via SASL. + These attributes are empty in case of no SASL authentication.

  • The "ccert_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via TLS. + These attributes are empty in case of no certificate authentication.

    +
  • The "encryption_*" attributes (Postfix 2.3 and later) + specify information about how the connection is encrypted. With + plaintext connections the protocol and cypher attributes are + empty and the keysize is zero.

    +

    The following is specific to SMTPD delegated policy requests: diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 0d0de949d..7e4de63d2 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -10,7 +10,9 @@ POSTCONF(1) POSTCONF(1) postconf - Postfix configuration utility SYNOPSIS - postconf [-dhmlnv] [-c config_dir] [parameter ...] + postconf [-dhnv] [-c config_dir] [parameter ...] + + postconf [-aAmlv] [-c config_dir] postconf [-ev] [-c config_dir] [parameter=value ...] @@ -24,74 +26,89 @@ POSTCONF(1) POSTCONF(1) Options: + -a List the available SASL server plug-in types. The + SASL plug-in type is selected with the + smtpd_sasl_type configuration parameter. + + This feature is available with Postfix 2.3 and + later. + + -A List the available SASL client plug-in types. The + SASL plug-in type is selected with the + smtp_sasl_type or lmtp_sasl_type configuration + parameters. + + This feature is available with Postfix 2.3 and + later. + -b [template_file] Display the message text that appears at the begin- - ning of delivery status notification (DSN) mes- - sages, with $name expressions replaced by actual - values. To override the built-in message text, - specify a template file at the end of the command - line, or specify a template file in main.cf with - the bounce_template_file parameter. To force - selection of the built-in message text templates, - specify an empty template file name (in shell lan- + ning of delivery status notification (DSN) mes- + sages, with $name expressions replaced by actual + values. To override the built-in message text, + specify a template file at the end of the command + line, or specify a template file in main.cf with + the bounce_template_file parameter. To force + selection of the built-in message text templates, + specify an empty template file name (in shell lan- guage: ""). - This feature is available with Postfix 2.3 and + This feature is available with Postfix 2.3 and later. -c config_dir - The main.cf configuration file is in the named + The main.cf configuration file is in the named directory instead of the default configuration directory. - -d Print default parameter settings instead of actual + -d Print default parameter settings instead of actual settings. - -e Edit the main.cf configuration file. The file is + -e Edit the main.cf configuration file. The file is copied to a temporary file then renamed into place. - Parameters and values are specified on the command - line. Use quotes in order to protect shell + Parameters and values are specified on the command + line. Use quotes in order to protect shell metacharacters and whitespace. - -h Show parameter values only, not the ``name = '' + -h Show parameter values only, not the ``name = '' label that normally precedes the value. - -l List the names of all supported mailbox locking + -l List the names of all supported mailbox locking methods. Postfix supports the following methods: - flock A kernel-based advisory locking method for - local files only. This locking method is - available on systems with a BSD compatible + flock A kernel-based advisory locking method for + local files only. This locking method is + available on systems with a BSD compatible library. - fcntl A kernel-based advisory locking method for + fcntl A kernel-based advisory locking method for local and remote files. dotlock - An application-level locking method. An - application locks a file named filename by - creating a file named filename.lock. The - application is expected to remove its own - lock file, as well as stale lock files that + An application-level locking method. An + application locks a file named filename by + creating a file named filename.lock. The + application is expected to remove its own + lock file, as well as stale lock files that were left behind after abnormal termination. -m List the names of all supported lookup table types. - In Postfix configuration files, lookup tables are - specified as type:name, where type is one of the - types listed below. The table name syntax depends - on the lookup table type as described in the DATA- + In Postfix configuration files, lookup tables are + specified as type:name, where type is one of the + types listed below. The table name syntax depends + on the lookup table type as described in the DATA- BASE_README document. - btree A sorted, balanced tree structure. This is + btree A sorted, balanced tree structure. This is available on systems with support for Berke- ley DB databases. - cdb A read-optimized structure with no support - for incremental updates. This is available + cdb A read-optimized structure with no support + for incremental updates. This is available on systems with support for CDB databases. - cidr A table that associates values with Class- - less Inter-Domain Routing (CIDR) patterns. + cidr A table that associates values with Class- + less Inter-Domain Routing (CIDR) patterns. This is described in cidr_table(5). dbm An indexed file type based on hashing. This @@ -100,75 +117,75 @@ POSTCONF(1) POSTCONF(1) environ The UNIX process environment array. The - lookup key is the variable name. Originally - implemented for testing, someone may find + lookup key is the variable name. Originally + implemented for testing, someone may find this useful someday. hash An indexed file type based on hashing. This - is available on systems with support for + is available on systems with support for Berkeley DB databases. ldap (read-only) - Perform lookups using the LDAP protocol. + Perform lookups using the LDAP protocol. This is described in ldap_table(5). mysql (read-only) - Perform lookups using the MYSQL protocol. + Perform lookups using the MYSQL protocol. This is described in mysql_table(5). pcre (read-only) A lookup table based on Perl Compatible Reg- - ular Expressions. The file format is + ular Expressions. The file format is described in pcre_table(5). pgsql (read-only) - Perform lookups using the PostgreSQL proto- + Perform lookups using the PostgreSQL proto- col. This is described in pgsql_table(5). proxy (read-only) - A lookup table that is implemented via the - Postfix proxymap(8) service. The table name + A lookup table that is implemented via the + Postfix proxymap(8) service. The table name syntax is type:name. regexp (read-only) A lookup table based on regular expressions. - The file format is described in regexp_ta- + The file format is described in regexp_ta- ble(5). sdbm An indexed file type based on hashing. This - is available on systems with support for + is available on systems with support for SDBM databases. static (read-only) - A table that always returns its name as - lookup result. For example, static:foobar - always returns the string foobar as lookup + A table that always returns its name as + lookup result. For example, static:foobar + always returns the string foobar as lookup result. tcp (read-only) Perform lookups using a simple request-reply - protocol that is described in tcp_table(5). - This feature is not included with Postfix + protocol that is described in tcp_table(5). + This feature is not included with Postfix 2.2. unix (read-only) - A limited way to query the UNIX authentica- + A limited way to query the UNIX authentica- tion database. The following tables are implemented: unix:passwd.byname - The table is the UNIX password data- - base. The key is a login name. The - result is a password file entry in + The table is the UNIX password data- + base. The key is a login name. The + result is a password file entry in passwd(5) format. unix:group.byname The table is the UNIX group database. - The key is a group name. The result - is a group file entry in group(5) + The key is a group name. The result + is a group file entry in group(5) format. - Other table types may exist depending on how Post- + Other table types may exist depending on how Post- fix was built. -n Print parameter settings that are not left at their @@ -177,18 +194,18 @@ POSTCONF(1) POSTCONF(1) -t [template_file] Display the templates for delivery status notifica- - tion (DSN) messages. To override the built-in tem- - plates, specify a template file at the end of the + tion (DSN) messages. To override the built-in tem- + plates, specify a template file at the end of the command line, or specify a template file in main.cf - with the bounce_template_file parameter. To force - selection of the built-in templates, specify an + with the bounce_template_file parameter. To force + selection of the built-in templates, specify an empty template file name (in shell language: ""). - This feature is available with Postfix 2.3 and + This feature is available with Postfix 2.3 and later. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. DIAGNOSTICS @@ -199,18 +216,18 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. bounce_template_file (empty) - Pathname of a configuration file with bounce mes- + Pathname of a configuration file with bounce mes- sage templates. FILES @@ -224,7 +241,7 @@ POSTCONF(1) POSTCONF(1) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 6f314d737..03a5ec6c3 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -2319,7 +2319,7 @@ This feature was removed in Postfix version 2.1.

    Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. With Postfix 2.3 this parameter -is renamed to smtp_fallback_relay.

    +is renamed to smtp_fallback_relay.

    By default, mail is returned to the sender when a destination is @@ -3222,7 +3222,7 @@ concurrency per recipient.

    Lookup tables, indexed by the remote LMTP server address, with case insensitive lists of LHLO keywords (pipelining, starttls, auth, etc.) that the LMTP client will ignore in the LHLO response -from a remote LMTP server. See lmtp_discard_lhlo_keywords for +from a remote LMTP server. See lmtp_discard_lhlo_keywords for details.

    This feature is available in Postfix 2.3 and later.

    @@ -3246,7 +3246,7 @@ from a remote LMTP server.

  • Specify the silent-discard pseudo keyword to prevent this action from being logged.

    -
  • Use the lmtp_discard_lhlo_keyword_address_maps feature to +

  • Use the lmtp_discard_lhlo_keyword_address_maps feature to discard LHLO keywords selectively.

    @@ -3307,7 +3307,7 @@ client, for example:
       /etc/postfix/master.cf:
    -        mylmtp ... lmtp -o lmtp_lhlo_name=foo.bar.com
    +        mylmtp ... lmtp -o lmtp_lhlo_name=foo.bar.com
     

    @@ -3502,16 +3502,30 @@ to the remote host.

    + + +
    lmtp_sasl_path +(default: empty)
    + +

    Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +lmtp_sasl_type. Typically this specifies the name of a +configuration file or rendez-vous point.

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    lmtp_sasl_security_options (default: noplaintext, noanonymous)
    -

    -What authentication mechanisms the Postfix LMTP client is allowed -to use. The list of available authentication mechanisms is system -dependent. -

    +

    SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with lmtp_sasl_type.

    + +

    The following security features are defined for the cyrus +client SASL implementation:

    @@ -3555,6 +3569,18 @@ configuration parameter. See there for details.

    This feature is available in Postfix 2.3 and later.

    +
    + +
    lmtp_sasl_type +(default: cyrus)
    + +

    The SASL plug-in type that the Postfix LMTP client should use +for authentication. The available types are listed with the +"postconf -A" command.

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    lmtp_send_xforward_command @@ -5089,6 +5115,19 @@ This feature is available in Postfix 2.0 and later.

    + + +
    plaintext_session_reject_code +(default: 450)
    + +

    +The numerical Postfix SMTP server response code when a request +is rejected by the reject_plaintext_session restriction. +

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    prepend_delivered_header @@ -6662,7 +6701,7 @@ host, host:port, [host]:port, [address] or [address]:port; the form destinations, Postfix will try them in the specified order.

    To prevent mailer loops between MX hosts and fall-back hosts, -Postfix version 2.3 and later will not use the smtp_fallback_relay +Postfix version 2.3 and later will not use the smtp_fallback_relay feature for destinations that it is MX host for.

    @@ -7036,16 +7075,30 @@ chroot jail, so you can leave the password file in /etc/postfix.

    + + +
    smtp_sasl_path +(default: empty)
    + +

    Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +smtp_sasl_type. Typically this specifies the name of a +configuration file or rendez-vous point.

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    smtp_sasl_security_options (default: noplaintext, noanonymous)
    -

    -What authentication mechanisms the Postfix SMTP client is allowed -to use. The list of available authentication mechanisms is system -dependent. -

    +

    SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with smtp_sasl_type.

    + +

    The following security features are defined for the cyrus +client SASL implementation:

    Specify zero or more of the following: @@ -7095,6 +7148,18 @@ Example: client uses for TLS encrypted SMTP sessions.

    +
    + +
    smtp_sasl_type +(default: cyrus)
    + +

    The SASL plug-in type that the Postfix SMTP client should use +for authentication. The available types are listed with the +"postconf -A" command.

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    smtp_send_xforward_command @@ -8016,6 +8081,16 @@ The multi_recipient response code for rejected requests (default: 550). This feature is available in Postfix 2.1 and later. +
    reject_plaintext_session
    + +
    Reject the request when the connection is not encrypted. This +restriction should not be used before the client has had a chance +to negotiate encryption with the AUTH or STARTTLS commands. +
    +The plaintext_session_reject_code parameter specifies the response +code for rejected requests (default: 450). This feature is available +in Postfix 2.3 and later.
    +
    reject_unauth_pipelining
    Reject the request when the client sends SMTP commands ahead @@ -9086,11 +9161,31 @@ Examples: +
    + +
    smtpd_sasl_path +(default: smtpd)
    + +

    Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +smtpd_sasl_type. Typically this specifies the name of a +configuration file or rendez-vous point.

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    smtpd_sasl_security_options (default: noanonymous)
    +

    SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL server implementation that is selected +with smtpd_sasl_type.

    + +

    The following security features are defined for the cyrus +server SASL implementation:

    +

    Restrict what authentication mechanisms the Postfix SMTP server will offer to the client. The list of available authentication @@ -9158,6 +9253,18 @@ Example: server uses for TLS encrypted SMTP sessions.

    +
    + +
    smtpd_sasl_type +(default: cyrus)
    + +

    The SASL plug-in type that the Postfix SMTP server should use +for authentication. The available types are listed with the +"postconf -a" command.

    + +

    This feature is available in Postfix 2.3 and later.

    + +
    smtpd_sender_login_maps diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index 78f1ca8b3..41d9075d9 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -48,19 +48,25 @@ SMTP(8) SMTP(8) SMTP DESTINATION SYNTAX SMTP destinations have the following form: - domainname, domainname:port + domainname + + domainname:port Look up the mail exchangers for the specified - domain. + domain, and connect to the specified port (default: + smtp). - [hostname], [hostname]:port - Look up the address of the specified host. + [hostname] - [address], [address]:port - Connect to the host at the specified address. An - IPv6 address must be formatted as [ipv6:address]. + [hostname]:port + Look up the address(es) of the specified host, and + connect to the specified port (default: smtp). - In all the above cases, when no port is specified, look up - the port defined as smtp in services(4). + [address] + + [address]:port + Connect to the host at the specified address, and + connect to the specified port (default: smtp). An + IPv6 address must be formatted as [ipv6:address]. LMTP DESTINATION SYNTAX LMTP destinations have the following form: @@ -71,19 +77,24 @@ SMTP(8) SMTP(8) runs chrooted, an absolute pathname is interpreted relative to the Postfix queue directory. - inet:hostname, inet:hostname:port + inet:hostname - inet:[address], inet:[address]:port + inet:hostname:port + + inet:[address] + + inet:[address]:port Connect to the specified TCP port on the specified local or remote host. If no port is specified, con- nect to the port defined as lmtp in services(4). If no such service is found, the lmtp_tcp_port con- figuration parameter (default value of 24) will be - used. + used. An IPv6 address must be formatted as + [ipv6:address]. SECURITY - The SMTP+LMTP client is moderately security-sensitive. It - talks to SMTP or LMTP servers and to DNS servers on the + The SMTP+LMTP client is moderately security-sensitive. It + talks to SMTP or LMTP servers and to DNS servers on the network. The SMTP+LMTP client can be run chrooted at fixed low privilege. @@ -104,35 +115,41 @@ SMTP(8) SMTP(8) RFC 3463 (Enhanced Status Codes) DIAGNOSTICS - Problems and transactions are logged to syslogd(8). Cor- - rupted message files are marked so that the queue manager + Problems and transactions are logged to syslogd(8). Cor- + rupted message files are marked so that the queue manager can move them to the corrupt queue for further inspection. - Depending on the setting of the notify_classes parameter, - the postmaster is notified of bounces, protocol problems, + Depending on the setting of the notify_classes parameter, + the postmaster is notified of bounces, protocol problems, and of other trouble. BUGS - SMTP and LMTP connection caching does not work with TLS. - The necessary support for TLS object passivation and re- - activation does not exist without closing the session, + SMTP and LMTP connection caching does not work with TLS. + The necessary support for TLS object passivation and re- + activation does not exist without closing the session, which defeats the purpose. SMTP and LMTP connection caching assumes that SASL creden- - tials are valid for all destinations that map onto the + tials are valid for all destinations that map onto the same IP address and TCP port. CONFIGURATION PARAMETERS - Most smtp_xxx configuration parameters have an lmtp_xxx - "ghost" parameter for the equivalent LMTP feature. This + Before Postfix version 2.3, the LMTP client is a separate + program that implements only a subset of the functionality + available with SMTP: there is no support for TLS, and con- + nections are cached in-process, making it ineffective when + the client is used for multiple domains. + + Most smtp_xxx configuration parameters have an lmtp_xxx + "ghost" parameter for the equivalent LMTP feature. This document describes only those LMTP-related parameters that aren't simply "ghost" parameters. Changes to main.cf are picked up automatically, as smtp(8) - processes run for only a limited amount of time. Use the + processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. COMPATIBILITY CONTROLS @@ -146,7 +163,7 @@ SMTP(8) SMTP(8) Never send EHLO at the start of an SMTP session. smtp_defer_if_no_mx_address_found (no) - Defer mail delivery when no MX record resolves to + Defer mail delivery when no MX record resolves to an IP address. smtp_line_length_limit (990) @@ -154,17 +171,17 @@ SMTP(8) SMTP(8) that Postfix will send via SMTP. smtp_pix_workaround_delay_time (10s) - How long the Postfix SMTP client pauses before + How long the Postfix SMTP client pauses before sending ".<CR><LF>" in order to work around the PIX firewall "<CR><LF>.<CR><LF>" bug. smtp_pix_workaround_threshold_time (500s) - How long a message must be queued before the PIX - firewall "<CR><LF>.<CR><LF>" bug workaround is + How long a message must be queued before the PIX + firewall "<CR><LF>.<CR><LF>" bug workaround is turned on. smtp_quote_rfc821_envelope (yes) - Quote addresses in SMTP MAIL FROM and RCPT TO com- + Quote addresses in SMTP MAIL FROM and RCPT TO com- mands as required by RFC 821. smtp_skip_5xx_greeting (yes) @@ -172,7 +189,7 @@ SMTP(8) SMTP(8) (go away, do not try again later). smtp_skip_quit_response (yes) - Do not wait for the response to the SMTP QUIT com- + Do not wait for the response to the SMTP QUIT com- mand. Available in Postfix version 2.0 and earlier: @@ -184,36 +201,36 @@ SMTP(8) SMTP(8) Available in Postfix version 2.2 and later: smtp_discard_ehlo_keyword_address_maps (empty) - Lookup tables, indexed by the remote SMTP server - address, with case insensitive lists of EHLO key- - words (pipelining, starttls, auth, etc.) that the + Lookup tables, indexed by the remote SMTP server + address, with case insensitive lists of EHLO key- + words (pipelining, starttls, auth, etc.) that the SMTP client will ignore in the EHLO response from a remote SMTP server. smtp_discard_ehlo_keywords (empty) - A case insensitive list of EHLO keywords (pipelin- - ing, starttls, auth, etc.) that the SMTP client + A case insensitive list of EHLO keywords (pipelin- + ing, starttls, auth, etc.) that the SMTP client will ignore in the EHLO response from a remote SMTP server. smtp_generic_maps (empty) Optional lookup tables that perform address rewrit- - ing in the SMTP client, typically to transform a + ing in the SMTP client, typically to transform a locally valid address into a globally valid address when sending mail across the Internet. Available in Postfix version 2.3 and later: - lmtp_discard_lhlo_keyword_address_maps (empty) - Lookup tables, indexed by the remote LMTP server - address, with case insensitive lists of LHLO key- - words (pipelining, starttls, auth, etc.) that the + lmtp_discard_lhlo_keyword_address_maps (empty) + Lookup tables, indexed by the remote LMTP server + address, with case insensitive lists of LHLO key- + words (pipelining, starttls, auth, etc.) that the LMTP client will ignore in the LHLO response from a remote LMTP server. - lmtp_discard_lhlo_keywords ($myhostname) - A case insensitive list of LHLO keywords (pipelin- - ing, starttls, auth, etc.) that the LMTP client + lmtp_discard_lhlo_keywords ($myhostname) + A case insensitive list of LHLO keywords (pipelin- + ing, starttls, auth, etc.) that the LMTP client will ignore in the LHLO response from a remote LMTP server. @@ -221,7 +238,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.0 and later: disable_mime_output_conversion (no) - Disable the conversion of 8BITMIME format to 7BIT + Disable the conversion of 8BITMIME format to 7BIT format. mime_boundary_length_limit (2048) @@ -236,41 +253,52 @@ SMTP(8) SMTP(8) Available in Postfix version 2.1 and later: smtp_send_xforward_command (no) - Send the non-standard XFORWARD command when the - Postfix SMTP server EHLO response announces XFOR- + Send the non-standard XFORWARD command when the + Postfix SMTP server EHLO response announces XFOR- WARD support. SASL AUTHENTICATION CONTROLS smtp_sasl_auth_enable (no) - Enable SASL authentication in the Postfix SMTP + Enable SASL authentication in the Postfix SMTP client. smtp_sasl_password_maps (empty) - Optional SMTP client lookup tables with one user- - name:password entry per remote hostname or domain, + Optional SMTP client lookup tables with one user- + name:password entry per remote hostname or domain, or sender address when sender-dependent authentica- tion is enabled. smtp_sasl_security_options (noplaintext, noanonymous) - What authentication mechanisms the Postfix SMTP - client is allowed to use. + SASL security options; as of Postfix 2.3 the list + of available features depends on the SASL client + implementation that is selected with + smtp_sasl_type. Available in Postfix version 2.2 and later: smtp_sasl_mechanism_filter (empty) - If non-empty, a Postfix SMTP client filter for the - remote SMTP server's list of offered SASL mecha- + If non-empty, a Postfix SMTP client filter for the + remote SMTP server's list of offered SASL mecha- nisms. Available in Postfix version 2.3 and later: smtp_sender_dependent_authentication (no) - Enable sender-dependent authentication in the SMTP - client; this is available only with SASL authenti- - cation, and disables SMTP connection caching to - ensure that mail from different senders will use + Enable sender-dependent authentication in the SMTP + client; this is available only with SASL authenti- + cation, and disables SMTP connection caching to + ensure that mail from different senders will use the appropriate credentials. + smtp_sasl_path (empty) + Implementation-specific information that is passed + through to the SASL plug-in implementation that is + selected with smtp_sasl_type. + + smtp_sasl_type (cyrus) + The SASL plug-in type that the Postfix SMTP client + should use for authentication. + STARTTLS SUPPORT CONTROLS Detailed information about STARTTLS configuration may be found in the TLS_README document. @@ -437,14 +465,20 @@ SMTP(8) SMTP(8) The SMTP client time limit for sending the RSET command, and for receiving the server response. + Available in Postfix version 2.2 and earlier: + + lmtp_cache_connection (yes) + Keep Postfix LMTP client connections open for up to + $max_idle seconds. + Available in Postfix version 2.2 and later: smtp_connection_cache_destinations (empty) - Permanently enable SMTP connection caching for the + Permanently enable SMTP connection caching for the specified destinations. smtp_connection_cache_on_demand (yes) - Temporarily enable SMTP connection caching while a + Temporarily enable SMTP connection caching while a destination has a high volume of mail in the active queue. @@ -454,57 +488,57 @@ SMTP(8) SMTP(8) smtp_connection_cache_time_limit (2s) When SMTP connection caching is enabled, the amount - of time that an unused SMTP client socket is kept + of time that an unused SMTP client socket is kept open before it is closed. Available in Postfix version 2.3 and later: connection_cache_protocol_timeout (5s) - Time limit for connection cache connect, send or + Time limit for connection cache connect, send or receive operations. TROUBLE SHOOTING CONTROLS debug_peer_level (2) - The increment in verbose logging level when a - remote client or server matches a pattern in the + The increment in verbose logging level when a + remote client or server matches a pattern in the debug_peer_list parameter. debug_peer_list (empty) - Optional list of remote client or server hostname - or network address patterns that cause the verbose - logging level to increase by the amount specified + Optional list of remote client or server hostname + or network address patterns that cause the verbose + logging level to increase by the amount specified in $debug_peer_level. error_notice_recipient (postmaster) - The recipient of postmaster notifications about - mail delivery problems that are caused by policy, + The recipient of postmaster notifications about + mail delivery problems that are caused by policy, resource, software or protocol errors. notify_classes (resource, software) - The list of error classes that are reported to the + The list of error classes that are reported to the postmaster. MISCELLANEOUS CONTROLS best_mx_transport (empty) - Where the Postfix SMTP client should deliver mail + Where the Postfix SMTP client should deliver mail when it detects a "mail loops back to myself" error condition. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to - handle a request before it is terminated by a + How much time a Postfix daemon process may take to + handle a request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal + The maximal number of digits after the decimal point when logging sub-second delay values. disable_dns_lookups (no) - Disable DNS lookups in the Postfix SMTP and LMTP + Disable DNS lookups in the Postfix SMTP and LMTP clients. inet_interfaces (all) @@ -512,7 +546,7 @@ SMTP(8) SMTP(8) tem receives mail on. inet_protocols (ipv4) - The Internet protocols Postfix will attempt to use + The Internet protocols Postfix will attempt to use when making or accepting connections. ipc_timeout (3600s) @@ -520,74 +554,74 @@ SMTP(8) SMTP(8) over an internal communication channel. lmtp_tcp_port (24) - The default TCP port that the Postfix LMTP client + The default TCP port that the Postfix LMTP client connects to. max_idle (100s) - The maximum amount of time that an idle Postfix - daemon process waits for the next service request + The maximum amount of time that an idle Postfix + daemon process waits for the next service request before exiting. max_use (100) - The maximal number of connection requests before a + The maximal number of connection requests before a Postfix daemon process terminates. process_id (read-only) - The process ID of a Postfix command or daemon + The process ID of a Postfix command or daemon process. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. proxy_interfaces (empty) The network interface addresses that this mail sys- - tem receives mail on by way of a proxy or network + tem receives mail on by way of a proxy or network address translation unit. smtp_bind_address (empty) An optional numerical network address that the SMTP - client should bind to when making an IPv4 connec- + client should bind to when making an IPv4 connec- tion. smtp_bind_address6 (empty) An optional numerical network address that the SMTP - client should bind to when making an IPv6 connec- + client should bind to when making an IPv6 connec- tion. smtp_helo_name ($myhostname) - The hostname to send in the SMTP EHLO or HELO com- + The hostname to send in the SMTP EHLO or HELO com- mand. - lmtp_lhlo_name ($myhostname) + lmtp_lhlo_name ($myhostname) The hostname to send in the LMTP LHLO command. smtp_host_lookup (dns) - What mechanisms when the SMTP client uses to look + What mechanisms when the SMTP client uses to look up a host's IP address. smtp_randomize_addresses (yes) - Randomize the order of equal-preference MX host + Randomize the order of equal-preference MX host addresses. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (postfix) - The mail system name that is prepended to the - process name in syslog records, so that "smtpd" + The mail system name that is prepended to the + process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". Available with Postfix 2.2 and earlier: fallback_relay (empty) - Optional list of relay hosts for SMTP destinations + Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. Available with Postfix 2.3 and later: - smtp_fallback_relay ($fallback_relay) - Optional list of relay hosts for SMTP destinations + smtp_fallback_relay ($fallback_relay) + Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. SEE ALSO @@ -605,7 +639,7 @@ SMTP(8) SMTP(8) TLS_README, Postfix STARTTLS howto LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 15a9c85ce..1ecc28658 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -207,33 +207,40 @@ SMTPD(8) SMTPD(8) Enable SASL authentication in the Postfix SMTP server. - smtpd_sasl_application_name (smtpd) - The application name used for SASL server initial- - ization. - smtpd_sasl_local_domain (empty) The name of the local SASL authentication realm. smtpd_sasl_security_options (noanonymous) - Restrict what authentication mechanisms the Postfix - SMTP server will offer to the client. + SASL security options; as of Postfix 2.3 the list + of available features depends on the SASL server + implementation that is selected with + smtpd_sasl_type. smtpd_sender_login_maps (empty) - Optional lookup table with the SASL login names + Optional lookup table with the SASL login names that own sender (MAIL FROM) addresses. Available in Postfix version 2.1 and later: smtpd_sasl_exceptions_networks (empty) - What SMTP clients Postfix will not offer AUTH sup- + What SMTP clients Postfix will not offer AUTH sup- port to. Available in Postfix version 2.3 and later: smtpd_sasl_authenticated_header (no) - Report the SASL authenticated user name in the + Report the SASL authenticated user name in the smtpd(8) Received message header. + smtpd_sasl_path (smtpd) + Implementation-specific information that is passed + through to the SASL plug-in implementation that is + selected with smtpd_sasl_type. + + smtpd_sasl_type (cyrus) + The SASL plug-in type that the Postfix SMTP server + should use for authentication. + STARTTLS SUPPORT CONTROLS Detailed information about STARTTLS configuration may be found in the TLS_README document. @@ -811,6 +818,11 @@ SMTPD(8) SMTPD(8) reject_non_fqdn_sender or reject_non_fqdn_recipient restriction. + plaintext_reject_code (450) + The numerical Postfix SMTP server response code + when a request is rejected by the reject_plain- + text_session restriction. + reject_code (554) The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index 05ee5f8d5..1b982d816 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -9,9 +9,11 @@ Postfix configuration utility .na .nf .fi -\fBpostconf\fR [\fB-dhmlnv\fR] [\fB-c \fIconfig_dir\fR] +\fBpostconf\fR [\fB-dhnv\fR] [\fB-c \fIconfig_dir\fR] [\fIparameter ...\fR] +\fBpostconf\fR [\fB-aAmlv\fR] [\fB-c \fIconfig_dir\fR] + \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] [\fIparameter=value ...\fR] @@ -25,6 +27,18 @@ values, or displays other configuration information about the Postfix mail system. Options: +.IP \fB-a\fR +List the available SASL server plug-in types. The SASL +plug-in type is selected with the \fBsmtpd_sasl_type\fR +configuration parameter. + +This feature is available with Postfix 2.3 and later. +.IP \fB-A\fR +List the available SASL client plug-in types. The SASL +plug-in type is selected with the \fBsmtp_sasl_type\fR or +\fBlmtp_sasl_type\fR configuration parameters. + +This feature is available with Postfix 2.3 and later. .IP "\fB-b\fR [\fItemplate_file\fR]" Display the message text that appears at the beginning of delivery status notification (DSN) messages, with $\fBname\fR diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 7c56cf5ce..97247d18b 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -1859,10 +1859,20 @@ Optional LMTP client lookup tables with one username:password entry per host or domain. If a remote host or domain has no username:password entry, then the Postfix LMTP client will not attempt to authenticate to the remote host. +.SH lmtp_sasl_path (default: empty) +Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +\fBlmtp_sasl_type\fR. Typically this specifies the name of a +configuration file or rendez-vous point. +.PP +This feature is available in Postfix 2.3 and later. .SH lmtp_sasl_security_options (default: noplaintext, noanonymous) -What authentication mechanisms the Postfix LMTP client is allowed -to use. The list of available authentication mechanisms is system -dependent. +SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with \fBlmtp_sasl_type\fR. +.PP +The following security features are defined for the \fBcyrus\fR +client SASL implementation: .IP "\fBnoplaintext\fR" Disallow authentication methods that use plaintext passwords. .IP "\fBnoactive\fR" @@ -1888,6 +1898,12 @@ The LMTP-specific version of the smtp_sasl_tls_security_options configuration parameter. See there for details. .PP This feature is available in Postfix 2.3 and later. +.SH lmtp_sasl_type (default: cyrus) +The SASL plug-in type that the Postfix LMTP client should use +for authentication. The available types are listed with the +"\fBpostconf -A\fR" command. +.PP +This feature is available in Postfix 2.3 and later. .SH lmtp_send_xforward_command (default: no) Send an XFORWARD command to the LMTP server when the LMTP LHLO server response announces XFORWARD support. This allows an \fBlmtp\fR(8) @@ -2786,6 +2802,11 @@ The name of the \fBpickup\fR(8) service. This service picks up local mail submissions from the Postfix maildrop queue. .PP This feature is available in Postfix 2.0 and later. +.SH plaintext_session_reject_code (default: 450) +The numerical Postfix SMTP server response code when a request +is rejected by the \fBreject_plaintext_session\fR restriction. +.PP +This feature is available in Postfix 2.3 and later. .SH prepend_delivered_header (default: command, file, forward) The message delivery contexts where the Postfix \fBlocal\fR(8) delivery agent prepends a Delivered-To: message header with the address @@ -3919,10 +3940,20 @@ attempt to authenticate to the remote host. .PP The Postfix SMTP client opens the lookup table before going to chroot jail, so you can leave the password file in /etc/postfix. +.SH smtp_sasl_path (default: empty) +Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +\fBsmtp_sasl_type\fR. Typically this specifies the name of a +configuration file or rendez-vous point. +.PP +This feature is available in Postfix 2.3 and later. .SH smtp_sasl_security_options (default: noplaintext, noanonymous) -What authentication mechanisms the Postfix SMTP client is allowed -to use. The list of available authentication mechanisms is system -dependent. +SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with \fBsmtp_sasl_type\fR. +.PP +The following security features are defined for the \fBcyrus\fR +client SASL implementation: .PP Specify zero or more of the following: .IP "\fBnoplaintext\fR" @@ -3949,6 +3980,12 @@ smtp_sasl_security_options = noplaintext .SH smtp_sasl_tls_security_options (default: $smtp_sasl_security_options) The SASL authentication security options that the Postfix SMTP client uses for TLS encrypted SMTP sessions. +.SH smtp_sasl_type (default: cyrus) +The SASL plug-in type that the Postfix SMTP client should use +for authentication. The available types are listed with the +"\fBpostconf -A\fR" command. +.PP +This feature is available in Postfix 2.3 and later. .SH smtp_send_xforward_command (default: no) Send the non-standard XFORWARD command when the Postfix SMTP server EHLO response announces XFORWARD support. @@ -4570,6 +4607,14 @@ Use at the RCPT stage will only reject the second etc. recipient. The multi_recipient_bounce_reject_code parameter specifies the response code for rejected requests (default: 550). This feature is available in Postfix 2.1 and later. +.IP "\fBreject_plaintext_session\fR" +Reject the request when the connection is not encrypted. This +restriction should not be used before the client has had a chance +to negotiate encryption with the AUTH or STARTTLS commands. +.br +The plaintext_session_reject_code parameter specifies the response +code for rejected requests (default: 450). This feature is available +in Postfix 2.3 and later. .IP "\fBreject_unauth_pipelining\fR" Reject the request when the client sends SMTP commands ahead of time where it is not allowed, or when the client sends SMTP @@ -5241,7 +5286,21 @@ smtpd_sasl_local_domain = $myhostname .fi .ad .ft R +.SH smtpd_sasl_path (default: smtpd) +Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +\fBsmtpd_sasl_type\fR. Typically this specifies the name of a +configuration file or rendez-vous point. +.PP +This feature is available in Postfix 2.3 and later. .SH smtpd_sasl_security_options (default: noanonymous) +SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL server implementation that is selected +with \fBsmtpd_sasl_type\fR. +.PP +The following security features are defined for the \fBcyrus\fR +server SASL implementation: +.PP Restrict what authentication mechanisms the Postfix SMTP server will offer to the client. The list of available authentication mechanisms is system dependent. @@ -5281,6 +5340,12 @@ smtpd_sasl_security_options = noanonymous, noplaintext .SH smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options) The SASL authentication security options that the Postfix SMTP server uses for TLS encrypted SMTP sessions. +.SH smtpd_sasl_type (default: cyrus) +The SASL plug-in type that the Postfix SMTP server should use +for authentication. The available types are listed with the +"\fBpostconf -a\fR" command. +.PP +This feature is available in Postfix 2.3 and later. .SH smtpd_sender_login_maps (default: empty) Optional lookup table with the SASL login names that own sender (MAIL FROM) addresses. diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index a7176c63b..3f42ff7d1 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -47,16 +47,19 @@ specific destinations. .ad .fi SMTP destinations have the following form: -.IP "\fIdomainname\fR, \fIdomainname\fR:\fIport\fR" -Look up the mail exchangers for the specified domain. -.IP "[\fIhostname\fR], [\fIhostname\fR]:\fIport\fR" -Look up the address of the specified host. -.IP "[\fIaddress\fR], [\fIaddress\fR]:\fIport\fR" -Connect to the host at the specified address. An IPv6 -address must be formatted as [\fBipv6\fR:\fIaddress\fR]. -.PP -In all the above cases, when no port is specified, look up -the port defined as \fBsmtp\fR in \fBservices\fR(4). +.IP \fIdomainname\fR +.IP \fIdomainname\fR:\fIport\fR +Look up the mail exchangers for the specified domain, and +connect to the specified port (default: \fBsmtp\fR). +.IP [\fIhostname\fR] +.IP [\fIhostname\fR]:\fIport\fR +Look up the address(es) of the specified host, and connect to +the specified port (default: \fBsmtp\fR). +.IP [\fIaddress\fR] +.IP [\fIaddress\fR]:\fIport\fR +Connect to the host at the specified address, and connect +to the specified port (default: \fBsmtp\fR). An IPv6 address +must be formatted as [\fBipv6\fR:\fIaddress\fR]. .SH "LMTP DESTINATION SYNTAX" .na .nf @@ -67,13 +70,16 @@ LMTP destinations have the following form: Connect to the local UNIX-domain server that is bound to the specified \fIpathname\fR. If the process runs chrooted, an absolute pathname is interpreted relative to the Postfix queue directory. -.IP "\fBinet\fR:\fIhostname\fR, \fBinet\fB:\fIhostname\fR:\fIport\fR" -.IP "\fBinet\fR:[\fIaddress\fR], \fBinet\fR:[\fIaddress\fR]:\fIport\fR" +.IP \fBinet\fR:\fIhostname\fR +.IP \fBinet\fB:\fIhostname\fR:\fIport\fR +.IP \fBinet\fR:[\fIaddress\fR] +.IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR Connect to the specified TCP port on the specified local or remote host. If no port is specified, connect to the port defined as \fBlmtp\fR in \fBservices\fR(4). If no such service is found, the \fBlmtp_tcp_port\fR configuration parameter (default value of 24) will be used. +An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. .PP .SH "SECURITY" .na @@ -126,6 +132,12 @@ address and TCP port. .nf .ad .fi +Before Postfix version 2.3, the LMTP client is a separate +program that implements only a subset of the functionality +available with SMTP: there is no support for TLS, and +connections are cached in-process, making it ineffective +when the client is used for multiple domains. + Most smtp_\fIxxx\fR configuration parameters have an lmtp_\fIxxx\fR "ghost" parameter for the equivalent LMTP feature. This document describes only those LMTP-related @@ -233,8 +245,9 @@ Optional SMTP client lookup tables with one username:password entry per remote hostname or domain, or sender address when sender-dependent authentication is enabled. .IP "\fBsmtp_sasl_security_options (noplaintext, noanonymous)\fR" -What authentication mechanisms the Postfix SMTP client is allowed -to use. +SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with \fBsmtp_sasl_type\fR. .PP Available in Postfix version 2.2 and later: .IP "\fBsmtp_sasl_mechanism_filter (empty)\fR" @@ -247,6 +260,13 @@ Enable sender-dependent authentication in the SMTP client; this is available only with SASL authentication, and disables SMTP connection caching to ensure that mail from different senders will use the appropriate credentials. +.IP "\fBsmtp_sasl_path (empty)\fR" +Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +\fBsmtp_sasl_type\fR. +.IP "\fBsmtp_sasl_type (cyrus)\fR" +The SASL plug-in type that the Postfix SMTP client should use +for authentication. .SH "STARTTLS SUPPORT CONTROLS" .na .nf @@ -360,6 +380,11 @@ limit). The SMTP client time limit for sending the RSET command, and for receiving the server response. .PP +Available in Postfix version 2.2 and earlier: +.IP "\fBlmtp_cache_connection (yes)\fR" +Keep Postfix LMTP client connections open for up to $max_idle +seconds. +.PP Available in Postfix version 2.2 and later: .IP "\fBsmtp_connection_cache_destinations (empty)\fR" Permanently enable SMTP connection caching for the specified diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 16de5979e..9b030aa9c 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -202,13 +202,12 @@ Enable inter-operability with SMTP clients that implement an obsolete version of the AUTH command (RFC 2554). .IP "\fBsmtpd_sasl_auth_enable (no)\fR" Enable SASL authentication in the Postfix SMTP server. -.IP "\fBsmtpd_sasl_application_name (smtpd)\fR" -The application name used for SASL server initialization. .IP "\fBsmtpd_sasl_local_domain (empty)\fR" The name of the local SASL authentication realm. .IP "\fBsmtpd_sasl_security_options (noanonymous)\fR" -Restrict what authentication mechanisms the Postfix SMTP server -will offer to the client. +SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL server implementation that is selected +with \fBsmtpd_sasl_type\fR. .IP "\fBsmtpd_sender_login_maps (empty)\fR" Optional lookup table with the SASL login names that own sender (MAIL FROM) addresses. @@ -221,6 +220,13 @@ Available in Postfix version 2.3 and later: .IP "\fBsmtpd_sasl_authenticated_header (no)\fR" Report the SASL authenticated user name in the \fBsmtpd\fR(8) Received message header. +.IP "\fBsmtpd_sasl_path (smtpd)\fR" +Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +\fBsmtpd_sasl_type\fR. +.IP "\fBsmtpd_sasl_type (cyrus)\fR" +The SASL plug-in type that the Postfix SMTP server should use +for authentication. .SH "STARTTLS SUPPORT CONTROLS" .na .nf @@ -653,6 +659,9 @@ reject_rhsbl_sender or reject_rhsbl_recipient restriction. The numerical Postfix SMTP server reply code when a client request is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender or reject_non_fqdn_recipient restriction. +.IP "\fBplaintext_reject_code (450)\fR" +The numerical Postfix SMTP server response code when a request +is rejected by the \fBreject_plaintext_session\fR restriction. .IP "\fBreject_code (554)\fR" The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by the "reject" restriction. diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index eab0521be..d57349ca9 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -192,7 +192,37 @@ while (<>) { s;\bipc_timeout\b;$&;g; s;\bipc_ttl\b;$&;g; s;\bline_length_limit\b;$&;g; + s;\blmtp_bind_address\b;$&;g; + s;\blmtp_bind_address6\b;$&;g; s;\blmtp_cache_connection\b;$&;g; + s;\blmtp_discard_lhlo_keyword_address_maps\b;$&;g; + s;\blmtp_discard_lhlo_keywords\b;$&;g; + s;\blmtp_sasl_tls_security_options\b;$&;g; + s;\blmtp_sasl_mechanism_filter\b;$&;g; + s;\blmtp_host_lookup\b;$&;g; + s;\blmtp_connection_cache_destinations\b;$&;g; + s;\blmtp_tls_per_site\b;$&;g; + s;\blmtp_generic_maps\b;$&;g; + s;\blmtp_pix_workaround_threshold_time\b;$&;g; + s;\blmtp_pix_workaround_delay_time\b;$&;g; + s;\blmtp_connection_reuse_time_limit\b;$&;g; + s;\blmtp_starttls_timeout\b;$&;g; + s;\blmtp_line_length_limit\b;$&;g; + s;\blmtp_mx_address_limit\b;$&;g; + s;\blmtp_mx_session_limit\b;$&;g; + s;\blmtp_tls_scert_verifydepth\b;$&;g; + s;\blmtp_skip_5xx_greeting\b;$&;g; + s;\blmtp_randomize_addresses\b;$&;g; + s;\blmtp_quote_rfc821_envelope\b;$&;g; + s;\blmtp_defer_if_no_mx_address_found\b;$&;g; + s;\blmtp_connection_cache_on_demand\b;$&;g; + s;\blmtp_use_tls\b;$&;g; + s;\blmtp_enforce_tls\b;$&;g; + s;\blmtp_tls_enforce_peername\b;$&;g; + s;\blmtp_tls_note_starttls_offer\b;$&;g; + s;\blmtp_sender_dependent_authentication\b;$&;g; + s;\blmtp_sasl_path\b;$&;g; + s;\blmtp_lhlo_name\b;$&;g; s;\blmtp_connect_timeout\b;$&;g; s;\blmtp_data_done_timeout\b;$&;g; s;\blmtp_data_init_timeout\b;$&;g; @@ -205,6 +235,7 @@ while (<>) { s;\blmtp_sasl_auth_enable\b;$&;g; s;\blmtp_sasl_password_maps\b;$&;g; s;\blmtp_sasl_security_options\b;$&;g; + s;\blmtp_sasl_type\b;$&;g; s;\blmtp_send_xforward_command\b;$&;g; s;\blmtp_skip_quit_response\b;$&;g; s;\blmtp_tcp_port\b;$&;g; @@ -259,6 +290,7 @@ while (<>) { s;\bpar[-]*\n* *[]*ent_domain_matches_subdomains\b;$&;g; s;\bpermit_mx_backup_networks\b;$&;g; s;\bpickup_service_name\b;$&;g; + s;\bplaintext_session_reject_code\b;$&;g; s;\bprepend_delivered_header\b;$&;g; s;\bprocess_id\b;$&;g; s;\bprocess_id_directory\b;$&;g; @@ -364,6 +396,7 @@ while (<>) { s;\bsmtp_sasl_auth_enable\b;$&;g; s;\bsmtp_sasl_mechanism_filter\b;$&;g; s;\bsmtp_sasl_password_maps\b;$&;g; + s;\bsmtp_sasl_path\b;$&;g; s;\bsmtp_sasl_secu[-]*\n* *[]*rity_options\b;$&;g; s;\bsmtp_send_xforward_command\b;$&;g; s;\bsmtp_skip_4xx_greeting\b;$&;g; @@ -410,7 +443,7 @@ while (<>) { s;\bsmtpd_reject_unlisted_recip[-]*\n* *[]*ient\b;$&;g; s;\bsmtpd_reject_unlisted_sender\b;$&;g; s;\bsmtpd_restriction_classes\b;$&;g; - s;\bsmtpd_sasl_application_name\b;$&;g; + s;\bsmtpd_sasl_path\b;$&;g; s;\bsmtpd_sasl_auth_enable\b;$&;g; s;\bsmtpd_sasl_authenticated_header\b;$&;g; s;\bsmtpd_sasl_exceptions_networks\b;$&;g; @@ -462,8 +495,10 @@ while (<>) { s;\bvir[-]*\n*[ ]*tual_uid_maps\b;$&;g; s;\bsmtp_enforce_tls\b;$&;g; + s;\bsmtp_fallback_relay\b;$&;g; s;\bsmtp_sasl_tls_security_options\b;$&;g; s;\bsmtp_sasl_tls_verified_security_options\b;$&;g; + s;\bsmtp_sasl_type\b;$&;g; s;\bsmtp_starttls_timeout\b;$&;g; s;\bsmtp_tls_CAfile\b;$&;g; s;\bsmtp_tls_CApath\b;$&;g; @@ -482,6 +517,7 @@ while (<>) { s;\bsmtp_use_tls\b;$&;g; s;\bsmtpd_enforce_tls\b;$&;g; s;\bsmtpd_sasl_tls_security_options\b;$&;g; + s;\bsmtpd_sasl_type\b;$&;g; s;\bsmtpd_starttls_timeout\b;$&;g; s;\bsmtpd_tls_CAfile\b;$&;g; s;\bsmtpd_tls_CApath\b;$&;g; @@ -607,6 +643,7 @@ while (<>) { s;\bdefer_if_permit\b;$&;g; s;\bdefer_if_reject\b;$&;g; s;\breject_multi_recip[-]*\n* *[]*ient_bounce\b;$&;g; + s;\breject_plaintext_session\b;$&;g; s;\breject_unauth_pipelining\b;$&;g; s;\bwarn_if_reject\b;$&;g; diff --git a/postfix/proto/SASL_README.html b/postfix/proto/SASL_README.html index b60ba9aea..90da1ee6e 100644 --- a/postfix/proto/SASL_README.html +++ b/postfix/proto/SASL_README.html @@ -19,10 +19,9 @@

    WARNING

    -

    People who go to the trouble of installing Postfix may have -the expectation that Postfix is more secure than some other mailers. -The Cyrus SASL library is a lot of code. With SASL authentication -enabled in the Postfix SMTP client and SMTP server, Postfix becomes +

    People who go to the trouble of installing Postfix may have the +expectation that Postfix is more secure than some other mailers. +The Cyrus SASL library is a lot of code. With this, Postfix becomes as secure as other mail systems that use the Cyrus SASL library.

    @@ -38,9 +37,11 @@ optionally grants mail access via the permit_sasl_authenticated UCE restriction.

    When sending mail, Postfix can look up the server hostname or -destination domain (the address right-hand part) in a table, and if a -username/password is found, it will use that username and password -to authenticate to the server.

    +destination domain (the address right-hand part) in a Postfix SASL password +table, and if a username/password is found, it will use that username +and password to authenticate to the server. And as of version 2.3, +Postfix can be configured to search its SASL password table by the +sender email address.

    This document covers the following topics:

    @@ -48,9 +49,9 @@ to authenticate to the server.

  • What SASL versions are supported -
  • Building the SASL library +
  • Building the Cyrus SASL library -
  • Building Postfix with SASL authentication +
  • Building Postfix with Cyrus SASL support
  • Enabling SASL authentication in the @@ -70,31 +71,20 @@ Postfix SMTP client
  • What SASL versions are supported

    -

    Postfix+SASL 1.5.5 was seen working on RedHat 6.1 (pwcheck_method -set to shadow or sasldb), Solaris 2.7 (pwcheck_method set to shadow -or sasldb), and FreeBSD 3.4 (pwcheck_method set to sasldb). On -RedHat 6.1, SASL 1.5.5 insisted on write access to /etc/sasldb. -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.

    - -

    Building the SASL library

    +

    This document describes Postfix with Cyrus SASL version 1 and +Cyrus SASL version 2. Postfix version 2.3 introduces has a plug-in +mechanism for other SASL implementations. Support for other +implementations is currently not part of the Postfix distribution +and will be described elsewhere.

    + +

    Building the Cyrus SASL library

    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/.
    +ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/
     
    @@ -107,8 +97,7 @@ version 2.1.1.

    non-standard SASL LOGIN authentication method. To enable this authentication method, specify ``./configure --enable-login''.

    -

    Building Postfix with SASL authentication -support

    +

    Building Postfix with Cyrus SASL support

    To build Postfix with SASL authentication support, the following assumes that the Cyrus SASL include files are in /usr/local/include, @@ -119,20 +108,20 @@ and that the Cyrus SASL libraries are in /usr/local/lib.

    -
    (for SASL version 1.5.5): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include" AUXLIBS="-L/usr/local/lib -lsasl"
     
    -
    (for SASL version 2.1.1): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib -lsasl2"
     
    @@ -142,20 +131,22 @@ otherwise ld.so will not find the SASL shared library:

    -
    (for SASL version 1.5.5): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include" AUXLIBS="-L/usr/local/lib \
    +    -R/usr/local/lib -lsasl"
     
    -
    (for SASL version 2.1.1): +
    (for Cyrus 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"
    +% make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
    +    -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib \
    +    -R/usr/local/lib -lsasl2"
     
    @@ -195,20 +186,22 @@ SMTP server

    Note: the SASL login names will be shared with the entire world.

    -

    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 +

    In /usr/local/lib/sasl/smtpd.conf (Cyrus SASL version 1.5.5) or +/usr/local/lib/sasl2/smtpd.conf (Cyrus SASL version 2.1.1) you need to specify how the server should validate client passwords.

    Note: some Postfix distributions are modified and look for the smtpd.conf file in /etc/postfix.

    -

    Note: some Cyrus SASL distributions are modified and look for -the smtpd.conf file in /etc/sasl2.

    +

    Note: some Cyrus SASL distributions look for the smtpd.conf +file in /etc/sasl2.

    + +
      -

      In order to authenticate against the UNIX password database, try:

      +
    • To authenticate against the UNIX password database, try:

      -
      (SASL version 1.5.5) +
      (Cyrus SASL version 1.5.5)
       /usr/local/lib/sasl/smtpd.conf:
      @@ -216,7 +209,7 @@ the smtpd.conf file in /etc/sasl2. 

      -
      (SASL version 2.1.1) +
      (Cyrus SASL version 2.1.1)
       /usr/local/lib/sasl2/smtpd.conf:
      @@ -225,8 +218,9 @@ the smtpd.conf file in /etc/sasl2. 

      -

      The name of the file in /usr/local/lib/sasl (SASL version 1.5.5) -or /usr/local/lib/sasl2 (SASL version 2.1.1) used by the SASL +

      The name of the file in /usr/local/lib/sasl (Cyrus SASL version +1.5.5) or /usr/local/lib/sasl2 (Cyrus SASL version 2.1.1) used by +the SASL library for configuration can be set with:

      @@ -242,18 +236,19 @@ library for configuration can be set with:

      permission for the /var/pwcheck directory, otherwise authentication attempts will fail.

      -

      Alternately, in SASL 1.5.26 and later (including 2.1.1), try:

      +
    • Alternately, in Cyrus SASL 1.5.26 and later (including +2.1.1), try:

      -
      (SASL version 1.5.26) +
      (Cyrus SASL version 1.5.26)
       /usr/local/lib/sasl/smtpd.conf:
           pwcheck_method: saslauthd
       
      -
      (SASL version 2.1.1) +
      (Cyrus SASL version 2.1.1)
       /usr/local/lib/sasl2/smtpd.conf:
      @@ -267,17 +262,17 @@ tarball.  It is more flexible than the pwcheck daemon, in that it
       can authenticate against PAM and various other sources. To use PAM,
       start saslauthd with "-a pam". 

      -

      In order to authenticate against SASL's own password database:

      +
    • To authenticate against Cyrus SASL's own password database:

      -
      (SASL version 1.5.5) +
      (Cyrus SASL version 1.5.5)
       /usr/local/lib/sasl/smtpd.conf:
           pwcheck_method:  sasldb
       
      -
      (SASL version 2.1.1) +
      (Cyrus SASL version 2.1.1)
       /usr/local/lib/sasl2/smtpd.conf:
      @@ -286,63 +281,29 @@ start saslauthd with "-a pam". 

      -

      This will use the SASL password file (default: /etc/sasldb in +

      This will use the Cyrus 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 have to play games with group access permissions. With the OTP authentication mechanism, -the SMTP server also needs write access to /etc/sasldb2 or /etc/sasldb +the SMTP server also needs WRITE access to /etc/sasldb2 or /etc/sasldb (or the back end SQL database, if used).

      -

      IMPORTANT: all users must be able to authenticate using ALL -authentication mechanisms advertised by Postfix, otherwise the -negotiation might end up with an unsupported mechanism, and -authentication would fail. For example if you configure SASL to -use saslauthd for authentication against PAM (pluggable -authentication modules), only the PLAIN and LOGIN mechanisms are -supported and stand a chance to succeed, yet the SASL library would also -advertise other mechanisms, such as DIGEST-MD5. This happens because -those mechanisms are made available by other plugins, and the SASL -library have no way to know that your only valid authentication source -is PAM. Thus you might need to limit the list of mechanisms advertised -by Postfix. This is only possible with SASL version 2.1.1 or later: -

      - -
      -
      -/usr/local/lib/sasl2/smtpd.conf:
      -    mech_list: plain login
      -
      -
      - -

      For the same reasons you might want to limit the list of plugins -used for authentication. With SASL version 1.5.5 your only choice is to -delete the corresponding libraries from /usr/local/lib/sasl. With SASL -version 2.1.1:

      - -
      -
      -/usr/local/lib/sasl2/smtpd.conf:
      -    pwcheck_method:  auxprop
      -    auxprop_plugin:  sql
      -
      -
      -

      IMPORTANT: To get sasldb running, make sure that you set the SASL domain (realm) to a fully qualified domain name.

      EXAMPLE:

      -
      (SASL version 1.5.5) +
      (Cyrus SASL version 1.5.5)
       % saslpasswd -c -u `postconf -h myhostname` exampleuser
       
      -
      (SASL version 2.1.1) +
      (Cyrus SASL version 2.1.1)
       % saslpasswd2 -c -u `postconf -h myhostname` exampleuser
      @@ -351,8 +312,8 @@ domain (realm) to a fully qualified domain name. 

      You can find out SASL's idea about the realms of the users -in sasldb with sasldblistusers (SASL version 1.5.5) or -sasldblistusers2 (SASL version 2.1.1).

      +in sasldb with sasldblistusers (Cyrus SASL version 1.5.5) or +sasldblistusers2 (Cyrus SASL version 2.1.1).

      On the Postfix side, you can have only one realm per smtpd instance, and only the users belonging to that realm would be able to @@ -366,6 +327,59 @@ realm used by smtpd:

    • +
    + +

    IMPORTANT: all users must be able to authenticate using ALL +authentication mechanisms advertised by Postfix, otherwise the +negotiation might end up with an unsupported mechanism, and +authentication would fail. For example if you configure SASL to +use saslauthd for authentication against PAM (pluggable +authentication modules), only the PLAIN and LOGIN mechanisms are +supported and stand a chance to succeed, yet the SASL library would also +advertise other mechanisms, such as DIGEST-MD5. This happens because +those mechanisms are made available by other plugins, and the SASL +library have no way to know that your only valid authentication source +is PAM. Thus you might need to limit the list of mechanisms advertised +by Postfix.

    + +
      + +
    • With older Cyrus SASL versions you remove the corresponding +library files from the SASL plug-in directory (and again whenever +the system is updated).

      + +
    • With Cyrus SASL version 2.1.1 or later:

      + +
      +
      +/usr/local/lib/sasl2/smtpd.conf:
      +    mech_list: plain login
      +
      +
      + +
    + +

    For the same reasons you might want to limit the list of plugins +used for authentication.

    + +
      + +
    • With Cyrus SASL version 1.5.5 your only choice is to +delete the corresponding library files from the SASL plug-in +directory.

      + +
    • With SASL version 2.1.1:

      + +
      +
      +/usr/local/lib/sasl2/smtpd.conf:
      +    pwcheck_method:  auxprop
      +    auxprop_plugin:  sql
      +
      +
      + +
    +

    To run software chrooted with SASL support is an interesting exercise. It probably is not worth the trouble.

    @@ -470,6 +484,25 @@ table.

    +

    Postfix version 2.3 supports-per-sender SASL password +information. To search the Postfix SASL password by sender +before it searches by destination, specify:

    + +
    +
    +/etc/postfix/main.cf:
    +    smtp_sender_dependent_authentication = yes
    +    smtp_sasl_auth_enable = yes
    +    smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
    +
    +/etc/postfix/sasl_passwd:
    +    user@example.com            username:password
    +    bar.com                     username
    +    [mail.myisp.net]            username:password
    +    [mail.myisp.net]:submission username:password
    +
    +
    +

    Note: some SMTP servers support PLAIN or LOGIN authentication only. By default, the Postfix SMTP client does not use authentication methods that send plaintext passwords, and defers delivery with @@ -480,11 +513,11 @@ for example:

     /etc/postfix/main.cf:
    -    smtp_sasl_security_options = 
    +    smtp_sasl_security_options = noanonymous
     
    -

    The SASL client password file is opened before the SMTP server +

    The Postfix SASL client password file is opened before the SMTP server enters the optional chroot jail, so you can keep the file in /etc/postfix.

    @@ -493,7 +526,17 @@ although available on the client system, may not in practice work or possess the appropriate credentials to authenticate to the server. It is possible via the smtp_sasl_mechanism_filter parameter to further restrict the list of server mechanisms that the smtp(8) client will take -into consideration.

    +into consideration:

    + +
    +
    +/etc/postfix/main.cf:
    +    smtp_sasl_mechanism_filter = !gssapi, !external, static:all
    +
    +
    + +

    In the above example, Postfix will decline to use mechanisms +that require special infrastructure such as Kerberos.

    The Postfix SMTP client is backwards compatible with SMTP servers that use the non-standard "AUTH=method..." syntax in response @@ -509,13 +552,16 @@ of SuSE Rhein/Main AG.

  • Wietse trimmed down the code to only the bare necessities. -
  • Support for SASL version 2 was contributed by Jason Hoos. +
  • Support for Cyrus SASL version 2 was contributed by Jason Hoos.
  • Liviu Daia added smtpd_sasl_application_name, split reject_sender_login_mismatch into reject_authenticated_sender_login_mismatch and reject_unauthenticated_sender_login_mismatch, and revised the docs. +
  • Wietse made another iteration through the code to add +plug-in support for multiple implementations. + diff --git a/postfix/proto/SMTPD_POLICY_README.html b/postfix/proto/SMTPD_POLICY_README.html index 5a3b5e26a..24e8cd8cc 100644 --- a/postfix/proto/SMTPD_POLICY_README.html +++ b/postfix/proto/SMTPD_POLICY_README.html @@ -83,13 +83,18 @@ client_address=1.2.3.4 client_name=another.domain.tld reverse_client_name=another.domain.tld instance=123.456.7 +Postfix version 2.2 and later: sasl_method=plain sasl_username=you sasl_sender= +size=12345 ccert_subject=solaris9.porcupine.org ccert_issuer=Wietse Venema ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 -size=12345 +Postfix version 2.3 and later: +encryption_protocol=TLSv1/SSLv3 +encryption_cipher=DHE-RSA-AES256-SHA +encryption_keysize=256 [empty line] @@ -137,12 +142,19 @@ size=12345
  • The "sasl_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via SASL. + These attributes are empty in case of no SASL authentication.

  • The "ccert_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via TLS. + These attributes are empty in case of no certificate authentication.

    +
  • The "encryption_*" attributes (Postfix 2.3 and later) + specify information about how the connection is encrypted. With + plaintext connections the protocol and cypher attributes are + empty and the keysize is zero.

    +

    The following is specific to SMTPD delegated policy requests: diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index cf73234eb..cc4786893 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -4048,11 +4048,12 @@ chroot jail, so you can leave the password file in /etc/postfix. %PARAM smtp_sasl_security_options noplaintext, noanonymous -

    -What authentication mechanisms the Postfix SMTP client is allowed -to use. The list of available authentication mechanisms is system -dependent. -

    +

    SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with smtp_sasl_type.

    + +

    The following security features are defined for the cyrus +client SASL implementation:

    Specify zero or more of the following: @@ -4703,6 +4704,16 @@ The multi_recipient_bounce_reject_code parameter specifies the response code for rejected requests (default: 550). This feature is available in Postfix 2.1 and later. +

    reject_plaintext_session
    + +
    Reject the request when the connection is not encrypted. This +restriction should not be used before the client has had a chance +to negotiate encryption with the AUTH or STARTTLS commands. +
    +The plaintext_session_reject_code parameter specifies the response +code for rejected requests (default: 450). This feature is available +in Postfix 2.3 and later.
    +
    reject_unauth_pipelining
    Reject the request when the client sends SMTP commands ahead @@ -5447,6 +5458,13 @@ smtpd_sasl_local_domain = $myhostname %PARAM smtpd_sasl_security_options noanonymous +

    SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL server implementation that is selected +with smtpd_sasl_type.

    + +

    The following security features are defined for the cyrus +server SASL implementation:

    +

    Restrict what authentication mechanisms the Postfix SMTP server will offer to the client. The list of available authentication @@ -6746,11 +6764,12 @@ to the remote host. %PARAM lmtp_sasl_security_options noplaintext, noanonymous -

    -What authentication mechanisms the Postfix LMTP client is allowed -to use. The list of available authentication mechanisms is system -dependent. -

    +

    SASL security options; as of Postfix 2.3 the list of available +features depends on the SASL client implementation that is selected +with lmtp_sasl_type.

    + +

    The following security features are defined for the cyrus +client SASL implementation:

    @@ -9036,3 +9055,64 @@ configuration parameter. See there for details.

    operations. The time limit is enforced in the client.

    This feature is available in Postfix 2.3 and later.

    + +%PARAM smtpd_sasl_type cyrus + +

    The SASL plug-in type that the Postfix SMTP server should use +for authentication. The available types are listed with the +"postconf -a" command.

    + +

    This feature is available in Postfix 2.3 and later.

    + +%PARAM smtp_sasl_type cyrus + +

    The SASL plug-in type that the Postfix SMTP client should use +for authentication. The available types are listed with the +"postconf -A" command.

    + +

    This feature is available in Postfix 2.3 and later.

    + + +%PARAM lmtp_sasl_type cyrus + +

    The SASL plug-in type that the Postfix LMTP client should use +for authentication. The available types are listed with the +"postconf -A" command.

    + +

    This feature is available in Postfix 2.3 and later.

    + +%PARAM smtpd_sasl_path smtpd + +

    Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +smtpd_sasl_type. Typically this specifies the name of a +configuration file or rendez-vous point.

    + +

    This feature is available in Postfix 2.3 and later.

    + +%PARAM smtp_sasl_path + +

    Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +smtp_sasl_type. Typically this specifies the name of a +configuration file or rendez-vous point.

    + +

    This feature is available in Postfix 2.3 and later.

    + +%PARAM lmtp_sasl_path + +

    Implementation-specific information that is passed through to +the SASL plug-in implementation that is selected with +lmtp_sasl_type. Typically this specifies the name of a +configuration file or rendez-vous point.

    + +

    This feature is available in Postfix 2.3 and later.

    + +%PARAM plaintext_session_reject_code 450 + +

    +The numerical Postfix SMTP server response code when a request +is rejected by the reject_plaintext_session restriction. +

    + +

    This feature is available in Postfix 2.3 and later.

    diff --git a/postfix/src/bounce/bounce_trace_service.c b/postfix/src/bounce/bounce_trace_service.c index a1f9fd532..04cf425ce 100644 --- a/postfix/src/bounce/bounce_trace_service.c +++ b/postfix/src/bounce/bounce_trace_service.c @@ -51,10 +51,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 11ec09bc1..bd1f46e99 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -46,10 +46,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/cleanup/cleanup_out_recipient.c b/postfix/src/cleanup/cleanup_out_recipient.c index 94af4cb78..476dc44b5 100644 --- a/postfix/src/cleanup/cleanup_out_recipient.c +++ b/postfix/src/cleanup/cleanup_out_recipient.c @@ -60,10 +60,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/dns/dns_rr_to_sa.c b/postfix/src/dns/dns_rr_to_sa.c index 4611fdabc..0ebe087a0 100644 --- a/postfix/src/dns/dns_rr_to_sa.c +++ b/postfix/src/dns/dns_rr_to_sa.c @@ -6,11 +6,11 @@ /* SYNOPSIS /* #include /* -/* int dns_rr_to_sa(rr, port, sa, sa_len) +/* int dns_rr_to_sa(rr, port, sa, sa_length) /* DNS_RR *rr; /* unsigned port; /* struct sockaddr *sa; -/* SOCKADDR_SIZE *sa_len; +/* SOCKADDR_SIZE *sa_length; /* DESCRIPTION /* dns_rr_to_sa() converts the address in a DNS resource record into /* a socket address of the corresponding type. @@ -22,7 +22,7 @@ /* TCP or UDP port, network byte order. /* .IP sa /* Socket address pointer. -/* .IP sa_len +/* .IP sa_length /* On input, the available socket address storage space. /* On output, the amount of space actually used. /* DIAGNOSTICS @@ -55,7 +55,7 @@ /* dns_rr_to_sa - resource record to socket address */ int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa, - SOCKADDR_SIZE *sa_len) + SOCKADDR_SIZE *sa_length) { SOCKADDR_SIZE sock_addr_len; @@ -63,7 +63,7 @@ int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa, if (rr->data_len != sizeof(SOCK_ADDR_IN_ADDR(sa))) { errno = EINVAL; return (-1); - } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN_PTR(sa))) > *sa_len) { + } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN_PTR(sa))) > *sa_length) { errno = ENOSPC; return (-1); } else { @@ -74,7 +74,7 @@ int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa, #ifdef HAS_SA_LEN sa->sa_len = sock_addr_len; #endif - *sa_len = sock_addr_len; + *sa_length = sock_addr_len; return (0); } #ifdef HAS_IPV6 @@ -82,7 +82,7 @@ int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa, if (rr->data_len != sizeof(SOCK_ADDR_IN6_ADDR(sa))) { errno = EINVAL; return (-1); - } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN6_PTR(sa))) > *sa_len) { + } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN6_PTR(sa))) > *sa_length) { errno = ENOSPC; return (-1); } else { @@ -93,7 +93,7 @@ int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa, #ifdef HAS_SA_LEN sa->sa_len = sock_addr_len; #endif - *sa_len = sock_addr_len; + *sa_length = sock_addr_len; return (0); } #endif @@ -127,7 +127,7 @@ int main(int argc, char **argv) MAI_SERVPORT_STR portnum; struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *) & ss; - SOCKADDR_SIZE sa_len = sizeof(ss); + SOCKADDR_SIZE sa_length = sizeof(ss); VSTRING *why; int type; int port; @@ -146,10 +146,10 @@ int main(int argc, char **argv) usage(); if (dns_lookup(argv[1], type, 0, &rr, (VSTRING *) 0, why) != DNS_OK) msg_fatal("%s: %s", argv[1], vstring_str(why)); - sa_len = sizeof(ss); - if (dns_rr_to_sa(rr, htons(port), sa, &sa_len) != 0) + sa_length = sizeof(ss); + if (dns_rr_to_sa(rr, htons(port), sa, &sa_length) != 0) msg_fatal("dns_rr_to_sa: %m"); - SOCKADDR_TO_HOSTADDR(sa, sa_len, &hostaddr, &portnum, 0); + SOCKADDR_TO_HOSTADDR(sa, sa_length, &hostaddr, &portnum, 0); vstream_printf("%s %s -> %s %s\n", argv[1], argv[2], hostaddr.buf, portnum.buf); vstream_fflush(VSTREAM_OUT); diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 590a02221..e46bf79a6 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -631,6 +631,8 @@ deliver_pass.o: ../../include/sys_defs.h deliver_pass.o: ../../include/vbuf.h deliver_pass.o: ../../include/vstream.h deliver_pass.o: ../../include/vstring.h +deliver_pass.o: bounce.h +deliver_pass.o: defer.h deliver_pass.o: deliver_pass.c deliver_pass.o: deliver_pass.h deliver_pass.o: deliver_request.h diff --git a/postfix/src/global/cfg_parser.c b/postfix/src/global/cfg_parser.c index 58a3c4afd..525294889 100644 --- a/postfix/src/global/cfg_parser.c +++ b/postfix/src/global/cfg_parser.c @@ -85,6 +85,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include "msg.h" diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index 09403e820..91675b495 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -68,6 +68,7 @@ #include #include #include +#include #define DELIVER_PASS_DEFER 1 #define DELIVER_PASS_UNKNOWN 2 diff --git a/postfix/src/global/dict_ldap.c b/postfix/src/global/dict_ldap.c index 24daf2972..eaaad4908 100644 --- a/postfix/src/global/dict_ldap.c +++ b/postfix/src/global/dict_ldap.c @@ -169,6 +169,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* * Older APIs have weird memory freeing behavior. */ diff --git a/postfix/src/global/dict_mysql.c b/postfix/src/global/dict_mysql.c index 62dbf38b3..282366c6c 100644 --- a/postfix/src/global/dict_mysql.c +++ b/postfix/src/global/dict_mysql.c @@ -172,6 +172,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include "dict.h" diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index eff145f19..2decd4cef 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1246,12 +1246,12 @@ extern bool var_smtpd_sasl_auth_hdr; #define DEF_SMTPD_SASL_OPTS "noanonymous" extern char *var_smtpd_sasl_opts; -#define VAR_SMTPD_SASL_APPNAME "smtpd_sasl_application_name" -#define DEF_SMTPD_SASL_APPNAME "smtpd" -extern char *var_smtpd_sasl_appname; +#define VAR_SMTPD_SASL_PATH "smtpd_sasl_path" +#define DEF_SMTPD_SASL_PATH "smtpd" +extern char *var_smtpd_sasl_path; #define VAR_SMTPD_SASL_TLS_OPTS "smtpd_sasl_tls_security_options" -#define DEF_SMTPD_SASL_TLS_OPTS "$smtpd_sasl_security_options" +#define DEF_SMTPD_SASL_TLS_OPTS "$" VAR_SMTPD_SASL_OPTS extern char *var_smtpd_sasl_tls_opts; #define VAR_SMTPD_SASL_REALM "smtpd_sasl_local_domain" @@ -1262,6 +1262,14 @@ extern char *var_smtpd_sasl_realm; #define DEF_SMTPD_SASL_EXCEPTIONS_NETWORKS "" extern char *var_smtpd_sasl_exceptions_networks; +#ifndef DEF_SERVER_SASL_TYPE +#define DEF_SERVER_SASL_TYPE "cyrus" +#endif + +#define VAR_SMTPD_SASL_TYPE "smtpd_sasl_type" +#define DEF_SMTPD_SASL_TYPE DEF_SERVER_SASL_TYPE +extern char *var_smtpd_sasl_type; + #define VAR_SMTPD_SND_AUTH_MAPS "smtpd_sender_login_maps" #define DEF_SMTPD_SND_AUTH_MAPS "" extern char *var_smtpd_snd_auth_maps; @@ -1287,16 +1295,30 @@ extern char *var_smtp_sasl_passwd; #define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous" extern char *var_smtp_sasl_opts; +#define VAR_SMTP_SASL_PATH "smtp_sasl_path" +#define DEF_SMTP_SASL_PATH "" +extern char *var_smtp_sasl_path; + #define VAR_SMTP_SASL_MECHS "smtp_sasl_mechanism_filter" #define DEF_SMTP_SASL_MECHS "" #define VAR_LMTP_SASL_MECHS "lmtp_sasl_mechanism_filter" #define DEF_LMTP_SASL_MECHS "" extern char *var_smtp_sasl_mechs; +#ifndef DEF_CLIENT_SASL_TYPE +#define DEF_CLIENT_SASL_TYPE "cyrus" +#endif + +#define VAR_SMTP_SASL_TYPE "smtp_sasl_type" +#define DEF_SMTP_SASL_TYPE DEF_CLIENT_SASL_TYPE +#define VAR_LMTP_SASL_TYPE "lmtp_sasl_type" +#define DEF_LMTP_SASL_TYPE DEF_CLIENT_SASL_TYPE +extern char *var_smtp_sasl_type; + #define VAR_SMTP_SASL_TLS_OPTS "smtp_sasl_tls_security_options" -#define DEF_SMTP_SASL_TLS_OPTS "$var_smtp_sasl_opts" +#define DEF_SMTP_SASL_TLS_OPTS "$" VAR_SMTP_SASL_OPTS #define VAR_LMTP_SASL_TLS_OPTS "lmtp_sasl_tls_security_options" -#define DEF_LMTP_SASL_TLS_OPTS "$var_lmtp_sasl_opts" +#define DEF_LMTP_SASL_TLS_OPTS "$" VAR_LMTP_SASL_OPTS extern char *var_smtp_sasl_tls_opts; /* @@ -1362,6 +1384,10 @@ extern char *var_lmtp_sasl_passwd; #define DEF_LMTP_SASL_OPTS "noplaintext, noanonymous" extern char *var_lmtp_sasl_opts; +#define VAR_LMTP_SASL_PATH "lmtp_sasl_path" +#define DEF_LMTP_SASL_PATH "" +extern char *var_lmtp_sasl_path; + /* * SASL-based relay etc. control. */ @@ -1649,6 +1675,11 @@ extern int var_defer_code; #define SLEEP "sleep" +#define REJECT_PLAINTEXT_SESSION "reject_plaintext_session" +#define VAR_PLAINTEXT_CODE "plaintext_reject_code" +#define DEF_PLAINTEXT_CODE 450 +extern int var_plaintext_code; + #define REJECT_UNKNOWN_CLIENT "reject_unknown_client" #define REJECT_UNKNOWN_CLIENT_HOSTNAME "reject_unknown_client_hostname" #define REJECT_UNKNOWN_REVERSE_HOSTNAME "reject_unknown_reverse_client_hostname" diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index b6e46ec5b..2612900dc 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -134,6 +134,9 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_CCERT_SUBJECT "ccert_subject" #define MAIL_ATTR_CCERT_ISSSUER "ccert_issuer" #define MAIL_ATTR_CCERT_FINGERPRINT "ccert_fingerprint" +#define MAIL_ATTR_CRYPTO_PROTOCOL "encryption_protocol" +#define MAIL_ATTR_CRYPTO_CYPHER "encryption_cipher" +#define MAIL_ATTR_CRYPTO_KEYSIZE "encryption_keysize" /* * Suffixes for sender_name, sender_domain etc. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 317e55d5c..b2924d7be 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20051212" +#define MAIL_RELEASE_DATE "20051220" #define MAIL_VERSION_NUMBER "2.3" #ifdef SNAPSHOT diff --git a/postfix/src/global/rec_type.h b/postfix/src/global/rec_type.h index 4e1b83bc7..ead079964 100644 --- a/postfix/src/global/rec_type.h +++ b/postfix/src/global/rec_type.h @@ -11,6 +11,12 @@ /* DESCRIPTION /* .nf + /* + * System library. + */ +#include +#include + /* * Diagnostic codes, not real record lookup results. */ diff --git a/postfix/src/global/sent.c b/postfix/src/global/sent.c index 56fdd8e2f..c99ae5b17 100644 --- a/postfix/src/global/sent.c +++ b/postfix/src/global/sent.c @@ -72,10 +72,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index db3f9cb19..5aee04ba0 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -11,7 +11,7 @@ MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \ PROG = postconf SAMPLES = ../../conf/main.cf.default INC_DIR = ../../include -LIBS = ../../lib/libglobal.a ../../lib/libutil.a +LIBS = ../../lib/libxsasl.a ../../lib/libglobal.a ../../lib/libutil.a .c.o:; $(CC) $(CFLAGS) -c $*.c @@ -97,6 +97,7 @@ postconf.o: ../../include/vbuf.h postconf.o: ../../include/vstream.h postconf.o: ../../include/vstring.h postconf.o: ../../include/vstring_vstream.h +postconf.o: ../../include/xsasl.h postconf.o: auto_table.h postconf.o: auto_vars.h postconf.o: bool_table.h diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index ed3796d4d..be948313f 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -5,9 +5,11 @@ /* Postfix configuration utility /* SYNOPSIS /* .fi -/* \fBpostconf\fR [\fB-dhmlnv\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostconf\fR [\fB-dhnv\fR] [\fB-c \fIconfig_dir\fR] /* [\fIparameter ...\fR] /* +/* \fBpostconf\fR [\fB-aAmlv\fR] [\fB-c \fIconfig_dir\fR] +/* /* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] /* [\fIparameter=value ...\fR] /* @@ -19,6 +21,18 @@ /* the Postfix mail system. /* /* Options: +/* .IP \fB-a\fR +/* List the available SASL server plug-in types. The SASL +/* plug-in type is selected with the \fBsmtpd_sasl_type\fR +/* configuration parameter. +/* +/* This feature is available with Postfix 2.3 and later. +/* .IP \fB-A\fR +/* List the available SASL client plug-in types. The SASL +/* plug-in type is selected with the \fBsmtp_sasl_type\fR or +/* \fBlmtp_sasl_type\fR configuration parameters. +/* +/* This feature is available with Postfix 2.3 and later. /* .IP "\fB-b\fR [\fItemplate_file\fR]" /* Display the message text that appears at the beginning of /* delivery status notification (DSN) messages, with $\fBname\fR @@ -203,10 +217,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - #ifdef USE_PATHS_H #include #endif @@ -241,6 +251,10 @@ #include #include +/* XSASL library. */ + +#include + /* * What we're supposed to be doing. */ @@ -251,6 +265,8 @@ #define EDIT_MAIN (1<<4) /* edit main.cf */ #define SHOW_LOCKS (1<<5) /* show mailbox lock methods */ #define SHOW_EVAL (1<<6) /* expand right-hand sides */ +#define SHOW_SASL_SERV (1<<7) /* show server auth plugin types */ +#define SHOW_SASL_CLNT (1<<7) /* show client auth plugin types */ /* * Lookup table for in-core parameter info. @@ -878,13 +894,27 @@ static void show_maps(void) static void show_locks(void) { - ARGV *maps_argv; + ARGV *locks_argv; int i; - maps_argv = mbox_lock_names(); - for (i = 0; i < maps_argv->argc; i++) - vstream_printf("%s\n", maps_argv->argv[i]); - argv_free(maps_argv); + locks_argv = mbox_lock_names(); + for (i = 0; i < locks_argv->argc; i++) + vstream_printf("%s\n", locks_argv->argv[i]); + argv_free(locks_argv); +} + +/* show_sasl - show SASL plug-in types */ + +static void show_sasl(int what) +{ + ARGV *sasl_argv; + int i; + + sasl_argv = (what & SHOW_SASL_SERV) ? xsasl_server_types() : + xsasl_client_types(); + for (i = 0; i < sasl_argv->argc; i++) + vstream_printf("%s\n", sasl_argv->argv[i]); + argv_free(sasl_argv); } /* show_parameters - show parameter info */ @@ -953,8 +983,14 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "bc:deEhmlntv")) > 0) { + while ((ch = GETOPT(argc, argv, "aAbc:deEhmlntv")) > 0) { switch (ch) { + case 'a': + mode |= SHOW_SASL_SERV; + break; + case 'A': + mode |= SHOW_SASL_CLNT; + break; case 'b': if (ext_argv) msg_fatal("specify one of -b and -t"); @@ -1005,18 +1041,19 @@ int main(int argc, char **argv) msg_verbose++; break; default: - msg_fatal("usage: %s [-b (bounce templates)] [-c config_dir] [-d (defaults)] [-e (edit)] [-h (no names)] [-l (lock types)] [-m (map types)] [-n (non-defaults)] [-v] [name...]", argv[0]); + msg_fatal("usage: %s [-a (server SASL types)] [-A (client SASL types)] [-b (bounce templates)] [-c config_dir] [-d (defaults)] [-e (edit)] [-h (no names)] [-l (lock types)] [-m (map types)] [-n (non-defaults)] [-v] [name...]", argv[0]); } } /* * Sanity check. */ - junk = (mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN)); + junk = (mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN | SHOW_SASL_SERV | SHOW_SASL_CLNT)); if (junk != 0 && ((junk != SHOW_DEFS && junk != SHOW_NONDEF - && junk != SHOW_MAPS && junk != SHOW_LOCKS && junk != EDIT_MAIN) + && junk != SHOW_MAPS && junk != SHOW_LOCKS && junk != EDIT_MAIN + && junk != SHOW_SASL_SERV && junk != SHOW_SASL_CLNT) || ext_argv != 0)) - msg_fatal("specify one of -b, -d, -e, -m, -l and -n"); + msg_fatal("specify one of -a, -A, -b, -d, -e, -m, -l and -n"); /* * Display bounce template information and exit. @@ -1054,6 +1091,15 @@ int main(int argc, char **argv) show_locks(); } + /* + * If showing SASL plug-in types, show them and exit + */ + else if (mode & SHOW_SASL_SERV) { + show_sasl(SHOW_SASL_SERV); + } else if (mode & SHOW_SASL_CLNT) { + show_sasl(SHOW_SASL_CLNT); + } + /* * Edit main.cf. */ diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index 70f34cfb5..44b377bad 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -451,6 +451,7 @@ int main(int argc, char **argv) * Further initialization... */ mail_conf_read(); + mail_dict_init(); /* proxy, sql, ldap */ get_mail_conf_str_table(str_table); /* diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 558515d4c..bb8a5ab4f 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -153,10 +153,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/qmqpd/qmqpd_peer.c b/postfix/src/qmqpd/qmqpd_peer.c index e05e77c8e..a42e184d2 100644 --- a/postfix/src/qmqpd/qmqpd_peer.c +++ b/postfix/src/qmqpd/qmqpd_peer.c @@ -75,16 +75,16 @@ void qmqpd_peer_init(QMQPD_STATE *state) char *myname = "qmqpd_peer_init"; struct sockaddr_storage ss; struct sockaddr *sa; - SOCKADDR_SIZE sa_len; + SOCKADDR_SIZE sa_length; INET_PROTO_INFO *proto_info = inet_proto_info(); sa = (struct sockaddr *) & ss; - sa_len = sizeof(ss); + sa_length = sizeof(ss); /* * Look up the peer address information. */ - if (getpeername(vstream_fileno(state->client), sa, &sa_len) >= 0) { + if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) { errno = 0; } @@ -121,7 +121,7 @@ void qmqpd_peer_init(QMQPD_STATE *state) /* * Convert the client address to printable form. */ - if ((aierr = sockaddr_to_hostaddr(sa, sa_len, &client_addr, + if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr, (MAI_SERVPORT_STR *) 0, 0)) != 0) msg_fatal("%s: cannot convert client address to string: %s", myname, MAI_STRERROR(aierr)); @@ -149,10 +149,10 @@ void qmqpd_peer_init(QMQPD_STATE *state) if (aierr) msg_fatal("%s: cannot convert %s from string to binary: %s", myname, state->addr, MAI_STRERROR(aierr)); - sa_len = res0->ai_addrlen; - if (sa_len > sizeof(ss)) - sa_len = sizeof(ss); - memcpy((char *) sa, res0->ai_addr, sa_len); + sa_length = res0->ai_addrlen; + if (sa_length > sizeof(ss)) + sa_length = sizeof(ss); + memcpy((char *) sa, res0->ai_addr, sa_length); freeaddrinfo(res0); } @@ -195,7 +195,7 @@ void qmqpd_peer_init(QMQPD_STATE *state) state->name = mystrdup(CLIENT_NAME_UNKNOWN); \ } - if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name, + if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name, (MAI_SERVNAME_STR *) 0, 0)) != 0) { state->name = mystrdup(CLIENT_NAME_UNKNOWN); } else { diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index b38447207..00a4ed30b 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -15,7 +15,7 @@ TESTPROG= smtp_unalias smtp_map11 PROG = smtp INC_DIR = ../../include LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \ - ../../lib/libglobal.a ../../lib/libutil.a + ../../lib/libxsasl.a ../../lib/libglobal.a ../../lib/libutil.a .c.o:; $(CC) $(CFLAGS) -c $*.c @@ -38,7 +38,7 @@ update: ../../libexec/$(PROG) smtp.o: smtp.c smtp_params.c lmtp_params.c -lmtp_params.c: smtp_params.c $(INC_DIR)/mail_params.h +lmtp_params.c: smtp_params.c egrep -v -f smtp-only smtp_params.c | \ sed 's/SMTP/LMTP/g; s/smtp_\([a-z]*_table\)/lmtp_\1/' >$@ @@ -412,7 +412,6 @@ smtp_sasl_glue.o: ../../include/match_ops.h smtp_sasl_glue.o: ../../include/msg.h smtp_sasl_glue.o: ../../include/msg_stats.h smtp_sasl_glue.o: ../../include/mymalloc.h -smtp_sasl_glue.o: ../../include/name_mask.h smtp_sasl_glue.o: ../../include/recipient_list.h smtp_sasl_glue.o: ../../include/resolve_clnt.h smtp_sasl_glue.o: ../../include/scache.h @@ -425,6 +424,7 @@ smtp_sasl_glue.o: ../../include/tok822.h smtp_sasl_glue.o: ../../include/vbuf.h smtp_sasl_glue.o: ../../include/vstream.h smtp_sasl_glue.o: ../../include/vstring.h +smtp_sasl_glue.o: ../../include/xsasl.h smtp_sasl_glue.o: smtp.h smtp_sasl_glue.o: smtp_sasl.h smtp_sasl_glue.o: smtp_sasl_glue.c diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c index 39f201872..efb85e3e6 100644 --- a/postfix/src/smtp/lmtp_params.c +++ b/postfix/src/smtp/lmtp_params.c @@ -4,10 +4,12 @@ VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0, VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0, + VAR_LMTP_SASL_PATH, DEF_LMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0, #ifdef USE_TLS VAR_LMTP_SASL_TLS_OPTS, DEF_LMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0, #endif VAR_LMTP_SASL_MECHS, DEF_LMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0, + VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, VAR_LMTP_BIND_ADDR, DEF_LMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0, VAR_LMTP_BIND_ADDR6, DEF_LMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0, VAR_LMTP_HELO_NAME, DEF_LMTP_HELO_NAME, &var_smtp_helo_name, 1, 0, diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index ee1312b18..a2b862daa 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -39,16 +39,19 @@ /* .ad /* .fi /* SMTP destinations have the following form: -/* .IP "\fIdomainname\fR, \fIdomainname\fR:\fIport\fR" -/* Look up the mail exchangers for the specified domain. -/* .IP "[\fIhostname\fR], [\fIhostname\fR]:\fIport\fR" -/* Look up the address of the specified host. -/* .IP "[\fIaddress\fR], [\fIaddress\fR]:\fIport\fR" -/* Connect to the host at the specified address. An IPv6 -/* address must be formatted as [\fBipv6\fR:\fIaddress\fR]. -/* .PP -/* In all the above cases, when no port is specified, look up -/* the port defined as \fBsmtp\fR in \fBservices\fR(4). +/* .IP \fIdomainname\fR +/* .IP \fIdomainname\fR:\fIport\fR +/* Look up the mail exchangers for the specified domain, and +/* connect to the specified port (default: \fBsmtp\fR). +/* .IP [\fIhostname\fR] +/* .IP [\fIhostname\fR]:\fIport\fR +/* Look up the address(es) of the specified host, and connect to +/* the specified port (default: \fBsmtp\fR). +/* .IP [\fIaddress\fR] +/* .IP [\fIaddress\fR]:\fIport\fR +/* Connect to the host at the specified address, and connect +/* to the specified port (default: \fBsmtp\fR). An IPv6 address +/* must be formatted as [\fBipv6\fR:\fIaddress\fR]. /* LMTP DESTINATION SYNTAX /* .ad /* .fi @@ -57,13 +60,16 @@ /* Connect to the local UNIX-domain server that is bound to the specified /* \fIpathname\fR. If the process runs chrooted, an absolute pathname /* is interpreted relative to the Postfix queue directory. -/* .IP "\fBinet\fR:\fIhostname\fR, \fBinet\fB:\fIhostname\fR:\fIport\fR" -/* .IP "\fBinet\fR:[\fIaddress\fR], \fBinet\fR:[\fIaddress\fR]:\fIport\fR" +/* .IP \fBinet\fR:\fIhostname\fR +/* .IP \fBinet\fB:\fIhostname\fR:\fIport\fR +/* .IP \fBinet\fR:[\fIaddress\fR] +/* .IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR /* Connect to the specified TCP port on the specified local or /* remote host. If no port is specified, connect to the port defined as /* \fBlmtp\fR in \fBservices\fR(4). /* If no such service is found, the \fBlmtp_tcp_port\fR configuration /* parameter (default value of 24) will be used. +/* An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. /* .PP /* SECURITY /* .ad @@ -106,6 +112,12 @@ /* CONFIGURATION PARAMETERS /* .ad /* .fi +/* Before Postfix version 2.3, the LMTP client is a separate +/* program that implements only a subset of the functionality +/* available with SMTP: there is no support for TLS, and +/* connections are cached in-process, making it ineffective +/* when the client is used for multiple domains. +/* /* Most smtp_\fIxxx\fR configuration parameters have an /* lmtp_\fIxxx\fR "ghost" parameter for the equivalent LMTP /* feature. This document describes only those LMTP-related @@ -205,8 +217,9 @@ /* per remote hostname or domain, or sender address when sender-dependent /* authentication is enabled. /* .IP "\fBsmtp_sasl_security_options (noplaintext, noanonymous)\fR" -/* What authentication mechanisms the Postfix SMTP client is allowed -/* to use. +/* SASL security options; as of Postfix 2.3 the list of available +/* features depends on the SASL client implementation that is selected +/* with \fBsmtp_sasl_type\fR. /* .PP /* Available in Postfix version 2.2 and later: /* .IP "\fBsmtp_sasl_mechanism_filter (empty)\fR" @@ -219,6 +232,13 @@ /* available only with SASL authentication, and disables SMTP connection /* caching to ensure that mail from different senders will use the /* appropriate credentials. +/* .IP "\fBsmtp_sasl_path (empty)\fR" +/* Implementation-specific information that is passed through to +/* the SASL plug-in implementation that is selected with +/* \fBsmtp_sasl_type\fR. +/* .IP "\fBsmtp_sasl_type (cyrus)\fR" +/* The SASL plug-in type that the Postfix SMTP client should use +/* for authentication. /* STARTTLS SUPPORT CONTROLS /* .ad /* .fi @@ -328,6 +348,11 @@ /* The SMTP client time limit for sending the RSET command, and /* for receiving the server response. /* .PP +/* Available in Postfix version 2.2 and earlier: +/* .IP "\fBlmtp_cache_connection (yes)\fR" +/* Keep Postfix LMTP client connections open for up to $max_idle +/* seconds. +/* .PP /* Available in Postfix version 2.2 and later: /* .IP "\fBsmtp_connection_cache_destinations (empty)\fR" /* Permanently enable SMTP connection caching for the specified @@ -548,9 +573,11 @@ char *var_error_rcpt; int var_smtp_always_ehlo; int var_smtp_never_ehlo; char *var_smtp_sasl_opts; +char *var_smtp_sasl_path; char *var_smtp_sasl_passwd; bool var_smtp_sasl_enable; char *var_smtp_sasl_mechs; +char *var_smtp_sasl_type; char *var_smtp_bind_addr; char *var_smtp_bind_addr6; bool var_smtp_rand_addr; @@ -799,16 +826,6 @@ static void pre_accept(char *unused_name, char **unused_argv) } } -/* pre_exit - pre-exit cleanup */ - -static void pre_exit(void) -{ -#ifdef USE_SASL_AUTH - if (var_smtp_sasl_enable) - sasl_done(); -#endif -} - /* main - pass control to the single-threaded skeleton */ int main(int argc, char **argv) @@ -837,6 +854,5 @@ int main(int argc, char **argv) MAIL_SERVER_PRE_INIT, pre_init, MAIL_SERVER_POST_INIT, post_init, MAIL_SERVER_PRE_ACCEPT, pre_accept, - MAIL_SERVER_EXIT, pre_exit, 0); } diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 2c9b785e3..9e4e5c8ed 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -8,14 +8,6 @@ /* DESCRIPTION /* .nf - /* - * SASL library. - */ -#ifdef USE_SASL_AUTH -#include -#include -#endif - /* * Utility library. */ @@ -208,10 +200,8 @@ typedef struct SMTP_SESSION { char *sasl_mechanism_list; /* server mechanism list */ char *sasl_username; /* client username */ char *sasl_passwd; /* client password */ - sasl_conn_t *sasl_conn; /* SASL internal state */ - VSTRING *sasl_encoded; /* encoding buffer */ - VSTRING *sasl_decoded; /* decoding buffer */ - sasl_callback_t *sasl_callbacks; /* stateful callbacks */ + struct XSASL_CLIENT *sasl_client; /* SASL internal state */ + VSTRING *sasl_reply; /* client response */ #endif /* @@ -433,6 +423,7 @@ extern void smtp_dsn_formal(DSN_BUF *, const char *, const char *, int, * Silly little macros. */ #define STR(s) vstring_str(s) +#define LEN(s) VSTRING_LEN(s) /* LICENSE /* .ad diff --git a/postfix/src/smtp/smtp_chat.c b/postfix/src/smtp/smtp_chat.c index 61f7a389e..6008b2d0b 100644 --- a/postfix/src/smtp/smtp_chat.c +++ b/postfix/src/smtp/smtp_chat.c @@ -133,8 +133,6 @@ #include "smtp.h" -#define LEN VSTRING_LEN - /* smtp_chat_init - initialize SMTP transaction log */ void smtp_chat_init(SMTP_SESSION *session) @@ -288,7 +286,9 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session) */ session->error_mask |= MAIL_ERROR_PROTOCOL; if (session->features & SMTP_FEATURE_PIPELINING) { - msg_warn("non-SMTP response from %s: %s", + msg_warn("non-%s response from %s: %s", + (session->state->misc_flags & + SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP", session->namaddr, STR(session->buffer)); vstream_longjmp(session->stream, SMTP_ERR_PROTO); } @@ -391,8 +391,11 @@ void smtp_chat_notify(SMTP_SESSION *session) post_mail_fprintf(notice, "From: %s (Mail Delivery System)", mail_addr_mail_daemon()); post_mail_fprintf(notice, "To: %s (Postmaster)", var_error_rcpt); - post_mail_fprintf(notice, "Subject: %s SMTP client: errors from %s", - var_mail_name, session->namaddr); + post_mail_fprintf(notice, "Subject: %s %s client: errors from %s", + var_mail_name, + (session->state->misc_flags & + SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "SMTP", + session->namaddr); post_mail_fputs(notice, ""); post_mail_fprintf(notice, "Unexpected response from %s.", session->namaddr); post_mail_fputs(notice, ""); diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index a3b79866b..6e883116d 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -342,7 +342,8 @@ static SMTP_SESSION *smtp_connect_sock(int sock, struct sockaddr * sa, if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) { smtp_dsn_update(why, DSN_BY_LOCAL_MTA, "4.4.0", 421, "421 Lost connection", - "connect to %s[%s]: server dropped connection without sending the initial SMTP greeting", + "connect to %s[%s]: server dropped connection" + " without sending the initial greeting", addr->name, hostaddr.buf); smtp_errno = SMTP_ERR_RETRY; vstream_fclose(stream); @@ -378,7 +379,7 @@ static char *smtp_parse_destination(char *destination, char *def_service, * destination argument so the parsing can be destructive. */ if ((err = host_port(buf, hostp, (char *) 0, &service, def_service)) != 0) - msg_fatal("%s in SMTP server description: %s", err, destination); + msg_fatal("%s in server description: %s", err, destination); /* * Convert service to port number, network byte order. diff --git a/postfix/src/smtp/smtp_map11.c b/postfix/src/smtp/smtp_map11.c index 8c42db373..297dee8a0 100644 --- a/postfix/src/smtp/smtp_map11.c +++ b/postfix/src/smtp/smtp_map11.c @@ -55,10 +55,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c index 021229c43..f3a1494b1 100644 --- a/postfix/src/smtp/smtp_params.c +++ b/postfix/src/smtp/smtp_params.c @@ -5,10 +5,12 @@ VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0, VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0, + VAR_SMTP_SASL_PATH, DEF_SMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0, #ifdef USE_TLS VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0, #endif VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0, + VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0, VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0, VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0, diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index bb92a2000..5fbe78d73 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -490,7 +490,9 @@ int smtp_helo(SMTP_STATE *state) msg_fatal("%s: setsockopt: %m", myname); } if (msg_verbose) - msg_info("Using ESMTP PIPELINING, TCP send buffer size is %d", + msg_info("Using %s PIPELINING, TCP send buffer size is %d", + (state->misc_flags & + SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP", session->sndbufsize); } else { session->sndbufsize = 0; @@ -597,8 +599,18 @@ int smtp_helo(SMTP_STATE *state) } #endif #ifdef USE_SASL_AUTH - if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH)) - return (smtp_sasl_helo_login(state)); + if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH)) { + if (session->sasl_mechanism_list != 0) + return (smtp_sasl_helo_login(state)); + else + return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, + SMTP_RESP_FAKE(&fake, 421, "4.7.0", + "421 SASL authentication failed: " + "server offered no compatible authentication mechanisms"), + "SASL authentication failed: " + "server %s offered no compatible authentication mechanisms", + session->namaddr)); + } #endif return (0); diff --git a/postfix/src/smtp/smtp_sasl_glue.c b/postfix/src/smtp/smtp_sasl_glue.c index 8e78942d2..b08ed135c 100644 --- a/postfix/src/smtp/smtp_sasl_glue.c +++ b/postfix/src/smtp/smtp_sasl_glue.c @@ -1,6 +1,6 @@ /*++ /* NAME -/* smtp_sasl 3 +/* smtp_sasl_glue 3 /* SUMMARY /* Postfix SASL interface for SMTP client /* SYNOPSIS @@ -54,7 +54,7 @@ /* case of unsuccessful authentication, > 0 in case of success. /* The why argument is updated with a reason for failure. /* This routine must be called only when smtp_sasl_passwd_lookup() -/* suceeds. +/* succeeds. /* /* smtp_sasl_cleanup() cleans up. It must be called at the /* end of every SMTP session that uses SASL authentication. @@ -97,9 +97,6 @@ #include #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif /* * Utility library @@ -108,7 +105,6 @@ #include #include #include -#include /* * Global library @@ -118,6 +114,11 @@ #include #include + /* + * XSASL library. + */ +#include + /* * Application-specific */ @@ -126,59 +127,6 @@ #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, -#if SASL_VERSION_MAJOR >= 2 - "mutual_auth", SASL_SEC_MUTUAL_AUTH, -#endif - 0, -}; - - /* - * 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_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. */ @@ -189,119 +137,10 @@ static MAPS *smtp_sasl_passwd_map; */ STRING_LIST *smtp_sasl_mechs; -/* smtp_sasl_log - logging call-back routine */ - -static int smtp_sasl_log(void *unused_context, int priority, - const char *message) -{ - switch (priority) { - case SASL_LOG_ERR: /* unusual errors */ -#ifdef SASL_LOG_WARN /* non-fatal warnings (Cyrus-SASL v2) */ - case SASL_LOG_WARN: -#endif -#ifdef SASL_LOG_WARNING /* non-fatal warnings (Cyrus-SASL v1) */ - case SASL_LOG_WARNING: -#endif - msg_warn("SASL authentication problem: %s", message); - break; -#ifdef SASL_LOG_INFO - case SASL_LOG_INFO: /* other info (Cyrus-SASL v1) */ - if (msg_verbose) - msg_info("SASL authentication info: %s", message); - break; -#endif -#ifdef SASL_LOG_NOTE - case SASL_LOG_NOTE: /* other info (Cyrus-SASL v2) */ - if (msg_verbose) - msg_info("SASL authentication info: %s", message); - break; -#endif -#ifdef SASL_LOG_FAIL - case SASL_LOG_FAIL: /* authentication failures - * (Cyrus-SASL v2) */ - msg_warn("SASL authentication failure: %s", message); - break; -#endif -#ifdef SASL_LOG_DEBUG - case SASL_LOG_DEBUG: /* more verbose than LOG_NOTE - * (Cyrus-SASL v2) */ - if (msg_verbose > 1) - msg_info("SASL authentication debug: %s", message); - break; -#endif -#ifdef SASL_LOG_TRACE - case SASL_LOG_TRACE: /* traces of internal - * protocols (Cyrus-SASL v2) */ - if (msg_verbose > 1) - msg_info("SASL authentication trace: %s", message); - break; -#endif -#ifdef SASL_LOG_PASS - case SASL_LOG_PASS: /* traces of internal - * protocols, including - * passwords (Cyrus-SASL v2) */ - if (msg_verbose > 1) - msg_info("SASL authentication pass: %s", message); - break; -#endif - } - return (SASL_OK); -} - -/* smtp_sasl_get_user - username lookup call-back routine */ - -static int smtp_sasl_get_user(void *context, int unused_id, const char **result, - unsigned *len) -{ - char *myname = "smtp_sasl_get_user"; - SMTP_SESSION *session = (SMTP_SESSION *) context; - - if (msg_verbose) - msg_info("%s: %s", myname, session->sasl_username); - - /* - * Sanity check. - */ - if (session->sasl_passwd == 0) - msg_panic("%s: no username looked up", myname); - - *result = session->sasl_username; - if (len) - *len = strlen(session->sasl_username); - return (SASL_OK); -} - -/* smtp_sasl_get_passwd - password lookup call-back routine */ - -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_SESSION *session = (SMTP_SESSION *) context; - int len; - - if (msg_verbose) - msg_info("%s: %s", myname, session->sasl_passwd); - - /* - * Sanity check. - */ - if (!conn || !psecret || id != SASL_CB_PASS) - return (SASL_BADPARAM); - if (session->sasl_passwd == 0) - msg_panic("%s: no password looked up", myname); - - /* - * Convert the password into a counted string. - */ - len = strlen(session->sasl_passwd); - if ((*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len)) == 0) - return (SASL_NOMEM); - (*psecret)->len = len; - memcpy((*psecret)->data, session->sasl_passwd, len + 1); - - return (SASL_OK); -} + /* + * SASL implementation handle. + */ +static XSASL_CLIENT_IMPL *smtp_sasl_impl; /* smtp_sasl_passwd_lookup - password lookup routine */ @@ -358,43 +197,10 @@ int smtp_sasl_passwd_lookup(SMTP_SESSION *session) void smtp_sasl_initialize(void) { - /* - * Global callbacks. These have no per-session context. - */ - static sasl_callback_t callbacks[] = { - {SASL_CB_LOG, &smtp_sasl_log, 0}, - {SASL_CB_LIST_END, 0, 0} - }; - -#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \ - || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19)) - int sasl_major; - int sasl_minor; - int sasl_step; - - /* - * DLL hell guard. - */ - sasl_version_info((const char **) 0, (const char **) 0, - &sasl_major, &sasl_minor, - &sasl_step, (int *) 0); - if (sasl_major != SASL_VERSION_MAJOR -#if 0 - || sasl_minor != SASL_VERSION_MINOR - || sasl_step != SASL_VERSION_STEP -#endif - ) - msg_fatal("incorrect SASL library version. " - "Postfix was built with include files from version %d.%d.%d, " - "but the run-time library version is %d.%d.%d", - SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP, - sasl_major, sasl_minor, sasl_step); -#endif - /* * Sanity check. */ - if (smtp_sasl_passwd_map) + if (smtp_sasl_passwd_map || smtp_sasl_impl) msg_panic("smtp_sasl_initialize: repeated call"); if (*var_smtp_sasl_passwd == 0) msg_fatal("specify a password table via the `%s' configuration parameter", @@ -406,7 +212,8 @@ void smtp_sasl_initialize(void) */ smtp_sasl_passwd_map = maps_create("smtp_sasl_passwd", var_smtp_sasl_passwd, DICT_FLAG_LOCK); - if (sasl_client_init(callbacks) != SASL_OK) + if ((smtp_sasl_impl = xsasl_client_init(var_smtp_sasl_type, + var_smtp_sasl_path)) == 0) msg_fatal("SASL library initialization"); /* @@ -421,13 +228,16 @@ void smtp_sasl_initialize(void) void smtp_sasl_connect(SMTP_SESSION *session) { + + /* + * This initialization happens whenever we instantiate an SMTP session + * object. We don't instantiate a SASL client until we actually need one. + */ session->sasl_mechanism_list = 0; session->sasl_username = 0; session->sasl_passwd = 0; - session->sasl_conn = 0; - session->sasl_encoded = 0; - session->sasl_decoded = 0; - session->sasl_callbacks = 0; + session->sasl_client = 0; + session->sasl_reply = 0; } /* smtp_sasl_start - per-session SASL initialization */ @@ -435,62 +245,13 @@ void smtp_sasl_connect(SMTP_SESSION *session) void smtp_sasl_start(SMTP_SESSION *session, const char *sasl_opts_name, const char *sasl_opts_val) { - static sasl_callback_t callbacks[] = { - {SASL_CB_USER, &smtp_sasl_get_user, 0}, - {SASL_CB_AUTHNAME, &smtp_sasl_get_user, 0}, - {SASL_CB_PASS, &smtp_sasl_get_passwd, 0}, - {SASL_CB_LIST_END, 0, 0} - }; - sasl_callback_t *cp; - sasl_security_properties_t sec_props; - if (msg_verbose) msg_info("starting new SASL client"); - - /* - * Per-session initialization. Provide each session with its own callback - * context. - */ -#define NULL_SECFLAGS 0 - - session->sasl_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks)); - memcpy((char *) session->sasl_callbacks, callbacks, sizeof(callbacks)); - for (cp = session->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++) - cp->context = (void *) session; - -#define NULL_SERVER_ADDR ((char *) 0) -#define NULL_CLIENT_ADDR ((char *) 0) - - if (SASL_CLIENT_NEW(var_procname, session->host, - NULL_CLIENT_ADDR, NULL_SERVER_ADDR, - session->sasl_callbacks, NULL_SECFLAGS, - (sasl_conn_t **) &session->sasl_conn) != SASL_OK) - msg_fatal("per-session SASL client initialization"); - - /* - * Per-session security properties. XXX This routine is not sufficiently - * documented. What is the purpose of all this? - */ - memset(&sec_props, 0L, sizeof(sec_props)); - sec_props.min_ssf = 0; - sec_props.max_ssf = 0; /* don't allow real SASL - * security layer */ - sec_props.security_flags = name_mask(sasl_opts_name, smtp_sasl_sec_mask, - sasl_opts_val); - sec_props.maxbufsize = 0; - sec_props.property_names = 0; - sec_props.property_values = 0; - if (sasl_setprop(session->sasl_conn, SASL_SEC_PROPS, - &sec_props) != SASL_OK) - msg_fatal("set per-session SASL security properties"); - - /* - * We use long-lived conversion buffers rather than local variables in - * order to avoid memory leaks in case of read/write timeout or I/O - * error. - */ - session->sasl_encoded = vstring_alloc(10); - session->sasl_decoded = vstring_alloc(10); + if ((session->sasl_client = + xsasl_client_create(smtp_sasl_impl, session->stream, var_procname, + session->host, sasl_opts_val)) == 0) + msg_fatal("SASL per-connection initialization failed"); + session->sasl_reply = vstring_alloc(20); } /* smtp_sasl_authenticate - run authentication protocol */ @@ -498,27 +259,16 @@ void smtp_sasl_start(SMTP_SESSION *session, const char *sasl_opts_name, int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) { 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; const char *mechanism; int result; char *line; -#define NO_SASL_SECRET 0 -#define NO_SASL_INTERACTION 0 -#define NO_SASL_LANGLIST ((const char *) 0) -#define NO_SASL_OUTLANG ((const char **) 0) + /* + * Sanity check. + */ + if (session->sasl_mechanism_list == 0) + msg_panic("%s: no mechanism list", myname); if (msg_verbose) msg_info("%s: %s: SASL mechanisms %s", @@ -527,18 +277,16 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) /* * Start the client side authentication protocol. */ - result = SASL_CLIENT_START((sasl_conn_t *) session->sasl_conn, - session->sasl_mechanism_list, - NO_SASL_SECRET, NO_SASL_INTERACTION, - &clientout, &clientoutlen, &mechanism); - if (result != SASL_OK && result != SASL_CONTINUE) { + result = xsasl_client_first(session->sasl_client, + session->sasl_mechanism_list, + session->sasl_username, + session->sasl_passwd, + &mechanism, session->sasl_reply); + if (result != XSASL_AUTH_OK) { dsb_update(why, "4.7.0", DSB_DEF_ACTION, DSB_SKIP_RMTA, DSB_DTYPE_SASL, - 421, sasl_errstring(result, NO_SASL_LANGLIST, - NO_SASL_OUTLANG), + 421, STR(session->sasl_reply), "cannot authenticate to server %s: %s", - session->namaddr, - sasl_errstring(result, NO_SASL_LANGLIST, - NO_SASL_OUTLANG)); + session->namaddr, STR(session->sasl_reply)); return (-1); } @@ -547,24 +295,9 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) * sasl_encode64() produces four bytes for each complete or incomplete * triple of input bytes. Allocate an extra byte for string termination. */ -#define ENCODE64_LENGTH(n) ((((n) + 2) / 3) * 4) - - if (clientoutlen > 0) { - if (msg_verbose) - msg_info("%s: %s: uncoded initial reply: %.*s", - myname, session->namaddr, (int) clientoutlen, clientout); - enc_length = ENCODE64_LENGTH(clientoutlen) + 1; - VSTRING_SPACE(session->sasl_encoded, enc_length); - if (sasl_encode64(clientout, clientoutlen, - STR(session->sasl_encoded), enc_length, - &enc_length_out) != SASL_OK) - msg_panic("%s: sasl_encode64 botch", myname); -#if SASL_VERSION_MAJOR < 2 - /* SASL version 1 doesn't free memory that it allocates. */ - free(clientout); -#endif + if (LEN(session->sasl_reply) > 0) { smtp_chat_cmd(session, "AUTH %s %s", mechanism, - STR(session->sasl_encoded)); + STR(session->sasl_reply)); } else { smtp_chat_cmd(session, "AUTH %s", mechanism); } @@ -580,50 +313,21 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) */ line = resp->str; (void) mystrtok(&line, "- \t\n"); /* skip over result code */ - serverinlen = strlen(line); - VSTRING_SPACE(session->sasl_decoded, serverinlen); - if (SASL_DECODE64(line, serverinlen, STR(session->sasl_decoded), - serverinlen, &enc_length) != SASL_OK) { - smtp_dsn_update(why, "5.7.0", DSN_BY_LOCAL_MTA, - 501, "501 malformed SASL challenge", - "malformed SASL challenge from server %s", - session->namaddr); - return (-1); + result = xsasl_client_next(session->sasl_client, line, + session->sasl_reply); + if (result != XSASL_AUTH_OK) { + dsb_update(why, "4.7.0", DSB_DEF_ACTION, /* Fix 200512 */ + DSB_SKIP_RMTA, DSB_DTYPE_SASL, + 421, STR(session->sasl_reply), + "cannot authenticate to server %s: %s", + session->namaddr, STR(session->sasl_reply)); + return (-1); /* Fix 200512 */ } - if (msg_verbose) - msg_info("%s: %s: decoded challenge: %.*s", - myname, session->namaddr, (int) enc_length, - STR(session->sasl_decoded)); - result = sasl_client_step((sasl_conn_t *) session->sasl_conn, - STR(session->sasl_decoded), enc_length, - NO_SASL_INTERACTION, &clientout, &clientoutlen); - if (result != SASL_OK && result != SASL_CONTINUE) - msg_warn("SASL authentication failed to server %s: %s", - session->namaddr, sasl_errstring(result, NO_SASL_LANGLIST, - NO_SASL_OUTLANG)); /* * Send a client response. */ - if (clientoutlen > 0) { - if (msg_verbose) - msg_info("%s: %s: uncoded client response %.*s", - myname, session->namaddr, - (int) clientoutlen, clientout); - enc_length = ENCODE64_LENGTH(clientoutlen) + 1; - VSTRING_SPACE(session->sasl_encoded, enc_length); - if (sasl_encode64(clientout, clientoutlen, - STR(session->sasl_encoded), enc_length, - &enc_length_out) != SASL_OK) - msg_panic("%s: sasl_encode64 botch", myname); -#if SASL_VERSION_MAJOR < 2 - /* SASL version 1 doesn't free memory that it allocates. */ - free(clientout); -#endif - } else { - vstring_strcat(session->sasl_encoded, ""); - } - smtp_chat_cmd(session, "%s", STR(session->sasl_encoded)); + smtp_chat_cmd(session, "%s", STR(session->sasl_reply)); } /* @@ -655,22 +359,15 @@ void smtp_sasl_cleanup(SMTP_SESSION *session) myfree(session->sasl_mechanism_list); session->sasl_mechanism_list = 0; } - if (session->sasl_conn) { + if (session->sasl_client) { if (msg_verbose) msg_info("disposing SASL state information"); - sasl_dispose(&session->sasl_conn); - } - if (session->sasl_callbacks) { - myfree((char *) session->sasl_callbacks); - session->sasl_callbacks = 0; - } - if (session->sasl_encoded) { - vstring_free(session->sasl_encoded); - session->sasl_encoded = 0; + xsasl_client_free(session->sasl_client); + session->sasl_client = 0; } - if (session->sasl_decoded) { - vstring_free(session->sasl_decoded); - session->sasl_decoded = 0; + if (session->sasl_reply) { + vstring_free(session->sasl_reply); + session->sasl_reply = 0; } } diff --git a/postfix/src/smtp/smtp_sasl_proto.c b/postfix/src/smtp/smtp_sasl_proto.c index 153b041a5..699f163d2 100644 --- a/postfix/src/smtp/smtp_sasl_proto.c +++ b/postfix/src/smtp/smtp_sasl_proto.c @@ -136,12 +136,12 @@ void smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words) } if (strlen(mech_list) > 0) { session->sasl_mechanism_list = mystrdup(mech_list); - session->features |= SMTP_FEATURE_AUTH; } else { msg_warn(*words ? "%s offered no supported AUTH mechanisms: '%s'" : "%s offered null AUTH mechanism list", session->namaddr, words); } + session->features |= SMTP_FEATURE_AUTH; } /* smtp_sasl_helo_login - perform SASL login */ diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 6b42681f9..da78675d0 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -14,7 +14,7 @@ TESTPROG= smtpd_token smtpd_check PROG = smtpd INC_DIR = ../../include LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \ - ../../lib/libglobal.a ../../lib/libutil.a + ../../lib/libxsasl.a ../../lib/libglobal.a ../../lib/libutil.a .c.o:; $(CC) $(CFLAGS) -c $*.c @@ -321,20 +321,16 @@ smtpd_proxy.o: smtpd_proxy.h smtpd_sasl_glue.o: ../../include/argv.h smtpd_sasl_glue.o: ../../include/mail_params.h smtpd_sasl_glue.o: ../../include/mail_stream.h -smtpd_sasl_glue.o: ../../include/match_list.h -smtpd_sasl_glue.o: ../../include/match_ops.h smtpd_sasl_glue.o: ../../include/msg.h smtpd_sasl_glue.o: ../../include/myaddrinfo.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/smtp_stream.h smtpd_sasl_glue.o: ../../include/stringops.h smtpd_sasl_glue.o: ../../include/sys_defs.h smtpd_sasl_glue.o: ../../include/tls.h smtpd_sasl_glue.o: ../../include/vbuf.h smtpd_sasl_glue.o: ../../include/vstream.h smtpd_sasl_glue.o: ../../include/vstring.h +smtpd_sasl_glue.o: ../../include/xsasl.h smtpd_sasl_glue.o: smtpd.h smtpd_sasl_glue.o: smtpd_chat.h smtpd_sasl_glue.o: smtpd_sasl_glue.c diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 6cdeb3a8b..f0c37f90d 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -174,13 +174,12 @@ /* version of the AUTH command (RFC 2554). /* .IP "\fBsmtpd_sasl_auth_enable (no)\fR" /* Enable SASL authentication in the Postfix SMTP server. -/* .IP "\fBsmtpd_sasl_application_name (smtpd)\fR" -/* The application name used for SASL server initialization. /* .IP "\fBsmtpd_sasl_local_domain (empty)\fR" /* The name of the local SASL authentication realm. /* .IP "\fBsmtpd_sasl_security_options (noanonymous)\fR" -/* Restrict what authentication mechanisms the Postfix SMTP server -/* will offer to the client. +/* SASL security options; as of Postfix 2.3 the list of available +/* features depends on the SASL server implementation that is selected +/* with \fBsmtpd_sasl_type\fR. /* .IP "\fBsmtpd_sender_login_maps (empty)\fR" /* Optional lookup table with the SASL login names that own sender /* (MAIL FROM) addresses. @@ -193,6 +192,13 @@ /* .IP "\fBsmtpd_sasl_authenticated_header (no)\fR" /* Report the SASL authenticated user name in the \fBsmtpd\fR(8) Received /* message header. +/* .IP "\fBsmtpd_sasl_path (smtpd)\fR" +/* Implementation-specific information that is passed through to +/* the SASL plug-in implementation that is selected with +/* \fBsmtpd_sasl_type\fR. +/* .IP "\fBsmtpd_sasl_type (cyrus)\fR" +/* The SASL plug-in type that the Postfix SMTP server should use +/* for authentication. /* STARTTLS SUPPORT CONTROLS /* .ad /* .fi @@ -605,6 +611,9 @@ /* The numerical Postfix SMTP server reply code when a client request /* is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender /* or reject_non_fqdn_recipient restriction. +/* .IP "\fBplaintext_reject_code (450)\fR" +/* The numerical Postfix SMTP server response code when a request +/* is rejected by the \fBreject_plaintext_session\fR restriction. /* .IP "\fBreject_code (554)\fR" /* The numerical Postfix SMTP server response code when a remote SMTP /* client request is rejected by the "reject" restriction. @@ -881,9 +890,10 @@ int var_smtpd_rcpt_overlim; bool var_smtpd_sasl_enable; bool var_smtpd_sasl_auth_hdr; char *var_smtpd_sasl_opts; -char *var_smtpd_sasl_appname; +char *var_smtpd_sasl_path; char *var_smtpd_sasl_realm; char *var_smtpd_sasl_exceptions_networks; +char *var_smtpd_sasl_type; char *var_filter_xport; bool var_broken_auth_clients; char *var_perm_mx_networks; @@ -945,6 +955,7 @@ char *var_smtpd_sasl_tls_opts; #endif bool var_smtpd_peername_lookup; +int var_plaintext_code; /* * Silly little macros. @@ -3705,6 +3716,7 @@ int main(int argc, char **argv) VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, 0, 0, VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0, VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0, + VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0, VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0, VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0, VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0, @@ -3774,7 +3786,7 @@ int main(int argc, char **argv) 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, - VAR_SMTPD_SASL_APPNAME, DEF_SMTPD_SASL_APPNAME, &var_smtpd_sasl_appname, 1, 0, + VAR_SMTPD_SASL_PATH, DEF_SMTPD_SASL_PATH, &var_smtpd_sasl_path, 1, 0, VAR_SMTPD_SASL_REALM, DEF_SMTPD_SASL_REALM, &var_smtpd_sasl_realm, 0, 0, VAR_SMTPD_SASL_EXCEPTIONS_NETWORKS, DEF_SMTPD_SASL_EXCEPTIONS_NETWORKS, &var_smtpd_sasl_exceptions_networks, 0, 0, VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, @@ -3799,6 +3811,7 @@ int main(int argc, char **argv) VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 0, 0, VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0, #endif + VAR_SMTPD_SASL_TYPE, DEF_SMTPD_SASL_TYPE, &var_smtpd_sasl_type, 1, 0, 0, }; static CONFIG_RAW_TABLE raw_table[] = { diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index cb061f416..f1d9af340 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -14,14 +14,6 @@ #include #include - /* - * SASL library. - */ -#ifdef USE_SASL_AUTH -#include -#include -#endif - /* * Utility library. */ @@ -112,17 +104,12 @@ typedef struct SMTPD_STATE { * SASL specific. */ #ifdef USE_SASL_AUTH -#if SASL_VERSION_MAJOR >= 2 - const char *sasl_mechanism_list; -#else + struct XSASL_SERVER *sasl_server; + VSTRING *sasl_reply; char *sasl_mechanism_list; -#endif char *sasl_method; char *sasl_username; char *sasl_sender; - sasl_conn_t *sasl_conn; - VSTRING *sasl_encoded; - VSTRING *sasl_decoded; #endif /* diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 86e2c4df0..5c4b07a19 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -952,6 +952,24 @@ static int reject_unknown_client(SMTPD_STATE *state) return (SMTPD_CHECK_DUNNO); } +/* reject_plaintext_session - fail if session is not encrypted */ + +static int reject_plaintext_session(SMTPD_STATE *state) +{ +#ifdef USE_TLS + char *myname = "reject_plaintext_session"; + + if (msg_verbose) + msg_info("%s: %s %s", myname, state->name, state->addr); + + if (state->tls_context == 0) + return (smtpd_check_reject(state, MAIL_ERROR_POLICY, + var_plaintext_code, "4.7.1", + "Session encryption is required")); +#endif + return (SMTPD_CHECK_DUNNO); +} + /* permit_inet_interfaces - succeed if client my own address */ static int permit_inet_interfaces(SMTPD_STATE *state) @@ -3283,6 +3301,13 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, IF_VERIFIED(state->tls_context->issuer_CN), ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT, IF_VERIFIED(state->tls_context->peer_fingerprint), +#define IF_ENCRYPTED(x) ((state->tls_context && ((x) != 0)) ? (x) : "") + ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_PROTOCOL, + IF_ENCRYPTED(state->tls_context->protocol), + ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_CYPHER, + IF_ENCRYPTED(state->tls_context->cipher_name), + ATTR_TYPE_NUM, MAIL_ATTR_CRYPTO_KEYSIZE, + state->tls_context->cipher_usebits, #endif ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ @@ -3456,6 +3481,10 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, "Server configuration error")); } else sleep(atoi(*++cpp)); +#endif +#ifdef USE_TLS + } else if (strcasecmp(name, REJECT_PLAINTEXT_SESSION) == 0) { + status = reject_plaintext_session(state); #endif } diff --git a/postfix/src/smtpd/smtpd_peer.c b/postfix/src/smtpd/smtpd_peer.c index 034f9cefe..7d46f3285 100644 --- a/postfix/src/smtpd/smtpd_peer.c +++ b/postfix/src/smtpd/smtpd_peer.c @@ -129,17 +129,17 @@ void smtpd_peer_init(SMTPD_STATE *state) { char *myname = "smtpd_peer_init"; - SOCKADDR_SIZE sa_len; + SOCKADDR_SIZE sa_length; struct sockaddr *sa; INET_PROTO_INFO *proto_info = inet_proto_info(); sa = (struct sockaddr *) & (state->sockaddr); - sa_len = sizeof(state->sockaddr); + sa_length = sizeof(state->sockaddr); /* * Look up the peer address information. */ - if (getpeername(vstream_fileno(state->client), sa, &sa_len) >= 0) { + if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) { errno = 0; } @@ -179,7 +179,7 @@ void smtpd_peer_init(SMTPD_STATE *state) /* * Convert the client address to printable form. */ - if ((aierr = sockaddr_to_hostaddr(sa, sa_len, &client_addr, + if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr, (MAI_SERVPORT_STR *) 0, 0)) != 0) msg_fatal("%s: cannot convert client address to string: %s", myname, MAI_STRERROR(aierr)); @@ -207,10 +207,10 @@ void smtpd_peer_init(SMTPD_STATE *state) if (aierr) msg_fatal("%s: cannot convert %s from string to binary: %s", myname, state->addr, MAI_STRERROR(aierr)); - sa_len = res0->ai_addrlen; - if (sa_len > sizeof(state->sockaddr)) - sa_len = sizeof(state->sockaddr); - memcpy((char *) sa, res0->ai_addr, sa_len); + sa_length = res0->ai_addrlen; + if (sa_length > sizeof(state->sockaddr)) + sa_length = sizeof(state->sockaddr); + memcpy((char *) sa, res0->ai_addr, sa_length); freeaddrinfo(res0); /* 200412 */ } @@ -262,7 +262,7 @@ void smtpd_peer_init(SMTPD_STATE *state) state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN); state->name_status = SMTPD_PEER_CODE_PERM; state->reverse_name_status = SMTPD_PEER_CODE_PERM; - } else if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name, + } else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name, (MAI_SERVNAME_STR *) 0, 0)) != 0) { state->name = mystrdup(CLIENT_NAME_UNKNOWN); state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN); diff --git a/postfix/src/smtpd/smtpd_proxy.c b/postfix/src/smtpd/smtpd_proxy.c index 0bae676d9..2cb7ca853 100644 --- a/postfix/src/smtpd/smtpd_proxy.c +++ b/postfix/src/smtpd/smtpd_proxy.c @@ -140,6 +140,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include diff --git a/postfix/src/smtpd/smtpd_sasl_glue.c b/postfix/src/smtpd/smtpd_sasl_glue.c index 10cfd3712..76f5bb9f1 100644 --- a/postfix/src/smtpd/smtpd_sasl_glue.c +++ b/postfix/src/smtpd/smtpd_sasl_glue.c @@ -6,10 +6,12 @@ /* SYNOPSIS /* #include "smtpd_sasl_glue.h" /* -/* void smtpd_sasl_initialize() +/* void smtpd_sasl_initialize() /* /* void smtpd_sasl_connect(state, sasl_opts_name, sasl_opts_val) /* SMTPD_STATE *state; +/* const char *sasl_opts_name; +/* const char *sasl_opts_val; /* /* char *smtpd_sasl_authenticate(state, sasl_method, init_response) /* SMTPD_STATE *state; @@ -36,10 +38,10 @@ /* are the postfix configuration parameters setting the security /* policy of the SASL authentication. /* -/* smtpd_sasl_authenticate() implements the authentication dialog. -/* The result is a null pointer in case of success, an SMTP reply -/* in case of failure. smtpd_sasl_authenticate() updates the -/* following state structure members: +/* smtpd_sasl_authenticate() implements the authentication +/* dialog. The result is zero in case of success, -1 in case +/* of failure. smtpd_sasl_authenticate() updates the following +/* state structure members: /* .IP sasl_method /* The authentication method that was successfully applied. /* This member is a null pointer in the absence of successful @@ -58,6 +60,10 @@ /* Arguments: /* .IP state /* SMTP session context. +/* .IP sasl_opts_name +/* Security options parameter name. +/* .IP sasl_opts_val +/* Security options parameter value. /* .IP sasl_method /* A SASL mechanism name /* .IP init_reply @@ -91,14 +97,15 @@ #include #include -#include -#include #include /* Global library. */ #include -#include + +/* XSASL library. */ + +#include /* Application-specific. */ @@ -114,166 +121,26 @@ #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. + * SASL server implementation handle. */ - -#if SASL_VERSION_MAJOR < 2 -/* SASL version 1.x */ -#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, - const char *message) -{ - switch (priority) { - case SASL_LOG_ERR: /* unusual errors */ -#ifdef SASL_LOG_WARN /* non-fatal warnings (Cyrus-SASL v2) */ - case SASL_LOG_WARN: -#endif -#ifdef SASL_LOG_WARNING /* non-fatal warnings (Cyrus-SASL v1) */ - case SASL_LOG_WARNING: -#endif - msg_warn("SASL authentication problem: %s", message); - break; -#ifdef SASL_LOG_INFO - case SASL_LOG_INFO: /* other info (Cyrus-SASL v1) */ - if (msg_verbose) - msg_info("SASL authentication info: %s", message); - break; -#endif -#ifdef SASL_LOG_NOTE - case SASL_LOG_NOTE: /* other info (Cyrus-SASL v2) */ - if (msg_verbose) - msg_info("SASL authentication info: %s", message); - break; -#endif -#ifdef SASL_LOG_FAIL - case SASL_LOG_FAIL: /* authentication failures - * (Cyrus-SASL v2) */ - msg_warn("SASL authentication failure: %s", message); - break; -#endif -#ifdef SASL_LOG_DEBUG - case SASL_LOG_DEBUG: /* more verbose than LOG_NOTE - * (Cyrus-SASL v2) */ - if (msg_verbose > 1) - msg_info("SASL authentication debug: %s", message); - break; -#endif -#ifdef SASL_LOG_TRACE - case SASL_LOG_TRACE: /* traces of internal - * protocols (Cyrus-SASL v2) */ - if (msg_verbose > 1) - msg_info("SASL authentication trace: %s", message); - break; -#endif -#ifdef SASL_LOG_PASS - case SASL_LOG_PASS: /* traces of internal - * protocols, including - * passwords (Cyrus-SASL v2) */ - if (msg_verbose > 1) - msg_info("SASL authentication pass: %s", message); - break; -#endif - } - return (SASL_OK); -} - - /* - * SASL callback interface structure. These call-backs have no per-session - * context. - */ -#define NO_CALLBACK_CONTEXT 0 - -static sasl_callback_t callbacks[] = { - {SASL_CB_LOG, &smtpd_sasl_log, NO_CALLBACK_CONTEXT}, - {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, -#if SASL_VERSION_MAJOR >= 2 - "mutual_auth", SASL_SEC_MUTUAL_AUTH, -#endif - 0, -}; +static XSASL_SERVER_IMPL *smtpd_sasl_impl; /* smtpd_sasl_initialize - per-process initialization */ void smtpd_sasl_initialize(void) { -#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \ - || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19)) - int sasl_major; - int sasl_minor; - int sasl_step; /* - * DLL hell guard. + * Sanity check. */ - sasl_version_info((const char **) 0, (const char **) 0, - &sasl_major, &sasl_minor, - &sasl_step, (int *) 0); - if (sasl_major != SASL_VERSION_MAJOR -#if 0 - || sasl_minor != SASL_VERSION_MINOR - || sasl_step != SASL_VERSION_STEP -#endif - ) - msg_fatal("incorrect SASL library version. " - "Postfix was built with include files from version %d.%d.%d, " - "but the run-time library version is %d.%d.%d", - SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP, - sasl_major, sasl_minor, sasl_step); -#endif + if (smtpd_sasl_impl) + msg_panic("smtpd_sasl_initialize: repeated call"); /* - * Initialize the library: load SASL plug-in routines, etc. + * Initialize the SASL library. */ - if (msg_verbose) - msg_info("smtpd_sasl_initialize: SASL config file is %s.conf", - var_smtpd_sasl_appname); - if (sasl_server_init(callbacks, var_smtpd_sasl_appname) != SASL_OK) + if ((smtpd_sasl_impl = xsasl_server_init(var_smtpd_sasl_type, + var_smtpd_sasl_path)) == 0) msg_fatal("SASL per-process initialization failed"); } @@ -283,16 +150,7 @@ void smtpd_sasl_initialize(void) void smtpd_sasl_connect(SMTPD_STATE *state, const char *sasl_opts_name, const char *sasl_opts_val) { -#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; + const char *mechanism_list; /* * Initialize SASL-specific state variables. Use long-lived storage for @@ -300,246 +158,114 @@ void smtpd_sasl_connect(SMTPD_STATE *state, const char *sasl_opts_name, * memory leaks when a read or write routine returns abnormally after * timeout or I/O error. */ + state->sasl_reply = vstring_alloc(20); state->sasl_mechanism_list = 0; state->sasl_username = 0; state->sasl_method = 0; state->sasl_sender = 0; - state->sasl_conn = 0; - state->sasl_decoded = vstring_alloc(10); - state->sasl_encoded = vstring_alloc(10); /* * Set up a new server context for this connection. */ -#define NO_SECURITY_LAYERS (0) -#define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0) -#define NO_AUTH_REALM ((char *) 0) - -#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 ? - var_smtpd_sasl_realm : NO_AUTH_REALM, - server_address, client_address, - NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS, - &state->sasl_conn) != SASL_OK) - msg_fatal("SASL per-connection server initialization"); +#define SMTPD_SASL_SERVICE "smtp" - /* - * Security options. Some information can be found in the sasl.h include - * file. Disallow anonymous authentication; this is because the - * permit_sasl_authenticated feature is restricted to authenticated - * clients only. - */ - memset(&sec_props, 0, sizeof(sec_props)); - sec_props.min_ssf = 0; - sec_props.max_ssf = 0; /* don't allow real SASL - * security layer */ - sec_props.security_flags = name_mask(sasl_opts_name, smtpd_sasl_mask, - sasl_opts_val); - sec_props.maxbufsize = 0; - sec_props.property_names = 0; - sec_props.property_values = 0; - - if (sasl_setprop(state->sasl_conn, SASL_SEC_PROPS, - &sec_props) != SASL_OK) - msg_fatal("SASL per-connection security setup"); + if ((state->sasl_server = + xsasl_server_create(smtpd_sasl_impl, state->client, + SMTPD_SASL_SERVICE, *var_smtpd_sasl_realm ? + var_smtpd_sasl_realm : (char *) 0, + sasl_opts_val)) == 0) + msg_fatal("SASL per-connection initialization failed"); /* * Get the list of authentication mechanisms. */ -#define UNSUPPORTED_USER ((char *) 0) -#define IGNORE_MECHANISM_LEN ((unsigned *) 0) - - if (sasl_listmech(state->sasl_conn, UNSUPPORTED_USER, - "", " ", "", - &state->sasl_mechanism_list, - IGNORE_MECHANISM_LEN, - &sasl_mechanism_count) != SASL_OK) - msg_fatal("cannot lookup SASL authentication mechanisms"); - if (sasl_mechanism_count <= 0) + if ((mechanism_list = + xsasl_server_get_mechanism_list(state->sasl_server)) == 0) msg_fatal("no SASL authentication mechanisms"); + state->sasl_mechanism_list = mystrdup(mechanism_list); } /* smtpd_sasl_disconnect - per-connection cleanup */ void smtpd_sasl_disconnect(SMTPD_STATE *state) { + if (state->sasl_reply) { + vstring_free(state->sasl_reply); + state->sasl_reply = 0; + } 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 + myfree(state->sasl_mechanism_list); state->sasl_mechanism_list = 0; } - if (state->sasl_conn) { - sasl_dispose(&state->sasl_conn); - state->sasl_conn = 0; + if (state->sasl_username) { + myfree(state->sasl_username); + state->sasl_username = 0; + } + if (state->sasl_method) { + myfree(state->sasl_method); + state->sasl_method = 0; + } + if (state->sasl_sender) { + myfree(state->sasl_sender); + state->sasl_sender = 0; + } + if (state->sasl_server) { + xsasl_server_free(state->sasl_server); + state->sasl_server = 0; } - vstring_free(state->sasl_decoded); - vstring_free(state->sasl_encoded); } /* smtpd_sasl_authenticate - per-session authentication */ -char *smtpd_sasl_authenticate(SMTPD_STATE *state, +int smtpd_sasl_authenticate(SMTPD_STATE *state, const char *sasl_method, const char *init_response) { - char *myname = "smtpd_sasl_authenticate"; - char *dec_buffer; - unsigned dec_length; - unsigned enc_length; - unsigned enc_length_out; - unsigned reply_len; - 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) - msg_info("%s: sasl_method %s%s%s", myname, sasl_method, - IFELSE(init_response, ", init_response ", ""), - IFELSE(init_response, init_response, "")); - - /* - * Sanity check. - */ - if (state->sasl_username || state->sasl_method) - msg_panic("%s: already authenticated", myname); + int status; + const char *sasl_username; /* * SASL authentication protocol start-up. Process any initial client * response that was sent along in the AUTH command. */ - if (init_response) { - 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, reply_len, &dec_length) != SASL_OK) - return ("501 5.7.0 Authentication failed: malformed initial response"); - if (msg_verbose) - msg_info("%s: decoded initial response %s", myname, dec_buffer); - } else { - dec_buffer = 0; - dec_length = 0; - } - result = SASL_SERVER_START(state->sasl_conn, sasl_method, dec_buffer, - dec_length, &serverout, &serveroutlen, &errstr); - - /* - * Repeat until done or until the client gives up. - */ - while (result == SASL_CONTINUE) { + for (status = xsasl_server_first(state->sasl_server, sasl_method, + init_response, state->sasl_reply); + status == XSASL_AUTH_MORE; + status = xsasl_server_next(state->sasl_server, STR(state->buffer), + state->sasl_reply)) { /* - * Send a server challenge. Avoid storing the challenge in a local - * variable, because we would leak memory when smtpd_chat_reply() - * does not return due to timeout or I/O error. sasl_encode64() - * null-terminates the result if the result buffer is large enough. - * - * Regarding the hairy expression below: output from sasl_encode64() - * comes in multiples of four bytes for each triple of input bytes, - * plus four bytes for any incomplete last triple, plus one byte for - * the null terminator. - * - * XXX Replace the klunky sasl_encode64() interface by something that - * uses VSTRING buffers. + * Send a server challenge. */ - if (msg_verbose) - msg_info("%s: uncoded challenge: %.*s", - myname, (int) serveroutlen, serverout); - enc_length = ((serveroutlen + 2) / 3) * 4 + 1; - VSTRING_SPACE(state->sasl_encoded, enc_length); - 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)); + smtpd_chat_reply(state, "334 %s", STR(state->sasl_reply)); /* * Receive the client response. "*" means that the client gives up. - * XXX For now we ignore the fact that excessively long responses - * will be truncated. To handle such responses, we need to change - * smtpd_chat_query() so that it returns an error indication. + * XXX For now we ignore the fact that an excessively long response + * will be chopped into multiple reponses. To handle such responses, + * we need to change smtpd_chat_query() so that it returns an error + * indication. */ smtpd_chat_query(state); - if (strcmp(vstring_str(state->buffer), "*") == 0) - return ("501 5.7.0 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), reply_len, - &dec_length) != SASL_OK) - return ("501 5.7.0 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), - dec_length, &serverout, &serveroutlen, &errstr); + if (strcmp(STR(state->buffer), "*") == 0) { + msg_warn("%s[%s]: SASL %s authentication aborted", + state->name, state->addr, sasl_method); + smtpd_chat_reply(state, "501 5.7.0 Authentication aborted"); + return (-1); + } } - - /* - * Cleanup. What an awful interface. - */ -#if SASL_VERSION_MAJOR < 2 - if (serverout) - free(serverout); -#endif - - /* - * The authentication protocol was completed. - */ - if (result != SASL_OK) - return ("535 5.7.0 Error: authentication failed"); - - /* - * Authentication succeeded. Find out the login name for logging and for - * 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); + if (status != XSASL_AUTH_DONE) { + msg_warn("%s[%s]: SASL %s authentication failed: %s", + state->name, state->addr, sasl_method, + STR(state->sasl_reply)); + smtpd_chat_reply(state, "535 5.7.0 Error: authentication failed: %s", + STR(state->sasl_reply)); + return (-1); + } + smtpd_chat_reply(state, "235 2.0.0 Authentication successful"); + if ((sasl_username = xsasl_server_get_username(state->sasl_server)) == 0) + msg_panic("cannot look up the authenticated SASL username"); + state->sasl_username = mystrdup(sasl_username); printable(state->sasl_username, '?'); state->sasl_method = mystrdup(sasl_method); printable(state->sasl_method, '?'); diff --git a/postfix/src/smtpd/smtpd_sasl_glue.h b/postfix/src/smtpd/smtpd_sasl_glue.h index 2466f9a57..b11981cd6 100644 --- a/postfix/src/smtpd/smtpd_sasl_glue.h +++ b/postfix/src/smtpd/smtpd_sasl_glue.h @@ -4,7 +4,7 @@ /* SUMMARY /* Postfix SMTP server, SASL support interface /* SYNOPSIS -/* #include "smtpd_sasl.h" +/* #include "smtpd_sasl_glue.h" /* DESCRIPTION /* .nf @@ -14,7 +14,7 @@ extern void smtpd_sasl_initialize(void); extern void smtpd_sasl_connect(SMTPD_STATE *, const char *, const char *); extern void smtpd_sasl_disconnect(SMTPD_STATE *); -extern char *smtpd_sasl_authenticate(SMTPD_STATE *, const char *, const char *); +extern int 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); diff --git a/postfix/src/smtpd/smtpd_sasl_proto.c b/postfix/src/smtpd/smtpd_sasl_proto.c index 3e200cdfc..e7c2edd4a 100644 --- a/postfix/src/smtpd/smtpd_sasl_proto.c +++ b/postfix/src/smtpd/smtpd_sasl_proto.c @@ -5,7 +5,7 @@ /* Postfix SMTP protocol support for SASL authentication /* SYNOPSIS /* #include "smtpd.h" -/* #include "smtpd_sasl.h" +/* #include "smtpd_sasl_proto.h" /* /* void smtpd_sasl_auth_cmd(state, argc, argv) /* SMTPD_STATE *state; @@ -34,9 +34,19 @@ /* the SMTP protocol interface for SASL negotiation. The goal /* is to reduce clutter of the main SMTP server source code. /* -/* smtpd_sasl_auth_cmd() implements the AUTH command. -/* +/* smtpd_sasl_auth_cmd() implements the AUTH command and updates +/* the following state structure members: +/* .IP sasl_method +/* The authentication method that was successfully applied. +/* This member is a null pointer in the absence of successful +/* authentication. +/* .IP sasl_username +/* The username that was successfully authenticated. +/* This member is a null pointer in the absence of successful +/* authentication. +/* .PP /* smtpd_sasl_auth_reset() cleans up after the AUTH command. +/* This is required before smtpd_sasl_auth_cmd() can be used again. /* /* smtpd_sasl_mail_opt() implements the SASL-specific AUTH=sender /* option to the MAIL FROM command. The result is an error response @@ -96,6 +106,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include @@ -124,7 +138,6 @@ int smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) { char *auth_mechanism; char *initial_response; - char *err; if (var_helo_required && state->helo_name == 0) { state->error_mask |= MAIL_ERROR_POLICY; @@ -161,15 +174,7 @@ int smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) */ auth_mechanism = argv[1].strval; initial_response = (argc == 3 ? argv[2].strval : 0); - err = smtpd_sasl_authenticate(state, auth_mechanism, initial_response); - if (err != 0) { - msg_warn("%s[%s]: SASL %s authentication failed", - state->name, state->addr, auth_mechanism); - smtpd_chat_reply(state, "%s", err); - return (-1); - } - smtpd_chat_reply(state, "235 2.0.0 Authentication successful"); - return (0); + return (smtpd_sasl_authenticate(state, auth_mechanism, initial_response)); } /* smtpd_sasl_auth_reset - clean up after AUTH command */ diff --git a/postfix/src/smtpd/smtpd_token.c b/postfix/src/smtpd/smtpd_token.c index d45408132..7180317c4 100644 --- a/postfix/src/smtpd/smtpd_token.c +++ b/postfix/src/smtpd/smtpd_token.c @@ -51,6 +51,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include diff --git a/postfix/src/smtpstone/qmqp-sink.c b/postfix/src/smtpstone/qmqp-sink.c index d0c2d07c2..3be497a45 100644 --- a/postfix/src/smtpstone/qmqp-sink.c +++ b/postfix/src/smtpstone/qmqp-sink.c @@ -58,10 +58,6 @@ #include #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c index 3e4a0dc3e..c4bcce919 100644 --- a/postfix/src/tls/tls_client.c +++ b/postfix/src/tls/tls_client.c @@ -128,6 +128,10 @@ #ifdef USE_TLS #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include diff --git a/postfix/src/tls/tls_mgr.c b/postfix/src/tls/tls_mgr.c index 22b9acdba..0e1cdf93c 100644 --- a/postfix/src/tls/tls_mgr.c +++ b/postfix/src/tls/tls_mgr.c @@ -96,6 +96,10 @@ #ifdef USE_TLS +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include diff --git a/postfix/src/tls/tls_verify.c b/postfix/src/tls/tls_verify.c index 4471da58e..91a85ed6f 100644 --- a/postfix/src/tls/tls_verify.c +++ b/postfix/src/tls/tls_verify.c @@ -96,10 +96,6 @@ #ifdef USE_TLS #include -#ifdef STRCASECMP_IN_STRINGS_H -#include -#endif - /* Utility library. */ #include diff --git a/postfix/src/util/dict_pcre.c b/postfix/src/util/dict_pcre.c index 6a554e0da..cc7b24bcf 100644 --- a/postfix/src/util/dict_pcre.c +++ b/postfix/src/util/dict_pcre.c @@ -41,6 +41,10 @@ #include #include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + /* Utility library. */ #include "mymalloc.h" diff --git a/postfix/src/util/name_mask.c b/postfix/src/util/name_mask.c index 3ce83ffc4..8a2a361ee 100644 --- a/postfix/src/util/name_mask.c +++ b/postfix/src/util/name_mask.c @@ -64,8 +64,8 @@ /* .IP NAME_MASK_RETURN /* Require that all names listed in \fIname\fR exist in \fItable\fR, /* and that all bits listed in \fImask\fR exist in \fItable\fR. -/* Return 0 (name_mask()) or a null pointer (str_name_mask()) -/* if this condition is not met. +/* Log a warning, and return 0 (name_mask()) or a null pointer +/* (str_name_mask()) if this condition is not met. /* .IP NAME_MASK_ANY_CASE /* Enable case-insensitive matching. /* This feature is not enabled by default when calling name_mask(); @@ -137,8 +137,11 @@ int name_mask_opt(const char *context, NAME_MASK *table, const char *names, if (flags & NAME_MASK_FATAL) msg_fatal("unknown %s value \"%s\" in \"%s\"", context, name, names); - if (flags & NAME_MASK_RETURN) + if (flags & NAME_MASK_RETURN) { + msg_warn("unknown %s value \"%s\" in \"%s\"", + context, name, names); return (0); + } break; } if (lookup(name, np->name) == 0) { @@ -174,8 +177,11 @@ const char *str_name_mask_opt(const char *context, NAME_MASK *table, if (flags & NAME_MASK_FATAL) msg_fatal("%s: invalid %s bit in mask: 0x%x", myname, context, mask); - if (flags & NAME_MASK_RETURN) + if (flags & NAME_MASK_RETURN) { + msg_warn("%s: invalid %s bit in mask: 0x%x", + myname, context, mask); return (0); + } break; } if (mask & np->mask) { diff --git a/postfix/src/util/sane_basename.c b/postfix/src/util/sane_basename.c index 3dea9e16f..6c3a4c19e 100644 --- a/postfix/src/util/sane_basename.c +++ b/postfix/src/util/sane_basename.c @@ -55,6 +55,7 @@ /* System library. */ #include +#include /* Utility library. */ diff --git a/postfix/src/util/stringops.h b/postfix/src/util/stringops.h index 04e09df00..8f96aa4b7 100644 --- a/postfix/src/util/stringops.h +++ b/postfix/src/util/stringops.h @@ -35,6 +35,7 @@ extern char *basename(const char *); extern char *sane_basename(VSTRING *, const char *); extern char *sane_dirname(VSTRING *, const char *); extern VSTRING *unescape(VSTRING *, const char *); +extern VSTRING *escape(VSTRING *, const char *, ssize_t); extern int alldig(const char *); extern int allprint(const char *); extern int allspace(const char *); diff --git a/postfix/src/util/unescape.c b/postfix/src/util/unescape.c index ef76d6d64..14be31fa6 100644 --- a/postfix/src/util/unescape.c +++ b/postfix/src/util/unescape.c @@ -9,11 +9,18 @@ /* VSTRING *unescape(result, input) /* VSTRING *result; /* const char *input; +/* +/* VSTRING *escape(result, input, len) +/* VSTRING *result; +/* const char *input; +/* ssize_t len; /* DESCRIPTION /* unescape() translates C-like escape sequences in the null-terminated /* string \fIinput\fR and places the result in \fIresult\fR. The result /* is null-terminated, and is the function result value. /* +/* escape() does the reverse transformation. +/* /* Escape sequences and their translations: /* .IP \ea /* Bell character. @@ -121,6 +128,50 @@ VSTRING *unescape(VSTRING *result, const char *data) return (result); } +/* escape - reverse transformation */ + +VSTRING *escape(VSTRING *result, const char *data, ssize_t len) +{ + int ch; + + VSTRING_RESET(result); + while (len-- > 0) { + ch = *UCHAR(data++); + if (ISASCII(ch)) { + if (ISPRINT(ch)) { + if (ch == '\\') + VSTRING_ADDCH(result, ch); + VSTRING_ADDCH(result, ch); + continue; + } else if (ch == '\a') { /* \a -> audible bell */ + vstring_strcat(result, "\a"); + continue; + } else if (ch == '\b') { /* \b -> backspace */ + vstring_strcat(result, "\b"); + continue; + } else if (ch == '\f') { /* \f -> formfeed */ + vstring_strcat(result, "\f"); + continue; + } else if (ch == '\n') { /* \n -> newline */ + vstring_strcat(result, "\n"); + continue; + } else if (ch == '\r') { /* \r -> carriagereturn */ + vstring_strcat(result, "\r"); + continue; + } else if (ch == '\t') { /* \t -> horizontal tab */ + vstring_strcat(result, "\t"); + continue; + } else if (ch == '\v') { /* \v -> vertical tab */ + vstring_strcat(result, "\v"); + continue; + } + } + vstring_sprintf_append(result, "\\%03d", ch); + } + VSTRING_TERMINATE(result); + return (result); +} + #ifdef TEST #include diff --git a/postfix/src/util/unix_recv_fd.c b/postfix/src/util/unix_recv_fd.c index d7fbb7eba..5c1658531 100644 --- a/postfix/src/util/unix_recv_fd.c +++ b/postfix/src/util/unix_recv_fd.c @@ -33,6 +33,7 @@ #include /* includes */ #include #include +#include /* Utility library. */ @@ -71,6 +72,7 @@ int unix_recv_fd(int fd) } control_un; struct cmsghdr *cmptr; + memset((char *) &msg, 0, sizeof(msg)); msg.msg_control = control_un.control; msg.msg_controllen = CMSG_LEN(sizeof(newfd)); /* Fix 200506 */ #else diff --git a/postfix/src/util/unix_send_fd.c b/postfix/src/util/unix_send_fd.c index f913de53e..20436a0fb 100644 --- a/postfix/src/util/unix_send_fd.c +++ b/postfix/src/util/unix_send_fd.c @@ -36,6 +36,7 @@ #include /* includes */ #include #include +#include /* Utility library. */ @@ -73,6 +74,7 @@ int unix_send_fd(int fd, int sendfd) } control_un; struct cmsghdr *cmptr; + memset((char *) &msg, 0, sizeof(msg)); msg.msg_control = control_un.control; msg.msg_controllen = CMSG_LEN(sizeof(sendfd)); /* Fix 200506 */ diff --git a/postfix/src/util/vbuf_print.c b/postfix/src/util/vbuf_print.c index c7281db08..4046110e6 100644 --- a/postfix/src/util/vbuf_print.c +++ b/postfix/src/util/vbuf_print.c @@ -105,10 +105,11 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) { + const char *myname = "vbuf_print"; static VSTRING *fmt; /* format specifier */ unsigned char *cp; - unsigned width; /* field width */ - unsigned prec; /* numerical precision */ + int width; /* width and numerical precision */ + int prec; /* are signed for overflow defense */ unsigned long_flag; /* long or plain integer */ int ch; char *s; @@ -160,6 +161,10 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) VSTRING_ADDCH(fmt, ch); } } + if (width < 0) { + msg_warn("%s: bad width %d in %.50s", myname, width, format); + width = 0; + } if (*cp == '.') /* width/precision separator */ VSTRING_ADDCH(fmt, *cp++); if (*cp == '*') { /* dynamic precision */ @@ -172,6 +177,10 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) VSTRING_ADDCH(fmt, ch); } } + if (prec < 0) { + msg_warn("%s: bad precision %d in %.50s", myname, prec, format); + prec = 0; + } if ((long_flag = (*cp == 'l')) != 0)/* long whatever */ VSTRING_ADDCH(fmt, *cp++); if (*cp == 0) /* premature end, punt */ diff --git a/postfix/src/xsasl/.indent.pro b/postfix/src/xsasl/.indent.pro new file mode 120000 index 000000000..5c837eca6 --- /dev/null +++ b/postfix/src/xsasl/.indent.pro @@ -0,0 +1 @@ +../../.indent.pro \ No newline at end of file diff --git a/postfix/src/xsasl/Makefile.in b/postfix/src/xsasl/Makefile.in new file mode 100644 index 000000000..0e45a12fe --- /dev/null +++ b/postfix/src/xsasl/Makefile.in @@ -0,0 +1,130 @@ +SHELL = /bin/sh +SRCS = xsasl_server.c xsasl_cyrus_server.c xsasl_cyrus_log.c \ + xsasl_cyrus_security.c xsasl_client.c xsasl_cyrus_client.c +OBJS = xsasl_server.o xsasl_cyrus_server.o xsasl_cyrus_log.o \ + xsasl_cyrus_security.o xsasl_client.o xsasl_cyrus_client.o +HDRS = xsasl.h +TESTSRC = +DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) +CFLAGS = $(DEBUG) $(OPT) $(DEFS) +INCL = +LIB = libxsasl.a +TESTPROG= + +LIBS = ../../lib/libglobal.a ../../lib/libutil.a +LIB_DIR = ../../lib +INC_DIR = ../../include +MAKES = + +.c.o:; $(CC) $(CFLAGS) -c $*.c + +all: $(LIB) + +$(OBJS): ../../conf/makedefs.out + +Makefile: Makefile.in + (cat ../../conf/makedefs.out $?) >$@ + +test: $(TESTPROG) + +$(LIB): $(OBJS) + $(AR) $(ARFL) $(LIB) $? + $(RANLIB) $(LIB) + +$(LIB_DIR)/$(LIB): $(LIB) + cp $(LIB) $(LIB_DIR) + $(RANLIB) $(LIB_DIR)/$(LIB) + +update: $(LIB_DIR)/$(LIB) $(HDRS) + -for i in $(HDRS); \ + do \ + cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \ + done + cd $(INC_DIR); chmod 644 $(HDRS) + +printfck: $(OBJS) $(PROG) + rm -rf printfck + mkdir printfck + cp *.h printfck + sed '1,/^# do not edit/!d' Makefile >printfck/Makefile + set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done + cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o` + +lint: + lint $(DEFS) $(SRCS) $(LINTFIX) + +clean: + rm -f *.o $(LIB) *core $(TESTPROG) junk + rm -rf printfck + +tidy: clean + +foo: $(LIB) $(LIBS) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) + mv junk $@.o + +depend: $(MAKES) + (sed '1,/^# do not edit/!d' Makefile.in; \ + set -e; for i in [a-z][a-z0-9]*.c; do \ + $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \ + -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \ + -e 's/o: \.\//o: /' -e p -e '}' ; \ + done | sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in + @$(EXPORT) make -f Makefile.in Makefile 1>&2 + +# do not edit below this line - it is generated by 'make depend' +xsasl_client.o: ../../include/argv.h +xsasl_client.o: ../../include/msg.h +xsasl_client.o: ../../include/mymalloc.h +xsasl_client.o: ../../include/sys_defs.h +xsasl_client.o: ../../include/vbuf.h +xsasl_client.o: ../../include/vstream.h +xsasl_client.o: ../../include/vstring.h +xsasl_client.o: xsasl.h +xsasl_client.o: xsasl_client.c +xsasl_client.o: xsasl_cyrus.h +xsasl_cyrus_client.o: ../../include/argv.h +xsasl_cyrus_client.o: ../../include/msg.h +xsasl_cyrus_client.o: ../../include/mymalloc.h +xsasl_cyrus_client.o: ../../include/stringops.h +xsasl_cyrus_client.o: ../../include/sys_defs.h +xsasl_cyrus_client.o: ../../include/vbuf.h +xsasl_cyrus_client.o: ../../include/vstream.h +xsasl_cyrus_client.o: ../../include/vstring.h +xsasl_cyrus_client.o: xsasl.h +xsasl_cyrus_client.o: xsasl_cyrus.h +xsasl_cyrus_client.o: xsasl_cyrus_client.c +xsasl_cyrus_client.o: xsasl_cyrus_common.h +xsasl_cyrus_log.o: ../../include/msg.h +xsasl_cyrus_log.o: ../../include/sys_defs.h +xsasl_cyrus_log.o: xsasl_cyrus_common.h +xsasl_cyrus_log.o: xsasl_cyrus_log.c +xsasl_cyrus_security.o: ../../include/name_mask.h +xsasl_cyrus_security.o: ../../include/sys_defs.h +xsasl_cyrus_security.o: xsasl_cyrus_common.h +xsasl_cyrus_security.o: xsasl_cyrus_security.c +xsasl_cyrus_server.o: ../../include/argv.h +xsasl_cyrus_server.o: ../../include/mail_params.h +xsasl_cyrus_server.o: ../../include/msg.h +xsasl_cyrus_server.o: ../../include/mymalloc.h +xsasl_cyrus_server.o: ../../include/name_mask.h +xsasl_cyrus_server.o: ../../include/stringops.h +xsasl_cyrus_server.o: ../../include/sys_defs.h +xsasl_cyrus_server.o: ../../include/vbuf.h +xsasl_cyrus_server.o: ../../include/vstream.h +xsasl_cyrus_server.o: ../../include/vstring.h +xsasl_cyrus_server.o: xsasl.h +xsasl_cyrus_server.o: xsasl_cyrus.h +xsasl_cyrus_server.o: xsasl_cyrus_common.h +xsasl_cyrus_server.o: xsasl_cyrus_server.c +xsasl_server.o: ../../include/argv.h +xsasl_server.o: ../../include/msg.h +xsasl_server.o: ../../include/mymalloc.h +xsasl_server.o: ../../include/sys_defs.h +xsasl_server.o: ../../include/vbuf.h +xsasl_server.o: ../../include/vstream.h +xsasl_server.o: ../../include/vstring.h +xsasl_server.o: xsasl.h +xsasl_server.o: xsasl_cyrus.h +xsasl_server.o: xsasl_server.c diff --git a/postfix/src/xsasl/README b/postfix/src/xsasl/README new file mode 100644 index 000000000..6755b6709 --- /dev/null +++ b/postfix/src/xsasl/README @@ -0,0 +1,105 @@ +Purpose of this document +======================== + +This document describes how to add your own SASL implementation to +Postfix. You don't have to provide both the server and client side. +You can provide just one and omit the other. The examples below +assume you do both. + +The plug-in API is described in cyrus_server.c and cyrus_client.c. +It was unavoidably contaminated^h^h^h^h^h^h^h^h^h^h^h^hinfluenced +by Cyrus SASL and may need revision as other implementations are +added. + +For an example of how the plug-in interface is implemented, have a +look at the xsasl/xsasl_cyrus_client.c and xsasl/xsasl_cyrus_server.c. + +Configuration features +====================== + +There are two configuration parameters that allow you to pass +information from main.cf into the plug_in: + + smtpd_sasl_path, smtpd_sasl_security_options + smtp_sasl_path, smtp_sasl_security_options + lmtp_sasl_path, lmtp_sasl_security_options + +The parameter values are passed to the plug-in without any +interpretation. The following restrictions are imposed by the main.cf +file parser: parameter values never contain newlines, and they never +start or end with whitespace characters. + +The _path parameter value is passed only once during process +initialization (i.e. it is a class variable). The path typically +specifies the location of a configuration file or rendez-vous point. +The _security_options parameter value is passed each time SASL is +turned on for a connection (i.e. it is an instance variable). The +options may depend on whether or not TLS encryption is turned on. +Remember that one Postfix process may perform up to 100 mail +transactions during its life time. Things that happen in one +transaction must not affect later transactions. + +Adding Postfix support for your own SASL implementation +======================================================= + +To add your own SASL implementation, say, FOOBAR: + +- Copy xsasl/xsasl_cyrus.h to xsasl/xsasl_foobar.h and replace + CYRUS by FOOBAR: + + #if defined(USE_SASL_AUTH) && defined(USE_FOOBAR_SASL) + /* + * SASL protocol interface + */ + #define XSASL_TYPE_FOOBAR "foobar" + extern XSASL_SERVER_IMPL *xsasl_foobar_server_init(const char *, const char *); + extern XSASL_CLIENT_IMPL *xsasl_foobar_client_init(const char *, const char *); + #endif + +- Edit xsasl/xsasl_server.c, add your #include line + under #include at the top, and add your initialization + function in the table at the bottom as shown below: + + static XSASL_SERVER_IMPL_INFO server_impl_info[] = { + #ifdef XSASL_TYPE_CYRUS + XSASL_TYPE_CYRUS, xsasl_cyrus_server_init, + #endif + #ifdef XSASL_TYPE_FOOBAR + XSASL_TYPE_FOOBAR, xsasl_foobar_server_init, + #endif + 0, + }; + +- Repeat the (almost) same procedure for xsasl/xsasl_client.c. + +- Create your own xsasl/xsasl_foobar_{client,server}.c and support + files. Perhaps it's convenient to copy the cyrus files, rip out + the function bodies, and replace CYRUS by FOOBAR. + +- List your source files in Makefile.in. Don't forget to do "make + depend" after you do "make makefiles" in the step that follows + after this one. + + SRCS = xsasl_server.c xsasl_cyrus_server.c xsasl_cyrus_log.c \ + xsasl_cyrus_security.c xsasl_client.c xsasl_cyrus_client.c \ + xsasl_foobar_client.c xsasl_foobar_server.c + OBJS = xsasl_server.o xsasl_cyrus_server.o xsasl_cyrus_log.o \ + xsasl_cyrus_security.o xsasl_client.o xsasl_cyrus_client.o \ + xsasl_foobar_client.o xsasl_foobar_server.o + +- Create the Postfix makefiles from the top-level directory: + + % make makefiles CCARGS='-DUSE_SASL_AUTH -DUSE_FOOBAR_SASL \ + -DDEF_CLIENT_SASL_TYPE=\"foobar\" -DDEF_SERVER_TYPE=\"foobar\" \ + -I/some/where/include' AUXLIBS='-L/some/where/lib -lfoobar' + + Yes, you can have different default SASL implementation types for + the client and server plug-ins. + + Of course you don't have to override the default SASL implementation + type; it is shown here as an example. + + +- Don't forget to do "make depend" in the xsasl directory. + +- Document your build and configuration with a README document. diff --git a/postfix/src/xsasl/xsasl.h b/postfix/src/xsasl/xsasl.h new file mode 100644 index 000000000..291ff8edd --- /dev/null +++ b/postfix/src/xsasl/xsasl.h @@ -0,0 +1,113 @@ +#ifndef _XSASL_H_INCLUDED_ +#define _XSASL_H_INCLUDED_ + +/*++ +/* NAME +/* xsasl 3h +/* SUMMARY +/* Postfix SASL plug-in interface +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include +#include +#include + + /* + * Generic server object. Specific instances extend this with their own + * private data. + */ +typedef struct XSASL_SERVER { + void (*free) (struct XSASL_SERVER *); + int (*first) (struct XSASL_SERVER *, const char *, const char *, VSTRING *); + int (*next) (struct XSASL_SERVER *, const char *, VSTRING *); + const char *(*get_mechanism_list) (struct XSASL_SERVER *); + const char *(*get_username) (struct XSASL_SERVER *); +} XSASL_SERVER; + +#define xsasl_server_free(server) (server)->free(server) +#define xsasl_server_first(server, method, init_resp, reply) \ + (server)->first((server), (method), (init_resp), (reply)) +#define xsasl_server_next(server, request, reply) \ + (server)->next((server), (request), (reply)) +#define xsasl_server_get_mechanism_list(server) \ + (server)->get_mechanism_list((server)) +#define xsasl_server_get_username(server) \ + (server)->get_username((server)) + + /* + * Generic server implementation. Specific instances extend this with their + * own private data. + */ +typedef struct XSASL_SERVER_IMPL { + XSASL_SERVER *(*create) (struct XSASL_SERVER_IMPL *, VSTREAM *, const char *, const char *, const char *); + void (*done) (struct XSASL_SERVER_IMPL *); +} XSASL_SERVER_IMPL; + +extern XSASL_SERVER_IMPL *xsasl_server_init(const char *, const char *); +extern ARGV *xsasl_server_types(void); + +#define xsasl_server_create(impl, stream, service, realm, sec_props) \ + (impl)->create((impl), (stream), (service), (realm), (sec_props)) +#define xsasl_server_done(impl) (impl)->done((impl)); + + /* + * Generic client object. Specific instances extend this with their own + * private data. + */ +typedef struct XSASL_CLIENT { + void (*free) (struct XSASL_CLIENT *); + int (*first) (struct XSASL_CLIENT *, const char *, const char *, const char *, const char **, VSTRING *); + int (*next) (struct XSASL_CLIENT *, const char *, VSTRING *); +} XSASL_CLIENT; + +#define xsasl_client_free(client) (client)->free(client) +#define xsasl_client_first(client, server, method, user, pass, init_resp) \ + (client)->first((client), (server), (method), (user), (pass), (init_resp)) +#define xsasl_client_next(client, request, reply) \ + (client)->next((client), (request), (reply)) +#define xsasl_client_set_password(client, user, pass) \ + (client)->set_password((client), (user), (pass)) + + /* + * Generic client implementation. Specific instances extend this with their + * own private data. + */ +typedef struct XSASL_CLIENT_IMPL { + XSASL_CLIENT *(*create) (struct XSASL_CLIENT_IMPL *, VSTREAM *, const char *, const char *, const char *); + void (*done) (struct XSASL_CLIENT_IMPL *); +} XSASL_CLIENT_IMPL; + +extern XSASL_CLIENT_IMPL *xsasl_client_init(const char *, const char *); +extern ARGV *xsasl_client_types(void); + +#define xsasl_client_create(impl, stream, service, server, sec_props) \ + (impl)->create((impl), (stream), (service), (server), (sec_props)) +#define xsasl_client_done(impl) (impl)->done((impl)); + + /* + * Status codes. + */ +#define XSASL_AUTH_OK 1 /* Success */ +#define XSASL_AUTH_MORE 2 /* Need another c/s protocol exchange */ +#define XSASL_AUTH_DONE 3 /* Authentication completed */ +#define XSASL_AUTH_FORM 4 /* Cannot decode response */ +#define XSASL_AUTH_FAIL 5 /* Error */ + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/xsasl/xsasl_client.c b/postfix/src/xsasl/xsasl_client.c new file mode 100644 index 000000000..0e6267c7c --- /dev/null +++ b/postfix/src/xsasl/xsasl_client.c @@ -0,0 +1,223 @@ +/*++ +/* NAME +/* xsasl_client 3 +/* SUMMARY +/* Postfix SASL client plug-in interface +/* SYNOPSIS +/* #include +/* +/* XSASL_CLIENT_IMPL *xsasl_client_init(client_type, path_info) +/* const char *client_type; +/* const char *path_info; +/* +/* void xsasl_client_done(implementation) +/* XSASL_CLIENT_IMPL *implementation; +/* +/* ARGV *xsasl_client_types() +/* +/* XSASL_CLIENT *xsasl_client_create(implementation, stream, service, +/* server_name, security_properties) +/* XSASL_CLIENT_IMPL *implementation; +/* VSTREAM *stream; +/* const char *service; +/* const char *server_name; +/* const char *security_properties; +/* +/* void xsasl_client_free(client) +/* XSASL_CLIENT *client; +/* +/* int xsasl_client_first(client, stream, mech_list, username, +/* password, auth_method, init_resp) +/* XSASL_CLIENT *client; +/* const char *mech_list; +/* const char *username; +/* const char *password; +/* const char **auth_method; +/* VSTRING *init_resp; +/* +/* int xsasl_client_next(client, server_reply, client_reply) +/* XSASL_CLIENT *client; +/* const char *server_reply; +/* VSTRING *client_reply; +/* DESCRIPTION +/* The XSASL_CLIENT abstraction implements a generic interface +/* to one or more SASL authentication implementations. +/* +/* xsasl_client_init() is called once during process initialization. +/* It selects a SASL implementation by name, specifies the +/* location of a configuration file or rendez-vous point, and +/* returns an implementation handle that can be used to generate +/* SASL client instances. This function is typically used to +/* initialize the underlying implementation. +/* +/* xsasl_client_done() disposes of an implementation handle, +/* and allows the underlying implementation to release resources. +/* +/* xsasl_client_types() lists the available implementation types. +/* The result should be destroyed by the caller. +/* +/* xsasl_client_create() is called at the start of an SMTP +/* session. It generates a Postfix SASL plug-in client instance +/* for the specified service and server name, with the specified +/* security properties. The stream handle is stored so that +/* encryption can be turned on after successful negotiations. +/* +/* xsasl_client_free() is called at the end of an SMTP session. +/* It destroys a SASL client instance, and disables further +/* read/write operations if encryption was turned on. +/* +/* xsasl_client_first() produces the client input for the AUTH +/* command. The input is an authentication method list from +/* an EHLO response, a username and a password. On return, the +/* method argument specifies the authentication method; storage +/* space is owned by the underlying implementation. The initial +/* response and client non-error replies are BASE64 encoded. +/* Client error replies are 7-bit ASCII text without control +/* characters, and without BASE64 encoding. They are meant for +/* the local application, not for transmission to the server. +/* The client may negotiate encryption of the client-server +/* connection. +/* +/* The result is one of the following: +/* .IP XSASL_AUTH_OK +/* Success. +/* .IP XSASL_AUTH_FORM +/* The server reply is incorrectly formatted. The client error +/* reply explains why. +/* .IP XSASL_AUTH_FAIL +/* Other error. The client error reply explains why. +/* .PP +/* xsasl_client_next() supports the subsequent stages of the +/* AUTH protocol. Both the client reply and client non-error +/* responses are BASE64 encoded. See xsasl_client_first() for +/* other details. +/* +/* Arguments: +/* .IP client +/* SASL plug-in client handle. +/* .IP client_reply +/* BASE64 encoded non-error client reply, or ASCII error +/* description for the user. +/* .IP client_type +/* The name of a Postfix SASL client plug_in implementation. +/* .IP client_types +/* Null-terminated array of strings with SASL client plug-in +/* implementation names. +/* .IP init_resp +/* The AUTH command initial response. +/* .IP implementation +/* Implementation handle that was obtained with xsasl_client_init(). +/* .IP mech_list +/* List of SASL mechanisms as announced by the server. +/* .IP auth_method +/* The AUTH command authentication method. +/* .IP password +/* Information from the Postfix SASL password file or equivalent. +/* .IP path_info +/* The value of the smtp_sasl_path parameter or equivalent. +/* This specifies the implementation-dependent location of a +/* configuration file, rendez-vous point, etc., and is passed +/* unchanged to the plug-in. +/* .IP security_options +/* The value of the smtp_sasl_security_options parameter or +/* equivalent. This is passed unchanged to the plug-in. +/* .IP server_name +/* The remote server fully qualified hostname. +/* .IP server_reply +/* BASE64 encoded server reply without SMTP reply code or +/* enhanced status code. +/* .IP service +/* The service that is implemented by the local client (typically, +/* "lmtp" or "smtp"). +/* .IP stream +/* The connection between client and server. +/* When SASL encryption is negotiated, the plug-in will +/* transparently intercept the socket read/write operations. +/* .IP username +/* Information from the Postfix SASL password file. +/* SECURITY +/* .ad +/* .fi +/* The caller does not sanitize the server reply. It is the +/* responsibility of the underlying SASL client implementation +/* to produce 7-bit ASCII without control characters as client +/* non-error and error replies. +/* DIAGNOSTICS +/* In case of error, xsasl_client_init() and xsasl_client_create() +/* log a warning and return a null pointer. +/* +/* Functions that normally return XSASL_AUTH_OK will log a warning +/* and return an appropriate result value. +/* +/* Panic: interface violation. +/* +/* Fatal errors: out of memory. +/* SEE ALSO +/* cyrus_security(3) Cyrus SASL security features +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this +/* software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include + +/* Utility library. */ + +#include +#include + +/* SASL implementations. */ + +#include +#include + + /* + * Lookup table for available SASL client implementations. + */ +typedef struct { + char *client_type; + struct XSASL_CLIENT_IMPL *(*client_init) (const char *, const char *); +} XSASL_CLIENT_IMPL_INFO; + +static XSASL_CLIENT_IMPL_INFO client_impl_info[] = { +#ifdef XSASL_TYPE_CYRUS + XSASL_TYPE_CYRUS, xsasl_cyrus_client_init, +#endif + 0, +}; + +/* xsasl_client_init - look up client implementation by name */ + +XSASL_CLIENT_IMPL *xsasl_client_init(const char *client_type, + const char *path_info) +{ + XSASL_CLIENT_IMPL_INFO *xp; + + for (xp = client_impl_info; xp->client_type; xp++) + if (strcmp(client_type, xp->client_type) == 0) + return (xp->client_init(client_type, path_info)); + msg_warn("unsupported SASL client implementation: %s", client_type); + return (0); +} + +/* xsasl_client_types - report available implementation types */ + +ARGV *xsasl_client_types(void) +{ + XSASL_CLIENT_IMPL_INFO *xp; + ARGV *argv = argv_alloc(1); + + for (xp = client_impl_info; xp->client_type; xp++) + argv_add(argv, xp->client_type, ARGV_END); + return (argv); +} diff --git a/postfix/src/xsasl/xsasl_cyrus.h b/postfix/src/xsasl/xsasl_cyrus.h new file mode 100644 index 000000000..5e78dcd2b --- /dev/null +++ b/postfix/src/xsasl/xsasl_cyrus.h @@ -0,0 +1,42 @@ +#ifndef _XSASL_CYRUS_H_INCLUDED_ +#define _XSASL_CYRUS_H_INCLUDED_ + +/*++ +/* NAME +/* xsasl_cyrus 3h +/* SUMMARY +/* Cyrus SASL plug-in +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * XSASL library. + */ +#include + +#if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL) + + /* + * SASL protocol interface + */ +#define XSASL_TYPE_CYRUS "cyrus" + +extern XSASL_SERVER_IMPL *xsasl_cyrus_server_init(const char *, const char *); +extern XSASL_CLIENT_IMPL *xsasl_cyrus_client_init(const char *, const char *); + +#endif + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/xsasl/xsasl_cyrus_client.c b/postfix/src/xsasl/xsasl_cyrus_client.c new file mode 100644 index 000000000..5e9e85b66 --- /dev/null +++ b/postfix/src/xsasl/xsasl_cyrus_client.c @@ -0,0 +1,565 @@ +/*++ +/* NAME +/* xsasl_cyrus_client 3 +/* SUMMARY +/* Cyrus SASL client-side plug-in +/* SYNOPSIS +/* #include +/* +/* XSASL_CLIENT_IMPL *xsasl_cyrus_client_init(client_type, path_info) +/* const char *client_type; +/* DESCRIPTION +/* This module implements the Cyrus SASL client-side authentication +/* plug-in. +/* +/* xsasl_cyrus_client_init() initializes the Cyrus SASL library and +/* returns an implementation handle that can be used to generate +/* SASL client instances. +/* +/* Arguments: +/* .IP client_type +/* The plug-in SASL client type (cyrus). This argument is +/* ignored, but it could be used when one implementation +/* provides multiple variants. +/* .IP path_info +/* Implementation-specific information to specify the location +/* of a configuration file, rendez-vous point, etc. This +/* information is ignored by the Cyrus SASL client plug-in. +/* DIAGNOSTICS +/* Fatal: out of memory. +/* +/* Panic: interface violation. +/* +/* Other: the routines log a warning and return an error result +/* as specified in xsasl_client(3). +/* SEE ALSO +/* xsasl_client(3) Client API +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Original author: +/* Till Franke +/* SuSE Rhein/Main AG +/* 65760 Eschborn, Germany +/* +/* Adopted by: +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + + /* + * System library. + */ +#include +#include +#include + + /* + * Utility library + */ +#include +#include +#include + + /* + * Application-specific + */ +#include +#include +#include + +#if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL) + +#include +#include + +/* + * Silly little macros. + */ +#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_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_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) +typedef char *CLIENTOUT_TYPE; + +#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) +typedef const char *CLIENTOUT_TYPE; + +#endif + + /* + * The XSASL_CYRUS_CLIENT object is derived from the generic XSASL_CLIENT + * object. + */ +typedef struct { + XSASL_CLIENT xsasl; /* generic members, must be first */ + VSTREAM *stream; /* client-server connection */ + sasl_conn_t *sasl_conn; /* SASL context */ + VSTRING *decoded; /* decoded server challenge */ + sasl_callback_t *callbacks; /* user/password lookup */ + char *username; + char *password; +} XSASL_CYRUS_CLIENT; + + /* + * Forward declarations. + */ +static void xsasl_cyrus_client_done(XSASL_CLIENT_IMPL *); +static XSASL_CLIENT *xsasl_cyrus_client_create(XSASL_CLIENT_IMPL *, + VSTREAM *, + const char *, + const char *, + const char *); +static int xsasl_cyrus_client_set_security(XSASL_CLIENT *, const char *); +static int xsasl_cyrus_client_first(XSASL_CLIENT *, const char *, const char *, + const char *, const char **, VSTRING *); +static int xsasl_cyrus_client_next(XSASL_CLIENT *, const char *, VSTRING *); +static void xsasl_cyrus_client_free(XSASL_CLIENT *); + +/* xsasl_cyrus_client_get_user - username lookup call-back routine */ + +static int xsasl_cyrus_client_get_user(void *context, int unused_id, + const char **result, + unsigned *len) +{ + char *myname = "xsasl_cyrus_get_user"; + XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) context; + + if (msg_verbose) + msg_info("%s: %s", myname, client->username); + + /* + * Sanity check. + */ + if (client->password == 0) + msg_panic("%s: no username looked up", myname); + + *result = client->username; + if (len) + *len = strlen(client->username); + return (SASL_OK); +} + +/* xsasl_cyrus_client_get_passwd - password lookup call-back routine */ + +static int xsasl_cyrus_client_get_passwd(sasl_conn_t *conn, void *context, + int id, sasl_secret_t **psecret) +{ + char *myname = "xsasl_cyrus_get_passwd"; + XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) context; + int len; + + if (msg_verbose) + msg_info("%s: %s", myname, client->password); + + /* + * Sanity check. + */ + if (!conn || !psecret || id != SASL_CB_PASS) + return (SASL_BADPARAM); + if (client->password == 0) + msg_panic("%s: no password looked up", myname); + + /* + * Convert the password into a counted string. + */ + len = strlen(client->password); + if ((*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len)) == 0) + return (SASL_NOMEM); + (*psecret)->len = len; + memcpy((*psecret)->data, client->password, len + 1); + + return (SASL_OK); +} + +/* xsasl_cyrus_client_init - initialize Cyrus SASL library */ + +XSASL_CLIENT_IMPL *xsasl_cyrus_client_init(const char *unused_client_type, + const char *unused_path_info) +{ + XSASL_CLIENT_IMPL *xp; + int sasl_status; + + /* + * Global callbacks. These have no per-session context. + */ + static sasl_callback_t callbacks[] = { + {SASL_CB_LOG, &xsasl_cyrus_log, 0}, + {SASL_CB_LIST_END, 0, 0} + }; + +#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \ + || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19)) + int sasl_major; + int sasl_minor; + int sasl_step; + + /* + * DLL hell guard. + */ + sasl_version_info((const char **) 0, (const char **) 0, + &sasl_major, &sasl_minor, + &sasl_step, (int *) 0); + if (sasl_major != SASL_VERSION_MAJOR +#if 0 + || sasl_minor != SASL_VERSION_MINOR + || sasl_step != SASL_VERSION_STEP +#endif + ) { + msg_warn("incorrect SASL library version. " + "Postfix was built with include files from version %d.%d.%d, " + "but the run-time library version is %d.%d.%d", + SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP, + sasl_major, sasl_minor, sasl_step); + return (0); + } +#endif + + /* + * Initialize the SASL library. + */ + if ((sasl_status = sasl_client_init(callbacks)) != SASL_OK) { + msg_warn("SASL library initialization error: %s", + xsasl_cyrus_strerror(sasl_status)); + return (0); + } + + /* + * Return a generic XSASL_CLIENT_IMPL object. We don't need to extend it + * with our own methods or data. + */ + xp = (XSASL_CLIENT_IMPL *) mymalloc(sizeof(*xp)); + xp->create = xsasl_cyrus_client_create; + xp->done = xsasl_cyrus_client_done; + return (xp); +} + +/* xsasl_cyrus_client_done - dispose of implementation */ + +static void xsasl_cyrus_client_done(XSASL_CLIENT_IMPL *impl) +{ + myfree((char *) impl); + sasl_done(); +} + +/* xsasl_cyrus_client_create - per-session SASL initialization */ + +XSASL_CLIENT *xsasl_cyrus_client_create(XSASL_CLIENT_IMPL *unused_impl, + VSTREAM *stream, + const char *service, + const char *server, + const char *sec_props) +{ + XSASL_CYRUS_CLIENT *client = 0; + static sasl_callback_t callbacks[] = { + {SASL_CB_USER, &xsasl_cyrus_client_get_user, 0}, + {SASL_CB_AUTHNAME, &xsasl_cyrus_client_get_user, 0}, + {SASL_CB_PASS, &xsasl_cyrus_client_get_passwd, 0}, + {SASL_CB_LIST_END, 0, 0} + }; + sasl_conn_t *sasl_conn = 0; + sasl_callback_t *custom_callbacks = 0; + sasl_callback_t *cp; + int sasl_status; + + /* + * The optimizer will eliminate duplication and/or dead code. + */ +#define XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(x) \ + do { \ + if (client) { \ + xsasl_cyrus_client_free(&client->xsasl); \ + } else { \ + if (custom_callbacks) \ + myfree((char *) custom_callbacks); \ + if (sasl_conn) \ + sasl_dispose(&sasl_conn); \ + } \ + return (x); \ + } while (0) + + /* + * Per-session initialization. Provide each session with its own callback + * context. + */ +#define NULL_SECFLAGS 0 + + custom_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks)); + memcpy((char *) custom_callbacks, callbacks, sizeof(callbacks)); + +#define NULL_SERVER_ADDR ((char *) 0) +#define NULL_CLIENT_ADDR ((char *) 0) + + if ((sasl_status = SASL_CLIENT_NEW(service, server, + NULL_CLIENT_ADDR, NULL_SERVER_ADDR, + custom_callbacks, NULL_SECFLAGS, + &sasl_conn)) != SASL_OK) { + msg_warn("per-session SASL client initialization: %s", + xsasl_cyrus_strerror(sasl_status)); + XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(0); + } + + /* + * Extend XSASL_CLIENT_IMPL object with our own state. We use long-lived + * conversion buffers rather than local variables to avoid memory leaks + * in case of read/write timeout or I/O error. + * + * XXX If we enable SASL encryption, there needs to be a way to inform the + * application, so that they can turn off connection caching, refuse + * STARTTLS, etc. + */ + client = (XSASL_CYRUS_CLIENT *) mymalloc(sizeof(*client)); + client->xsasl.free = xsasl_cyrus_client_free; + client->xsasl.first = xsasl_cyrus_client_first; + client->xsasl.next = xsasl_cyrus_client_next; + client->stream = stream; + client->sasl_conn = sasl_conn; + client->callbacks = custom_callbacks; + client->decoded = vstring_alloc(20); + client->username = 0; + client->password = 0; + + for (cp = custom_callbacks; cp->id != SASL_CB_LIST_END; cp++) + cp->context = (void *) client; + + if (xsasl_cyrus_client_set_security(&client->xsasl, sec_props) + != XSASL_AUTH_OK) + XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(0); + + return (&client->xsasl); +} + +/* xsasl_cyrus_client_set_security - set security properties */ + +static int xsasl_cyrus_client_set_security(XSASL_CLIENT *xp, + const char *sasl_opts_val) +{ + XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp; + sasl_security_properties_t sec_props; + int sasl_status; + + /* + * Per-session security properties. XXX This routine is not sufficiently + * documented. What is the purpose of all this? + */ + memset(&sec_props, 0L, sizeof(sec_props)); + sec_props.min_ssf = 0; + sec_props.max_ssf = 0; /* don't allow real SASL + * security layer */ + if (*sasl_opts_val == 0) { + sec_props.security_flags = 0; + } else { + sec_props.security_flags = + xsasl_cyrus_security_parse_opts(sasl_opts_val); + if (sec_props.security_flags == 0) { + msg_warn("bad per-session SASL security properties"); + return (XSASL_AUTH_FAIL); + } + } + sec_props.maxbufsize = 0; + sec_props.property_names = 0; + sec_props.property_values = 0; + if ((sasl_status = sasl_setprop(client->sasl_conn, SASL_SEC_PROPS, + &sec_props)) != SASL_OK) { + msg_warn("set per-session SASL security properties: %s", + xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FAIL); + } + return (XSASL_AUTH_OK); +} + +/* xsasl_cyrus_client_first - run authentication protocol */ + +static int xsasl_cyrus_client_first(XSASL_CLIENT *xp, + const char *mechanism_list, + const char *username, + const char *password, + const char **mechanism, + VSTRING *init_resp) +{ + char *myname = "xsasl_cyrus_client_first"; + XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp; + unsigned enc_length; + unsigned enc_length_out; + CLIENTOUT_TYPE clientout; + unsigned clientoutlen; + int sasl_status; + +#define NO_SASL_SECRET 0 +#define NO_SASL_INTERACTION 0 + + /* + * Save the username and password for the call-backs. + */ + if (client->username) + myfree(client->username); + client->username = mystrdup(username); + if (client->password) + myfree(client->password); + client->password = mystrdup(password); + + /* + * Start the client side authentication protocol. + */ + sasl_status = SASL_CLIENT_START((sasl_conn_t *) client->sasl_conn, + mechanism_list, + NO_SASL_SECRET, NO_SASL_INTERACTION, + &clientout, &clientoutlen, mechanism); + if (sasl_status != SASL_OK && sasl_status != SASL_CONTINUE) { + vstring_strcpy(init_resp, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FAIL); + } + + /* + * Generate the AUTH command and the optional initial client response. + * sasl_encode64() produces four bytes for each complete or incomplete + * triple of input bytes. Allocate an extra byte for string termination. + */ +#define ENCODE64_LENGTH(n) ((((n) + 2) / 3) * 4) + + if (clientoutlen > 0) { + if (msg_verbose) { + escape(client->decoded, clientout, clientoutlen); + msg_info("%s: uncoded initial reply: %s", + myname, STR(client->decoded)); + } + enc_length = ENCODE64_LENGTH(clientoutlen) + 1; + VSTRING_RESET(init_resp); /* Fix 200512 */ + VSTRING_SPACE(init_resp, enc_length); + if ((sasl_status = sasl_encode64(clientout, clientoutlen, + STR(init_resp), + vstring_avail(init_resp), + &enc_length_out)) != SASL_OK) + msg_panic("%s: sasl_encode64 botch: %s", + myname, xsasl_cyrus_strerror(sasl_status)); + VSTRING_AT_OFFSET(init_resp, enc_length_out); /* XXX */ +#if SASL_VERSION_MAJOR < 2 + /* SASL version 1 doesn't free memory that it allocates. */ + free(clientout); +#endif + } else { + vstring_strcpy(init_resp, ""); + } + return (XSASL_AUTH_OK); +} + +/* xsasl_cyrus_client_next - continue authentication */ + +static int xsasl_cyrus_client_next(XSASL_CLIENT *xp, const char *server_reply, + VSTRING *client_reply) +{ + char *myname = "xsasl_cyrus_client_next"; + XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp; + unsigned enc_length; + unsigned enc_length_out; + CLIENTOUT_TYPE clientout; + unsigned clientoutlen; + unsigned serverinlen; + int sasl_status; + + /* + * Process a server challenge. + */ + serverinlen = strlen(server_reply); + VSTRING_RESET(client->decoded); /* Fix 200512 */ + VSTRING_SPACE(client->decoded, serverinlen); + if ((sasl_status = SASL_DECODE64(server_reply, serverinlen, + STR(client->decoded), + vstring_avail(client->decoded), + &enc_length)) != SASL_OK) { + vstring_strcpy(client_reply, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FORM); + } + if (msg_verbose) + msg_info("%s: decoded challenge: %.*s", + myname, (int) enc_length, STR(client->decoded)); + sasl_status = sasl_client_step(client->sasl_conn, STR(client->decoded), + enc_length, NO_SASL_INTERACTION, + &clientout, &clientoutlen); + if (sasl_status != SASL_OK && sasl_status != SASL_CONTINUE) { + vstring_strcpy(client_reply, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FAIL); + } + + /* + * Send a client response. + */ + if (clientoutlen > 0) { + if (msg_verbose) + msg_info("%s: uncoded client response %.*s", + myname, (int) clientoutlen, clientout); + enc_length = ENCODE64_LENGTH(clientoutlen) + 1; + VSTRING_RESET(client_reply); /* Fix 200512 */ + VSTRING_SPACE(client_reply, enc_length); + if ((sasl_status = sasl_encode64(clientout, clientoutlen, + STR(client_reply), + vstring_avail(client_reply), + &enc_length_out)) != SASL_OK) + msg_panic("%s: sasl_encode64 botch: %s", + myname, xsasl_cyrus_strerror(sasl_status)); +#if SASL_VERSION_MAJOR < 2 + /* SASL version 1 doesn't free memory that it allocates. */ + free(clientout); +#endif + } else { + /* XXX Can't happen. */ + vstring_strcpy(client_reply, ""); + } + return (XSASL_AUTH_OK); +} + +/* xsasl_cyrus_client_free - per-session cleanup */ + +void xsasl_cyrus_client_free(XSASL_CLIENT *xp) +{ + XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp; + + if (client->username) + myfree(client->username); + if (client->password) + myfree(client->password); + if (client->sasl_conn) + sasl_dispose(&client->sasl_conn); + myfree((char *) client->callbacks); + vstring_free(client->decoded); + myfree((char *) client); +} + +#endif diff --git a/postfix/src/xsasl/xsasl_cyrus_common.h b/postfix/src/xsasl/xsasl_cyrus_common.h new file mode 100644 index 000000000..544737822 --- /dev/null +++ b/postfix/src/xsasl/xsasl_cyrus_common.h @@ -0,0 +1,39 @@ +#ifndef _CYRUS_COMMON_H_INCLUDED_ +#define _CYRUS_COMMON_H_INCLUDED_ + +/*++ +/* NAME +/* cyrus_common 3h +/* SUMMARY +/* Cyrus SASL plug-in helpers +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * External interface. + */ +#if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL) + +#define NO_SASL_LANGLIST ((const char *) 0) +#define NO_SASL_OUTLANG ((const char **) 0) +#define xsasl_cyrus_strerror(status) \ + sasl_errstring((status), NO_SASL_LANGLIST, NO_SASL_OUTLANG) +extern int xsasl_cyrus_log(void *, int, const char *); +extern int xsasl_cyrus_security_parse_opts(const char *); + +#endif + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/xsasl/xsasl_cyrus_log.c b/postfix/src/xsasl/xsasl_cyrus_log.c new file mode 100644 index 000000000..7bf25c368 --- /dev/null +++ b/postfix/src/xsasl/xsasl_cyrus_log.c @@ -0,0 +1,104 @@ +/*++ +/* NAME +/* xsasl_cyrus_log 3 +/* SUMMARY +/* Cyrus SASL logging call-back routine +/* SYNOPSIS +/* #include +/* +/* int xsasl_cyrus_log(context, priority, text) +/* void *context; +/* int priority; +/* const char *text; +/* DESCRIPTION +/* xsasl_cyrus_log() logs a Cyrus message. +/* DIAGNOSTICS: +/* Fatal: out of memory. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include + +/* Utility library. */ + +#include + +/* Application-specific */ + +#include + +#if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL) + +#include +#include + +/* xsasl_cyrus_log - logging callback */ + +int xsasl_cyrus_log(void *unused_context, int priority, + const char *message) +{ + switch (priority) { + case SASL_LOG_ERR: /* unusual errors */ +#ifdef SASL_LOG_WARN /* non-fatal warnings (Cyrus-SASL v2) */ + case SASL_LOG_WARN: +#endif +#ifdef SASL_LOG_WARNING /* non-fatal warnings (Cyrus-SASL v1) */ + case SASL_LOG_WARNING: +#endif + msg_warn("SASL authentication problem: %s", message); + break; +#ifdef SASL_LOG_INFO + case SASL_LOG_INFO: /* other info (Cyrus-SASL v1) */ + if (msg_verbose) + msg_info("SASL authentication info: %s", message); + break; +#endif +#ifdef SASL_LOG_NOTE + case SASL_LOG_NOTE: /* other info (Cyrus-SASL v2) */ + if (msg_verbose) + msg_info("SASL authentication info: %s", message); + break; +#endif +#ifdef SASL_LOG_FAIL + case SASL_LOG_FAIL: /* authentication failures + * (Cyrus-SASL v2) */ + msg_warn("SASL authentication failure: %s", message); + break; +#endif +#ifdef SASL_LOG_DEBUG + case SASL_LOG_DEBUG: /* more verbose than LOG_NOTE + * (Cyrus-SASL v2) */ + if (msg_verbose > 1) + msg_info("SASL authentication debug: %s", message); + break; +#endif +#ifdef SASL_LOG_TRACE + case SASL_LOG_TRACE: /* traces of internal + * protocols (Cyrus-SASL v2) */ + if (msg_verbose > 1) + msg_info("SASL authentication trace: %s", message); + break; +#endif +#ifdef SASL_LOG_PASS + case SASL_LOG_PASS: /* traces of internal + * protocols, including + * passwords (Cyrus-SASL v2) */ + if (msg_verbose > 1) + msg_info("SASL authentication pass: %s", message); + break; +#endif + } + return (SASL_OK); +} + +#endif diff --git a/postfix/src/xsasl/xsasl_cyrus_security.c b/postfix/src/xsasl/xsasl_cyrus_security.c new file mode 100644 index 000000000..c4c6d44ec --- /dev/null +++ b/postfix/src/xsasl/xsasl_cyrus_security.c @@ -0,0 +1,82 @@ +/*++ +/* NAME +/* xsasl_cyrus_security 3 +/* SUMMARY +/* convert Cyrus SASL security properties to bit mask +/* SYNOPSIS +/* #include +/* +/* int xsasl_cyrus_security_parse_opts(properties) +/* const char *properties; +/* DESCRIPTION +/* xsasl_cyrus_security_parse_opts() converts a list of security +/* properties to a bit mask. The result is zero in case of error. +/* +/* Arguments: +/* .IP properties +/* A comma or space separated list of zero or more of the +/* following: +/* .RS +/* .IP noplaintext +/* Disallow authentication methods that use plaintext passwords. +/* .IP noactive +/* Disallow authentication methods that are vulnerable to +/* non-dictionary active attacks. +/* .IP nodictionary +/* Disallow authentication methods that are vulnerable to +/* passive dictionary attack. +/* .IP noanonymous +/* Disallow anonymous logins. +/* .RE +/* DIAGNOSTICS: +/* Warning: bad input. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include + +/* Utility library. */ + +#include + +/* Application-specific. */ + +#include + +#if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL) + +#include + + /* + * SASL Security options. + */ +static NAME_MASK xsasl_cyrus_sec_mask[] = { + "noplaintext", SASL_SEC_NOPLAINTEXT, + "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, +}; + +/* xsasl_cyrus_security - parse security options */ + +int xsasl_cyrus_security_parse_opts(const char *sasl_opts_val) +{ + return (name_mask_opt("SASL security options", xsasl_cyrus_sec_mask, + sasl_opts_val, NAME_MASK_RETURN)); +} + +#endif diff --git a/postfix/src/xsasl/xsasl_cyrus_server.c b/postfix/src/xsasl/xsasl_cyrus_server.c new file mode 100644 index 000000000..40147e48b --- /dev/null +++ b/postfix/src/xsasl/xsasl_cyrus_server.c @@ -0,0 +1,599 @@ +/*++ +/* NAME +/* xsasl_cyrus_server 3 +/* SUMMARY +/* Cyrus SASL server-side plug-in +/* SYNOPSIS +/* #include +/* +/* XSASL_SERVER_IMPL *xsasl_cyrus_server_init(server_type, path_info) +/* const char *server_type; +/* const char *path_info; +/* DESCRIPTION +/* This module implements the Cyrus SASL server-side authentication +/* plug-in. +/* +/* xsasl_cyrus_server_init() initializes the Cyrus SASL library and +/* returns an implementation handle that can be used to generate +/* SASL server instances. +/* +/* Arguments: +/* .IP server_type +/* The server type (cyrus). This argument is ignored, but it +/* could be used when one implementation provides multiple +/* variants. +/* .IP path_info +/* The base name of the SASL server configuration file (example: +/* smtpd becomes /usr/lib/sasl2/smtpd.conf). +/* DIAGNOSTICS +/* Fatal: out of memory. +/* +/* Panic: interface violation. +/* +/* Other: the routines log a warning and return an error result +/* as specified in xsasl_server(3). +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Initial implementation by: +/* Till Franke +/* SuSE Rhein/Main AG +/* 65760 Eschborn, Germany +/* +/* Adopted by: +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include + +/* Global library. */ + +#include + +/* Application-specific. */ + +#include +#include +#include + +#if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL) + +#include +#include + +/* + * Silly little macros. + */ +#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_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) +typedef char *MECHANISM_TYPE; +typedef unsigned MECHANISM_COUNT_TYPE; +typedef char *SERVEROUT_TYPE; +typedef void *VOID_SERVEROUT_TYPE; + +#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) +typedef const char *MECHANISM_TYPE; +typedef int MECHANISM_COUNT_TYPE; +typedef const char *SERVEROUT_TYPE; +typedef const void *VOID_SERVEROUT_TYPE; + +#endif + + /* + * The XSASL_CYRUS_SERVER object is derived from the generic XSASL_SERVER + * object. + */ +typedef struct { + XSASL_SERVER xsasl; /* generic members, must be first */ + VSTREAM *stream; /* client-server connection */ + sasl_conn_t *sasl_conn; /* SASL context */ + VSTRING *decoded; /* decoded challenge or response */ + char *username; /* authenticated user */ + char *mechanism_list; /* applicable mechanisms */ +} XSASL_CYRUS_SERVER; + + /* + * Forward declarations. + */ +static void xsasl_cyrus_server_done(XSASL_SERVER_IMPL *); +static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *, + VSTREAM *, + const char *, + const char *, + const char *); +static void xsasl_cyrus_server_free(XSASL_SERVER *); +static int xsasl_cyrus_server_first(XSASL_SERVER *, const char *, + const char *, VSTRING *); +static int xsasl_cyrus_server_next(XSASL_SERVER *, const char *, VSTRING *); +static int xsasl_cyrus_server_set_security(XSASL_SERVER *, const char *); +static const char *xsasl_cyrus_server_get_mechanism_list(XSASL_SERVER *); +static const char *xsasl_cyrus_server_get_username(XSASL_SERVER *); + + /* + * SASL callback interface structure. These call-backs have no per-session + * context. + */ +#define NO_CALLBACK_CONTEXT 0 + +static sasl_callback_t callbacks[] = { + {SASL_CB_LOG, &xsasl_cyrus_log, NO_CALLBACK_CONTEXT}, + {SASL_CB_LIST_END, 0, 0} +}; + +/* xsasl_cyrus_server_init - create implementation handle */ + +XSASL_SERVER_IMPL *xsasl_cyrus_server_init(const char *unused_server_type, + const char *path_info) +{ + const char *myname = "xsasl_cyrus_server_init"; + XSASL_SERVER_IMPL *xp; + int sasl_status; + +#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \ + || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19)) + int sasl_major; + int sasl_minor; + int sasl_step; + + /* + * DLL hell guard. + */ + sasl_version_info((const char **) 0, (const char **) 0, + &sasl_major, &sasl_minor, + &sasl_step, (int *) 0); + if (sasl_major != SASL_VERSION_MAJOR +#if 0 + || sasl_minor != SASL_VERSION_MINOR + || sasl_step != SASL_VERSION_STEP +#endif + ) { + msg_warn("incorrect SASL library version. " + "Postfix was built with include files from version %d.%d.%d, " + "but the run-time library version is %d.%d.%d", + SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP, + sasl_major, sasl_minor, sasl_step); + return (0); + } +#endif + + /* + * Initialize the library: load SASL plug-in routines, etc. + */ + if (msg_verbose) + msg_info("%s: SASL config file is %s.conf", myname, path_info); + if ((sasl_status = sasl_server_init(callbacks, path_info)) != SASL_OK) { + msg_warn("SASL per-process initialization failed: %s", + xsasl_cyrus_strerror(sasl_status)); + return (0); + } + + /* + * Return a generic XSASL_SERVER_IMPL object. We don't need to extend it + * with our own methods or data. + */ + xp = (XSASL_SERVER_IMPL *) mymalloc(sizeof(*xp)); + xp->create = xsasl_cyrus_server_create; + xp->done = xsasl_cyrus_server_done; + return (xp); +} + +/* xsasl_cyrus_server_done - dispose of implementation */ + +static void xsasl_cyrus_server_done(XSASL_SERVER_IMPL *impl) +{ + myfree((char *) impl); + sasl_done(); +} + +/* xsasl_cyrus_server_create - create server instance */ + +static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, + VSTREAM *stream, + const char *service, + const char *realm, + const char *sec_props) +{ + const char *myname = "xsasl_cyrus_server_create"; + char *server_address; + char *client_address; + sasl_conn_t *sasl_conn = 0; + XSASL_CYRUS_SERVER *server = 0; + int sasl_status; + + if (msg_verbose) + msg_info("%s: SASL service=%s, realm=%s", + myname, service, realm ? realm : "(null)"); + + /* + * The optimizer will eliminate duplication and/or dead code. + */ +#define XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(x) \ + do { \ + if (server) { \ + xsasl_cyrus_server_free(&server->xsasl); \ + } else { \ + if (sasl_conn) \ + sasl_dispose(&sasl_conn); \ + } \ + return (x); \ + } while (0) + + /* + * Set up a new server context. + */ +#define NO_SECURITY_LAYERS (0) +#define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0) +#define NO_AUTH_REALM ((char *) 0) + +#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_status = + SASL_SERVER_NEW(service, var_myhostname, + realm ? realm : NO_AUTH_REALM, + server_address, client_address, + NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS, + &sasl_conn)) != SASL_OK) { + msg_warn("SASL per-connection server initialization: %s", + xsasl_cyrus_strerror(sasl_status)); + XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0); + } + + /* + * Extend the XSASL_SERVER_IMPL object with our own data. We use + * long-lived conversion buffers rather than local variables to avoid + * memory leaks in case of read/write timeout or I/O error. + */ + server = (XSASL_CYRUS_SERVER *) mymalloc(sizeof(*server)); + server->xsasl.free = xsasl_cyrus_server_free; + server->xsasl.first = xsasl_cyrus_server_first; + server->xsasl.next = xsasl_cyrus_server_next; + server->xsasl.get_mechanism_list = xsasl_cyrus_server_get_mechanism_list; + server->xsasl.get_username = xsasl_cyrus_server_get_username; + server->stream = stream; + server->sasl_conn = sasl_conn; + server->decoded = vstring_alloc(20); + server->username = 0; + server->mechanism_list = 0; + + if (xsasl_cyrus_server_set_security(&server->xsasl, sec_props) + != XSASL_AUTH_OK) + XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0); + + return (&server->xsasl); +} + +/* xsasl_cyrus_server_set_security - set security properties */ + +static int xsasl_cyrus_server_set_security(XSASL_SERVER *xp, + const char *sasl_opts_val) +{ + XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; + sasl_security_properties_t sec_props; + int sasl_status; + + /* + * Security options. Some information can be found in the sasl.h include + * file. + */ + memset(&sec_props, 0, sizeof(sec_props)); + sec_props.min_ssf = 0; + sec_props.max_ssf = 0; /* don't allow real SASL + * security layer */ + if (*sasl_opts_val == 0) { + sec_props.security_flags = 0; + } else { + sec_props.security_flags = + xsasl_cyrus_security_parse_opts(sasl_opts_val); + if (sec_props.security_flags == 0) { + msg_warn("bad per-session SASL security properties"); + return (XSASL_AUTH_FAIL); + } + } + sec_props.maxbufsize = 0; + sec_props.property_names = 0; + sec_props.property_values = 0; + + if ((sasl_status = sasl_setprop(server->sasl_conn, SASL_SEC_PROPS, + &sec_props)) != SASL_OK) { + msg_warn("SASL per-connection security setup; %s", + xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FAIL); + } + return (XSASL_AUTH_OK); +} + +/* xsasl_cyrus_server_get_mechanism_list - get available mechanisms */ + +static const char *xsasl_cyrus_server_get_mechanism_list(XSASL_SERVER *xp) +{ + const char *myname = "xsasl_cyrus_server_get_mechanism_list"; + XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; + MECHANISM_TYPE mechanism_list; + MECHANISM_COUNT_TYPE mechanism_count; + int sasl_status; + + /* + * Get the list of authentication mechanisms. + */ +#define UNSUPPORTED_USER ((char *) 0) +#define IGNORE_MECHANISM_LEN ((unsigned *) 0) + + if ((sasl_status = sasl_listmech(server->sasl_conn, UNSUPPORTED_USER, + "", " ", "", + &mechanism_list, + IGNORE_MECHANISM_LEN, + &mechanism_count)) != SASL_OK) { + msg_warn("%s: %s", myname, xsasl_cyrus_strerror(sasl_status)); + return (0); + } + if (mechanism_count <= 0) { + msg_warn("%s: no applicable SASL mechanisms", myname); + return (0); + } + server->mechanism_list = mystrdup(mechanism_list); +#if SASL_VERSION_MAJOR < 2 + /* SASL version 1 doesn't free memory that it allocates. */ + free(mechanism_list); +#endif + return (server->mechanism_list); +} + +/* xsasl_cyrus_server_free - destroy server instance */ + +static void xsasl_cyrus_server_free(XSASL_SERVER *xp) +{ + XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; + + sasl_dispose(&server->sasl_conn); + vstring_free(server->decoded); + if (server->username) + myfree(server->username); + if (server->mechanism_list) + myfree(server->mechanism_list); + myfree((char *) server); +} + +/* xsasl_cyrus_server_auth_response - encode server first/next response */ + +static int xsasl_cyrus_server_auth_response(int sasl_status, + SERVEROUT_TYPE serverout, + unsigned serveroutlen, + VSTRING *reply) +{ + const char *myname = "xsasl_cyrus_server_auth_response"; + unsigned enc_length; + unsigned enc_length_out; + + /* + * Encode the server first/next non-error response; otherwise return the + * unencoded error text that corresponds to the SASL error status. + * + * Regarding the hairy expression below: output from sasl_encode64() comes + * in multiples of four bytes for each triple of input bytes, plus four + * bytes for any incomplete last triple, plus one byte for the null + * terminator. + */ + if (sasl_status == SASL_OK) { + vstring_strcpy(reply, ""); + return (XSASL_AUTH_DONE); + } else if (sasl_status == SASL_CONTINUE) { + if (msg_verbose) + msg_info("%s: uncoded server challenge: %.*s", + myname, (int) serveroutlen, serverout); + enc_length = ((serveroutlen + 2) / 3) * 4 + 1; + VSTRING_RESET(reply); /* Fix 200512 */ + VSTRING_SPACE(reply, enc_length); + if ((sasl_status = sasl_encode64(serverout, serveroutlen, + STR(reply), vstring_avail(reply), + &enc_length_out)) != SASL_OK) + msg_panic("%s: sasl_encode64 botch: %s", + myname, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_MORE); + } else { + vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FAIL); + } +} + +/* xsasl_cyrus_server_first - per-session authentication */ + +int xsasl_cyrus_server_first(XSASL_SERVER *xp, const char *sasl_method, + const char *init_response, VSTRING *reply) +{ + char *myname = "xsasl_cyrus_server_first"; + XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; + char *dec_buffer; + unsigned dec_length; + unsigned reply_len; + unsigned serveroutlen; + int sasl_status; + SERVEROUT_TYPE serverout = 0; + int xsasl_status; + +#if SASL_VERSION_MAJOR < 2 + const char *errstr = 0; + +#endif + +#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3)) + + if (msg_verbose) + msg_info("%s: sasl_method %s%s%s", myname, sasl_method, + IFELSE(init_response, ", init_response ", ""), + IFELSE(init_response, init_response, "")); + + /* + * SASL authentication protocol start-up. Process any initial client + * response that was sent along in the AUTH command. + */ + if (init_response) { + reply_len = strlen(init_response); + VSTRING_RESET(server->decoded); /* Fix 200512 */ + VSTRING_SPACE(server->decoded, reply_len); + if ((sasl_status = SASL_DECODE64(init_response, reply_len, + dec_buffer = STR(server->decoded), + vstring_avail(server->decoded), + &dec_length)) != SASL_OK) { + vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FORM); + } + if (msg_verbose) + msg_info("%s: decoded initial response %s", myname, dec_buffer); + } else { + dec_buffer = 0; + dec_length = 0; + } + sasl_status = SASL_SERVER_START(server->sasl_conn, sasl_method, dec_buffer, + dec_length, &serverout, + &serveroutlen, &errstr); + xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout, + serveroutlen, reply); +#if SASL_VERSION_MAJOR < 2 + /* SASL version 1 doesn't free memory that it allocates. */ + free(serverout); +#endif + return (xsasl_status); +} + +/* xsasl_cyrus_server_next - continue authentication */ + +static int xsasl_cyrus_server_next(XSASL_SERVER *xp, const char *request, + VSTRING *reply) +{ + char *myname = "xsasl_cyrus_server_next"; + XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; + unsigned dec_length; + unsigned request_len; + unsigned serveroutlen; + int sasl_status; + SERVEROUT_TYPE serverout = 0; + int xsasl_status; + +#if SASL_VERSION_MAJOR < 2 + const char *errstr = 0; + +#endif + + request_len = strlen(request); + VSTRING_RESET(server->decoded); /* Fix 200512 */ + VSTRING_SPACE(server->decoded, request_len); + if ((sasl_status = SASL_DECODE64(request, request_len, + STR(server->decoded), + vstring_avail(server->decoded), + &dec_length)) != SASL_OK) { + vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); + return (XSASL_AUTH_FORM); + } + if (msg_verbose) + msg_info("%s: decoded response: %.*s", + myname, (int) dec_length, STR(server->decoded)); + sasl_status = SASL_SERVER_STEP(server->sasl_conn, STR(server->decoded), + dec_length, &serverout, + &serveroutlen, &errstr); + xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout, + serveroutlen, reply); +#if SASL_VERSION_MAJOR < 2 + /* SASL version 1 doesn't free memory that it allocates. */ + free(serverout); +#endif + return (xsasl_status); +} + +/* xsasl_cyrus_server_get_username - get authenticated username */ + +static const char *xsasl_cyrus_server_get_username(XSASL_SERVER *xp) +{ + const char *myname = "xsasl_cyrus_server_get_username"; + XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; + VOID_SERVEROUT_TYPE serverout = 0; + int sasl_status; + + /* + * XXX Do not free(serverout). + */ + sasl_status = sasl_getprop(server->sasl_conn, SASL_USERNAME, &serverout); + if (sasl_status != SASL_OK || serverout == 0) { + msg_warn("%s: sasl_getprop SASL_USERNAME botch: %s", + myname, xsasl_cyrus_strerror(sasl_status)); + return (0); + } + if (server->username) + myfree(server->username); + server->username = mystrdup(serverout); + printable(server->username, '?'); + return (server->username); +} + +#endif diff --git a/postfix/src/xsasl/xsasl_server.c b/postfix/src/xsasl/xsasl_server.c new file mode 100644 index 000000000..729cb46e6 --- /dev/null +++ b/postfix/src/xsasl/xsasl_server.c @@ -0,0 +1,228 @@ +/*++ +/* NAME +/* xsasl-server 3 +/* SUMMARY +/* Postfix SASL server plug-in interface +/* SYNOPSIS +/* #include +/* +/* XSASL_SERVER_IMPL *xsasl_server_init(server_type, path_info) +/* const char *server_type; +/* const char *path_info; +/* +/* void xsasl_server_done(implementation) +/* XSASL_SERVER_IMPL *implementation; +/* +/* ARGV *xsasl_server_types() +/* +/* XSASL_SERVER *xsasl_server_create(implementation, stream, service, +/* user_realm, security_options) +/* XSASL_SERVER_IMPL *implementation; +/* const char *service; +/* VSTREAM *stream; +/* const char *user_realm; +/* const char *security_options; +/* +/* void xsasl_server_free(server) +/* XSASL_SERVER *server; +/* +/* int xsasl_server_first(server, auth_method, init_resp, server_reply) +/* XSASL_SERVER *server; +/* const char *auth_method; +/* const char *init_resp; +/* VSTRING *server_reply; +/* +/* int xsasl_server_next(server, client_request, server_reply) +/* XSASL_SERVER *server; +/* const char *client_request; +/* VSTRING *server_reply; +/* +/* const char *xsasl_server_get_mechanism_list(server) +/* XSASL_SERVER *server; +/* +/* const char *xsasl_server_get_username(server) +/* XSASL_SERVER *server; +/* DESCRIPTION +/* The XSASL_SERVER abstraction implements a generic interface +/* to one or more SASL authentication implementations. +/* +/* xsasl_server_init() is called once during process initialization. +/* It selects a SASL implementation by name, specifies the +/* location of a configuration file or rendez-vous point, and +/* returns an implementation handle that can be used to generate +/* SASL server instances. This function is typically used to +/* initialize the underlying implementation. +/* +/* xsasl_server_done() disposes of an implementation handle, +/* and allows the underlying implementation to release resources. +/* +/* xsasl_server_types() lists the available implementation types. +/* The result should be destroyed by the caller. +/* +/* xsasl_server_create() is called at the start of an SMTP +/* session. It generates a Postfix SASL plug-in server instance +/* for the specified service and authentication realm, and +/* with the specified security properties. Specify a null +/* pointer when no realm should be used. The stream handle is +/* stored so that encryption can be turned on after successful +/* negotiations. +/* +/* xsasl_server_free() is called at the end of an SMTP session. +/* It destroys a SASL server instance, and disables further +/* read/write operations if encryption was turned on. +/* +/* xsasl_server_first() produces the server reponse for the +/* client AUTH command. The client input are an authentication +/* method, and an optional initial response or null pointer. +/* The initial response and server non-error replies are BASE64 +/* encoded. Server error replies are 7-bit ASCII text without +/* control characters, without BASE64 encoding, and without +/* SMTP reply code or enhanced status code. +/* +/* The result is one of the following: +/* .IP XSASL_AUTH_MORE +/* More client input is needed. The server reply specifies +/* what. +/* .IP XSASL_AUTH_DONE +/* Authentication completed successfully. +/* .IP XSASL_AUTH_FORM +/* The client input is incorrectly formatted. The server error +/* reply explains why. +/* .IP XSASL_AUTH_FAIL +/* Authentication failed. The server error reply explains why. +/* .PP +/* xsasl_server_next() supports the subsequent stages of the +/* client-server AUTH protocol. Both the client input and +/* server non-error responses are BASE64 encoded. See +/* xsasl_server_first() for other details. +/* +/* xsasl_server_get_mechanism_list() returns the authentication +/* mechanisms that match the security properties, as a white-space +/* separated list. This is meant to be used in the SMTP EHLO +/* reply. +/* +/* xsasl_server_get_username() returns the stored username +/* after successful authentication. +/* +/* Arguments: +/* .IP auth_method +/* AUTH command authentication method. +/* .IP init_resp +/* AUTH command initial response or null pointer. +/* .IP implementation +/* Implementation handle that was obtained with xsasl_server_init(). +/* .IP path_info +/* The value of the smtpd_sasl_path parameter or equivalent. +/* This specifies the implementation-dependent location of a +/* configuration file, rendez-vous point, etc., and is passed +/* unchanged to the plug-in. +/* .IP security_options +/* The value of the smtpd_security_options parameter or +/* equivalent. This is passed unchanged to the plug-in. +/* .IP server +/* SASL plug-in server handle. +/* .IP server_reply +/* BASE64 encoded server non-error reply (without SMTP reply +/* code or enhanced status code), or ASCII error description. +/* .IP server_type +/* The name of a Postfix SASL server plug_in implementation. +/* .IP server_types +/* Null-terminated array of strings with SASL server plug-in +/* implementation names. +/* .IP service +/* The service that is implemented by the local server, typically +/* "smtp" or "lmtp". +/* .IP stream +/* The connection between client and server. When SASL +/* encryption is negotiated, the plug-in will transparently +/* intercept the socket read/write operations. +/* .IP user_realm +/* Authentication domain or null pointer. +/* SECURITY +/* .ad +/* .fi +/* The caller does not sanitize client input. It is the +/* responsibility of the underlying SASL server implementation +/* to produce 7-bit ASCII without control characters as server +/* non-error and error replies, and as the result from +/* xsasl_server_method() and xsasl_server_username(). +/* DIAGNOSTICS +/* In case of failure, xsasl_server_init(), xsasl_server_create(), +/* xsasl_server_get_mechanism_list() and xsasl_server_get_username() +/* log a warning and return a null pointer. +/* +/* Functions that normally return XSASL_AUTH_OK will log a warning +/* and return an appropriate result value. +/* +/* Fatal errors: out of memory. +/* +/* Panic: interface violations. +/* SEE ALSO +/* cyrus_security(3) Cyrus SASL security features +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this +/* software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include + +/* Utility library. */ + +#include +#include + +/* SASL implementations. */ + +#include +#include + + /* + * Lookup table for available SASL server implementations. + */ +typedef struct { + char *server_type; + struct XSASL_SERVER_IMPL *(*server_init) (const char *, const char *); +} XSASL_SERVER_IMPL_INFO; + +static XSASL_SERVER_IMPL_INFO server_impl_info[] = { +#ifdef XSASL_TYPE_CYRUS + XSASL_TYPE_CYRUS, xsasl_cyrus_server_init, +#endif + 0, +}; + +/* xsasl_server_init - look up server implementation by name */ + +XSASL_SERVER_IMPL *xsasl_server_init(const char *server_type, + const char *path_info) +{ + XSASL_SERVER_IMPL_INFO *xp; + + for (xp = server_impl_info; xp->server_type; xp++) + if (strcmp(server_type, xp->server_type) == 0) + return (xp->server_init(server_type, path_info)); + msg_warn("unsupported SASL server implementation: %s", server_type); + return (0); +} + +/* xsasl_server_types - report available implementation types */ + +ARGV *xsasl_server_types(void) +{ + XSASL_SERVER_IMPL_INFO *xp; + ARGV *argv = argv_alloc(1); + + for (xp = server_impl_info; xp->server_type; xp++) + argv_add(argv, xp->server_type, ARGV_END); + return (argv); +}