]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20000316
authorWietse Venema <wietse@porcupine.org>
Thu, 16 Mar 2000 00:00:00 +0000 (00:00 +0000)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:10:14 +0000 (18:10 -0500)
90 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/Makefile
postfix/Makefile.in
postfix/Makefile.init
postfix/RELEASE_NOTES
postfix/SASL_README [new file with mode: 0644]
postfix/bounce/.indent.pro
postfix/bounce/Makefile.in
postfix/cleanup/.indent.pro
postfix/cleanup/Makefile.in
postfix/cleanup/cleanup_message.c
postfix/conf/sample-auth.cf [new file with mode: 0644]
postfix/conf/sample-tls.cf [new file with mode: 0644]
postfix/dns/.indent.pro
postfix/dns/Makefile.in
postfix/error/.indent.pro
postfix/error/Makefile.in
postfix/fsstone/.indent.pro
postfix/fsstone/Makefile.in
postfix/global/.indent.pro
postfix/global/Makefile.in
postfix/global/mail_params.h
postfix/global/mail_version.h
postfix/html/faq.html
postfix/local/.indent.pro
postfix/local/Makefile.in
postfix/makedefs
postfix/master/.indent.pro
postfix/master/Makefile.in
postfix/pickup/.indent.pro
postfix/pickup/Makefile.in
postfix/pipe/.indent.pro
postfix/pipe/Makefile.in
postfix/postalias/.indent.pro
postfix/postalias/Makefile.in
postfix/postcat/.indent.pro
postfix/postcat/Makefile.in
postfix/postconf/.indent.pro
postfix/postconf/Makefile.in
postfix/postconf/extract.awk
postfix/postdrop/.indent.pro
postfix/postdrop/Makefile.in
postfix/postfix/.indent.pro
postfix/postfix/Makefile.in
postfix/postkick/.indent.pro
postfix/postkick/Makefile.in
postfix/postlock/.indent.pro
postfix/postlock/Makefile.in
postfix/postlog/.indent.pro
postfix/postlog/Makefile.in
postfix/postmap/.indent.pro
postfix/postmap/Makefile.in
postfix/postsuper/.indent.pro
postfix/postsuper/Makefile.in
postfix/qmgr/.indent.pro
postfix/qmgr/Makefile.in
postfix/sendmail/.indent.pro
postfix/sendmail/Makefile.in
postfix/sendmail/sendmail.c
postfix/showq/.indent.pro
postfix/showq/Makefile.in
postfix/smtp/.indent.pro
postfix/smtp/Makefile.in
postfix/smtp/smtp.c
postfix/smtp/smtp.h
postfix/smtp/smtp_proto.c
postfix/smtp/smtp_sasl.h [new file with mode: 0644]
postfix/smtp/smtp_sasl_glue.c [new file with mode: 0644]
postfix/smtp/smtp_sasl_proto.c [new file with mode: 0644]
postfix/smtp/smtp_state.c
postfix/smtpd/.indent.pro
postfix/smtpd/Makefile.in
postfix/smtpd/smtpd.c
postfix/smtpd/smtpd.h
postfix/smtpd/smtpd_check.c
postfix/smtpd/smtpd_sasl_glue.c [new file with mode: 0644]
postfix/smtpd/smtpd_sasl_glue.h [new file with mode: 0644]
postfix/smtpd/smtpd_sasl_proto.c [new file with mode: 0644]
postfix/smtpd/smtpd_sasl_proto.h [new file with mode: 0644]
postfix/smtpd/smtpd_state.c
postfix/smtpstone/.indent.pro
postfix/smtpstone/Makefile.in
postfix/spawn/.indent.pro
postfix/spawn/Makefile.in
postfix/trivial-rewrite/.indent.pro
postfix/trivial-rewrite/Makefile.in
postfix/util/.indent.pro
postfix/util/Makefile.in
postfix/util/dict_open.c

index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 58fd9eb637562a2d57314a59def845778ba16eb8..d627a1b8516cbb6e9ce9017e34d6863e054e9987 100644 (file)
@@ -3743,3 +3743,33 @@ Apologies for any names omitted.
        The recipient counts provides an initial estimate for a
        more advanced queue manager scheduling algorithm. Files:
        cleanup/cleanup_envelope.c, cleanup/cleanup_extracted.c.
+
+20000311
+
+       Portability: HP-UX awk can't handle bare { in regexps
+       (Lamont Jones. HP). File: postconf/extract.awk.
+
+       Compatibility: sendmail now recognizes '.' as end of input.
+       File: sendmail/sendmail.c.
+
+20000313
+
+       Compatibility: dtcm (CDE desktop calendar manager) leaks
+       a file descriptor into its child process, and requires that
+       sendmail closes the descriptor, otherwise mail notification
+       will hang.  These GUI programmers never figured out that
+       the child process must close the writing ed of a pipe.
+       File:  sendmail/sendmail.c.
+
+20000314
+
+       Feature: SASL authentication in the SMTP server and client.
+       Based on code contributed by Till Franke, SuSE.  Specify:
+       "smtpd_sasl_auth_enable = yes" and "smtp_sasl_auth_enable
+       = yes". The "permit_sasl_authenticated" UCE restriction
+       gives special treatment to authenticated clients.
+
+20000315
+
+       Workaround: added -blibpath option for AIX 4.x, to close
+       hole in case postdrop needs to be set-gid.
index 424db7120881a2df273a11b1569317d1fa7e3357..8d9e069d9873405b0e885bdd3ce021c74e008692 100644 (file)
@@ -12,7 +12,7 @@ SHELL = /bin/sh
 default: update
 
 update depend printfck clean tidy depend_update: Makefiles
-       $(MAKE) $@
+       $(MAKE) MAKELEVEL= $@
 
 makefiles Makefiles:
-       $(MAKE) -f Makefile.in Makefiles
+       $(MAKE) -f Makefile.in MAKELEVEL= Makefiles
index ec3d76ba38c8936be8d43b2f5eec3798b8ab92c1..7bf601f1c94a346938b6588f0d54918a71a1b0ed 100644 (file)
@@ -36,6 +36,14 @@ depend_update:
            || exit 1; \
        done
 
+cleanmakefiles:
+       set -e; for i in $(DIRS); do \
+       (set -e; echo "[$$i]"; cd $$i; rm -f Makefile; \
+       ../cleanup_makefile.pl Makefile.in >Makefile.new; \
+       rm Makefile.in ; mv Makefile.new Makefile.in); \
+       done;
+       rm -f Makefile; (set -e; sh makedefs; cat Makefile.in) >Makefile
+
 tidy:  clean
        rm -f Makefile */Makefile
        cp Makefile.init Makefile
index 424db7120881a2df273a11b1569317d1fa7e3357..8d9e069d9873405b0e885bdd3ce021c74e008692 100644 (file)
@@ -12,7 +12,7 @@ SHELL = /bin/sh
 default: update
 
 update depend printfck clean tidy depend_update: Makefiles
-       $(MAKE) $@
+       $(MAKE) MAKELEVEL= $@
 
 makefiles Makefiles:
-       $(MAKE) -f Makefile.in Makefiles
+       $(MAKE) -f Makefile.in MAKELEVEL= Makefiles
index c83265f39fb9b3a90371ef5574b850568d730baa..bdcdaedc4ee2de535b024c9912ad5a0d47ead3e2 100644 (file)
@@ -5,6 +5,10 @@ This release is mainly to have a reference point after reorganizing
 the cleanup daemon, and before adding some major contributions from
 other people.
 
+The sendmail command now treats a `.' line as end of input, for
+the sake of compatibility. To revert to past behavior, specify the
+`-i' or `-oi' command-line flags.
+
 Major changes with snapshot-20000309
 ====================================
 
diff --git a/postfix/SASL_README b/postfix/SASL_README
new file mode 100644 (file)
index 0000000..de366bc
--- /dev/null
@@ -0,0 +1,74 @@
+Introduction
+============
+
+The Postfix SASL support according to RFC 2554 was originally
+implemented by Till Franke of SuSE Rhein/Main AG.  The present code
+is a trimmed-down implementation of only the bare necessities for
+SMTP clients and servers. When receiving mail, Postfix logs the
+client-provided username and sender address to the maillog file,
+but does not include that information in message headers.
+
+Building the SASL library
+=========================
+
+Postfix appears to work with cyrus-sasl-1.5.5, which is available
+from:
+
+    ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/
+
+Other SASL libraries may require some changes. All the library
+specific code is in smtp_sasl_glue.c and in smtpd_sasl_glue.c.
+
+Building Postfix with SASL authentication support
+=================================================
+
+To build Postfix with SASL authentication support, given that the
+SASL include files are in /usr/local/include, and that the SASL
+libraries are in /usr/local/lib:
+
+    % make makefiles CCARGS=-DUSE_SASL_AUTH" -I/usr/local/include" \
+       AUXLIBS="-L/usr/local/lib -lsasl"
+
+Enabling SASL authentication in the SMTP server
+===============================================
+
+See conf/sample-sasl.cf for examples. 
+
+    /etc/postfix/main.cf:
+       smtpd_sasl_auth_enable = yes
+
+In order to allow mail relaying by authenticated clients:
+
+    /etc/postfix/main.cf:
+       smtpd_recipient_restrictions = 
+           permit_mynetworks permit_sasl_authenticated ...
+
+In usr/local/lib/sasl/smtpd.conf you need to specify what authentication
+mechanisms the server will support, for example:
+
+    pwcheck_method:  {PAM, kerberos_v4, passwd, shadow, sasldb}
+
+/etc/sasldb is a db (dbm) database. IN order to make all this work
+with chrooted operation, you may have to copy files into chroot
+jail: password files, PAM libraries, etc.
+
+If PAM is used, the PAM service name is `smtp'.  The SASL service
+name is `smtp', too.
+
+Enabling SASL authentication in the SMTP client
+===============================================
+
+Turn on client-side SASl authentication, and specify a table with
+per-host username and password information.
+
+    /etc/postfix/main.cf:
+       smtp_sasl_auth_enable = yes
+       smtp_sasl_passwd_maps = hash:/etc/postfix/sasl_passwd
+
+    /etc/postfix/sasl_passwd:
+       host.domain     username:password
+       host.domain     username
+
+The SASL password file is opened before the SMTP server enters the
+optional chroot jail, so there is no need to copy the sasl_passwd
+file.
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 44d5b7ed2841607f6826383457c4e3aa401f6aef..1298eee4564fd6d5744f1149c89078210ea00c19 100644 (file)
@@ -53,7 +53,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 bounce.o: bounce.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 073c93006422fa3abd6f172106ffe8909b10e1c0..8b1da52c82158bf6067e0414e2e3c037a281ceb3 100644 (file)
@@ -57,7 +57,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 cleanup.o: cleanup.c
index c9a48f11c2839e01c9ccadef51364e268d0bf095..2c62763575e852b16747275078aecd915e74c285 100644 (file)
@@ -375,6 +375,22 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
                               state->resent, vstring_str(state->temp1));
        }
     }
+#ifdef USE_AUTH
+    /*
+     * Add client and sender identity headers if configured
+     */
+    if (cleanup_auth_client_identity && *var_cleanup_auth_client_header) {
+           cleanup_out_format(REC_TYPE_NORM, "%s %s@%s",
+                              var_cleanup_auth_client_header,
+                              cleanup_auth_client_identity, 
+                              var_cleanup_auth_client_header_domain);
+    }
+    if (cleanup_auth_sender_identity && *var_cleanup_auth_sender_header) {
+           cleanup_out_format(REC_TYPE_NORM, "%s %s",
+                              var_cleanup_auth_sender_header,
+                              cleanup_auth_sender_identity);
+    }
+#endif
 }
 
 /* cleanup_message - initialize message content segment */
diff --git a/postfix/conf/sample-auth.cf b/postfix/conf/sample-auth.cf
new file mode 100644 (file)
index 0000000..412fc81
--- /dev/null
@@ -0,0 +1,72 @@
+# This file contains example settings of Postfix configuration 
+# parameters that control SMTP authentication
+
+# The given example parameters are the default
+
+# smtpd options: incoming connections
+
+# The smtpd_auth_enable parameter controls whether authentication is
+# activated for Postfix as a server
+smtpd_auth_enable = yes
+
+# The smtpd_auth_require parameter controls whether authentication is
+# necessary for Postfix as a server
+# If it is set to 'no', the 'anonymous' mechanism is activated for all 
+# clients, otherwise it is not offered, except for local clients if 
+# smtpd_auth_mynetworks_anonymous is true.
+smtpd_auth_require = yes
+
+# TODO:
+# The smtpd_auth_mechanisms parameter controls which SASL mechanisms
+# are offered by the server
+# The default "" means that all available mechanisms are offered
+smtpd_auth_mechanisms = ""
+
+# TODO:
+# The smtpd_auth_mechanisms_weak parameter controls which SASL
+# mechanisms are considered too weak for specific purposes. This may
+# be used in the access checking rules.
+# The default "" means that all authentications are considered strong
+# enough.
+smtpd_auth_mechanisms_weak = ""
+
+
+# The smtpd_auth_mynetworks_anonymous controls whether the local nets
+# are allowed to authenticate anonymously and still be considered as
+# authenticated in the smtpd_check verifications. This has an
+# influence only if auth_required is set to "yes"
+smtpd_auth_mynetworks_anonymous = no
+
+# smtp options: outgoing connections
+
+# The smtp_auth_enable parameter controls whether authentication is 
+# activated for Postfix as a client
+smtp_auth_enable=yes
+
+# The smtp_auth_anonymous parameter controls whether the client tries
+# to authenticate as anonymous if authentication with a password
+# failed (i.e. the client tries to authenticate a second time, with the
+# `anonymous' mechanism)
+smtp_auth_anonymous = yes
+
+# The smtp_auth_passwd_map parameter specifies the name of the map that
+# contains usernames and passwords for postfix to authenticate as a
+# client
+# The mapping is hostname -> username:password
+# where hostname is the name of the host requesting authentication
+smtp_auth_passwd_map = ""
+
+# The cleanup_auth_client_header is inserted after the received headers to 
+# identify the relay. The default "" prevents the insertion of a header.
+cleanup_auth_client_header = ""
+
+# The cleanup_auth_client_header_domain can be used to append a domain
+# name to the auth_client_header, to identity the domain where the client
+# identity is valid. Default is $mydomain.
+cleanup_auth_client_header_domain = $mydomain
+
+
+# The cleanup_auth_sender_header is inserted after the received headers to 
+# identify the sender. The default "" prevents the insertion of a header.
+cleanup_auth_sender_header = ""
+
diff --git a/postfix/conf/sample-tls.cf b/postfix/conf/sample-tls.cf
new file mode 100644 (file)
index 0000000..97444df
--- /dev/null
@@ -0,0 +1,277 @@
+# This file contains example settings of Postfix configuration
+# parameters that control the behaviour of the TLS extensions.
+#
+# We strictly seperate between server side TLS (smtpd_) and client side
+# TLS (smtp_), as for practical reasons we might choose differently.
+
+# Section with SMTPD specific settings
+
+# To use TLS we do need a certificate and a private key. Both must be in
+# "pem" format, the private key must not be encrypted, that does mean:
+# it must be accessable without password. Both parts (certificate and
+# private key) may be in the same file.
+#
+# smtpd_tls_cert_file = /etc/postfix/server.pem
+# smtpd_tls_key_file = $tls_cert_file
+
+# The certificate was issued by a certification authority (CA), of which
+# the CA-cert must be available. This file may also contain the the
+# CA certificates of other trusted CAs. You must use this file for the
+# list of trusted CAs if you want to use chroot-mode.
+#
+# smtpd_tls_CAfile = /etc/postfix/CAcert.pem
+
+# To verify the peer certificate, we need to know the certificates of
+# certification authorities. These certificates in "pem" format are
+# collected in a directory. The same CAs are offered to clients for
+# client verification. Don't forget to create the necessary "hash"
+# links with $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs. A typical
+# place for the CA-certs may also be $OPENSSL_HOME/certs, so there is
+# no default and you explicitly have to set the value here!
+# This will not work in chroot mode, use the tls_CAfile instead.
+#
+smtpd_tls_CApath = /etc/postfix/certs
+
+# To get additional information during the TLS setup and negotiations
+# you can increase the loglevel from 0..4:
+# 0: No output about the TLS subsystem
+# 1: Printout startup and certificate information
+# 2: 1 + Printout of levels during negotiation
+# 3: 2 + Hex and ASCII dump of negotiation process
+# 4: 3 + Hex and ASCII dump of complete transmission after STARTTLS
+# Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
+# discouraged.
+#
+# smtpd_tls_loglevel = 0
+
+# To include information about the protocol and cipher used as well as the
+# client and issuer CommonName into the "Received:" header, set the
+# smtpd_tls_received_header variable to true. The default is no, as the
+# information is not necessarily authentic. Only the final destination
+# is reliable, since the headers might have been changed in between.
+#
+#smtpd_tls_received_header = true
+
+# By default TLS is disabled, so no difference to plain postfix is visible.
+# Explicitely switch it on here:
+#
+smtpd_use_tls = yes
+
+# You can ENFORCE the use of TLS, so that no commands (except QUIT of course)
+# are allowed without TLS. According to RFC2487 this MUST NOT be applied
+# in case of a publicly-referenced SMTP server. So this option is off
+# by default and should only seldom be used. Using this option implies
+# smtpd_use_tls = yes
+#
+# smtpd_enforce_tls = no
+
+# To receive a client certificate, the server must explicitly ask for one.
+# Hence netscape will either complain if no certificate is available (for
+# the list of CAs in /etc/postfix/certs) or will offer you client certificates
+# to choose from. This might be annoying, so this option is "off" by default.
+# You will however need the certificate if you want to to e.g. certificate
+# based relaying.
+#
+# smtpd_tls_ask_ccert = no
+
+# You may also decide to REQUIRE a client certificate to allow TLS connections.
+# I don't think it will be necessary often, it is however included here for
+# completeness. This option implies smtpd_tls_ask_ccert = yes
+#
+# smtpd_tls_req_ccert = no
+
+# The verification depth for client certificates. The default (1) is
+# sufficient, if the client certificate ist directly issued by a CA
+# listed under $tls_CApath
+#
+# smtpd_tls_ccert_vd = 1
+
+# One additional option has been added for relay control to the UCE rules:
+# check_relay_ccerts. If this option is added to smtpd_recipient_restrictions
+# postfix will relay if a valid client certificate is presented and in the
+# list of client certs (relay_clientcerts).
+#
+# smtpd_recipient_restrictions = check_relay_ccerts
+
+# The list of client certificates for which relaying will be allowed.
+# Unfortunately the routines for lists in postfix use whitespaces as
+# seperators and choke on special chars. So using the certificate
+# X509ONELINES is quite impractical. We will use the fingerprints at
+# this point, as they are difficult to fake but easy to use for lookup.
+# There is just one small problem: The colon ':' is interpreted as
+# seperator between database type and filename, so we must avoid it.
+# We use the underscore "_" instead.
+# As postmap (when using e.g. db) insists of having a pair of key and value,
+# but we only need the key, the value can be chosen freely, e.g. the name
+# of the user or host:
+# D7_04_2F_A7_0B_8C_A5_21_FA_31_77_E1_41_8A_EE_80 lutzpc.at.home
+#
+# relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+
+# Section with SMTP specific settings
+
+# During the startup negotiation we might present a certificate to the server.
+# Netscape is rather clever here and lets the user select between only those
+# certs that will match the CAs accepted from the server. As I simply use
+# the integrated "SSL_connect()" from the OpenSSL package, this is not
+# possible by now and we have to chose just one cert.
+# So for now the default is to use _no_ cert and key unless explictly
+# set here. It is possible to use the same key/cert pair as for the server.
+# If a cert is to be presented, it must be in "pem" format, the private key
+# must not be encrypted, that does mean: it must be accessable without
+# password. Both parts (certificate and # private key) may be in the
+# same file.
+#
+smtp_tls_cert_file = /etc/postfix/server.pem
+smtp_tls_key_file = $tls_cert_file
+
+# The certificate was issued by a certification authority (CA), of which
+# the CA-cert must be available. This file may also contain the the
+# CA certificates of other trusted CAs. You must use this file for the
+# list of trusted CAs if you want to use chroot-mode.
+# No default is supplied for this value as of now.
+#
+smtp_tls_CAfile = /etc/postfix/CAcert.pem
+
+# To verify the peer certificate, we need to know the certificates of
+# certification authorities. These certificates in "pem" format are
+# collected in a directory. Don't forget to create the necessary "hash"
+# links with $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs. A typical
+# place for the CA-certs may also be $OPENSSL_HOME/certs, so there is
+# no default and you explicitly have to set the value here!
+# This will not work in chroot mode, use the tls_CAfile instead.
+#
+smtp_tls_CApath = /etc/postfix/certs
+
+# To get additional information during the TLS setup and negotiations
+# you can increase the loglevel from 0..4:
+# 0: No output about the TLS subsystem
+# 1: Printout startup and certificate information
+# 2: 1 + Printout of levels during negotiation
+# 3: 2 + Hex and ASCII dump of negotiation process
+# 4: 3 + Hex and ASCII dump of complete transmission after STARTTLS
+# Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
+# discouraged.
+#
+smtp_tls_loglevel = 0
+
+# By default TLS is disabled, so no difference to plain postfix is visible.
+# If you enable TLS it will be used when offered by the server.
+# WARNING: I didn't have access to other software (except those explicitely
+# listed) to test the interaction. On corresponding mailing list
+# there was a discussion going on about MS exchange servers offering
+# STARTTLS even if it is not configured, so it might be wise to not
+# use this option on your central mail hub, as you don't know in advance
+# whether you are going to hit such host. Use the recipient/site specific
+# options instead.
+#
+# In case of failure, a "4xx" code is issued and the mail stays in the queue.
+#
+# Explicitely switch it on here, if you really wish it:
+#
+smtp_use_tls = yes
+
+# As generally trying TLS can be a bad idea (some hosts offer STARTTLS but
+# the negotiation will fail leading to unexplainable failures, it is a better
+# idea to decide based on the recipient or the mailhub to which you are
+# connecting.
+#
+# Recipient: The host/domain part of the recipients email address:
+# for "joe@dom.ain" the "dom.ain" is used for the 'recipient' matching.
+#
+# To try to use TLS whenever email is sent to somebody matching the recipient
+# domain "dom.ain", add it to the "use_tls_recipients" list. The STARTTLS
+# option is recognized and used regardless of the MX to which the smtp client
+# does connect.
+#
+smtp_use_tls_recipients = dom.ain, hash:/etc/postfix/use_tls_recipients
+#
+# Site: The name of the host the email is actually delivered to.
+#
+# To try to use TLS whenever a certain MX is used to deliver an email,
+# add it to the "use_tls_sites" list:
+#
+smtp_use_tls_sites = mailhost.some.where, some.where.else, hash:/etc/postfix/use_tls_sites
+#
+# The matching is done as a domain match, such that "some.where.else" will
+# match all hosts in the domain "some.where.else", e.g.
+# mailhost.some.where.else. For this reason, this option is named .._sites
+# and not .._hosts.
+#
+# These options will only use STARTTLS if it is offered. If it is not offered,
+# the mail will be delivered without encryption or authentication!! See also
+# the "enforce" options below.
+
+# You can ENFORCE the use of TLS, so that only connections with TLS will
+# be accepted. Additionally, the hostname of the receiving host is matched
+# against the CommonName in the certificate. Also, the certificate must
+# be verified "Ok", so that a CA trusted by the client must have issued
+# the certificate. If the certificate doesn't verify or the hostname doesn't
+# match, a "4xx" # will be issued and the mail stays in the queue.
+# The hostname used in the check is beyond question, as it must be the
+# principle hostname (no CNAME allowed here).
+#
+# This option is useful only if you are definitely sure that you will only
+# connect to servers supporting RFC2487 _and_ with valid certificates.
+# I use it for my clients which will only send email to one mailhub, which
+# does offer the necessary STARTTLS support.
+#
+# smtp_enforce_tls = no
+
+# For a per_site or per_recipient decision, use the corresponding lists.
+#
+# Recipient: The host/domain part of the recipients email address:
+# for "joe@dom.ain" the "dom.ain" is used for the 'recipient' matching.
+#
+# To enforce the use of TLS whenever email is sent to somebody matching the
+# recipient domain "dom.ain", add it to the "enforce_tls_recipients" list.
+# This way the email is only sent with encryption and authentication,
+# regardless of the MX to which the smtp client does connect. This way you
+# can assure that your email really is delivered to the correct MX; the
+# correctness of the MX nameserver record cannot be checked from postfix,
+# however.
+# Please note, that the authentication process requires that you recognize
+# the CA that issued the server certificate!
+#
+smtp_enforce_tls_recipients = dom.ain, hash:/etc/postfix/enforce_tls_recipients
+#
+# Site: The name of the host the email is actually delivered to.
+#
+# To enforce the use of TLS whenever a certain MX is used to deliver an email,
+# add it to the "enforce_tls_sites" list:
+#
+smtp_enforce_tls_sites = mailhost.some.where, some.where.else, hash:/etc/postfix/enforce_tls_sites
+#
+# The matching is done as a domain match, such that "some.where.else" will
+# match all hosts in the domain "some.where.else", e.g.
+# mailhost.some.where.else. For this reason, this option is named .._sites
+# and not .._hosts.
+
+# In case the client use of TLS is explicitely turned on, a list of
+# sites/hosts can be given for which no STARTTLS negotiation will be
+# started, e.g. because it is already known that it might fail for some
+# reason. It makes no sense for recipients, only receiving mail servers,
+# so only the "smtp_no_tls_sites" is offered, but not an equivalent
+# ".._recipients" option.
+#
+# HINT: This list is only checked when TLS usage is generally turned on
+# (usage or enforcement). If the recieving host/recipient is listed by the
+# specific "use/enforce_tls_sites/recipients" options, this setting has
+# precedence in any case and STARTTLS will be negotiated. No warning is given.
+#
+smtp_no_tls_sites = mailhost.some.where, some.where.else, hash:/etc/postfix/no_tls_sites
+
+# The verification depth for certificates. The default (1) is sufficient,
+# if the certificate ist directly issued by a CA listed under $tls_CApath
+#
+# smtp_tls_ccert_vd = 1
+
+# As we decide on a "per site" basis, wether to use TLS or not, it would be
+# good to have a list of sites, that offered "STARTTLS'. We can collect it
+# ourselves with this option.
+#
+# If activated and TLS is not already enabled for this host, a line is added
+# to the logfile:
+# postfix/smtp[pid]: Host offered STARTTLS: [name.of.host]
+#
+smtp_tls_note_starttls_offer = yes
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index be767bef2770b93732d42b6a1306aa5a722fd8c1..245fc77ee89ca89d5d0fe62297f8740ead53c246 100644 (file)
@@ -65,7 +65,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 dns_lookup.o: dns_lookup.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 5e0542b9c044f3fc5f1e5997a7e1116c93da06ce..7d43663d0f5182fd030bf8846510a6264f70a955 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 error.o: error.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 92dbdc3f63ad1e7af749913b161284797ba5b1a5..a463020f817c2babedbc37e6a59b2c80fe76760e 100644 (file)
@@ -51,7 +51,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 fsstone.o: fsstone.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 1eefc0ee1c2656535b4552a1b24b7c86c273e02a..0b207fe35fe07e1d97151bf7349a4fc1d0a70656 100644 (file)
@@ -217,7 +217,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 been_here.o: been_here.c
index e81bb0a625ebf2f51d717b8b2aa7ccbae22cae2c..aaf7468c04557c3cd73270837bf21b5561e931d9 100644 (file)
@@ -631,6 +631,27 @@ extern int var_smtpd_hard_erlim;
 #define DEF_SMTPD_ERR_SLEEP    5
 extern int var_smtpd_err_sleep;
 
+ /*
+  * SASL authentication support.
+  */
+#ifdef USE_SASL_AUTH
+
+#define VAR_SMTPD_SASL_ENABLE  "smtpd_sasl_auth_enable"
+#define DEF_SMTPD_SASL_ENABLE  0
+extern bool var_smtpd_sasl_enable;
+
+#define VAR_SMTP_SASL_ENABLE   "smtp_sasl_auth_enable"
+#define DEF_SMTP_SASL_ENABLE   0
+extern bool var_smtp_sasl_enable;
+
+#define VAR_SMTP_SASL_PWD_MAPS "smtp_sasl_password_maps"
+#define DEF_SMTP_SASL_PWD_MAPS ""
+extern char *var_smtp_sasl_pwd_maps;
+
+#define PERMIT_SASL_AUTH       "permit_sasl_authenticated"
+
+#endif
+
  /*
   * Cleanup service. Header info that exceeds $header_size_limit bytes forces
   * the start of the message body.
index 7b9ffd13bcc1777c2489c4351c91d90693fa9533..60a9586e938a3704df3b13bda4b880a011ba8ccf 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20000309"
+#define DEF_MAIL_VERSION       "Snapshot-20000316"
 extern char *var_mail_version;
 
 /* LICENSE
index 8e582d89c403bb506a0034c174de837e6b03f0be..bff21f6ffe058b2f39ead216e92bdc88d6fd2237 100644 (file)
@@ -2311,12 +2311,51 @@ include directory and of the object library.
 
 <p>
 
-One problem: older DB versions install a file
+When building with a third-party DB library you may into one of the
+following problems:
+
+<p>
+
+<ul>
+
+<li> Older DB versions install a file
 <b>/usr/local/include/ndbm.h</b> that is incompatible with
 <b>/usr/include/ndbm.h</b>. Be sure to get rid of the bogus file.
 See the FAQ entry titled "<a href="#dbm_dirfno">Undefined symbols:
 dbm_pagfno, dbm_dirfno etc</a>".
 
+<p>
+
+<li>With Sleepcat DB 3.0.55, the linker will complain that dbopen()
+is not found. To fix, apply the following patch to the DB 3.0.55
+db_185.h include file:
+
+<p>
+<pre>
+*** db_185.h.orig       Tue Mar  7 16:27:32 2000
+--- db_185.h    Tue Mar  7 16:27:44 2000
+***************
+*** 166,173 ****
+  #if defined(__cplusplus)
+  extern "C" {
+  #endif
+- #ifdef DB_LIBRARY_COMPATIBILITY_API
+  #define       dbopen  __db185_open
+  DB *__db185_open __P((const char *, int, int, DBTYPE, const void *));
+  #else
+  DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+--- 166,173 ----
+  #if defined(__cplusplus)
+  extern "C" {
+  #endif
+  #define       dbopen  __db185_open
++ #ifdef DB_LIBRARY_COMPATIBILITY_API
+  DB *__db185_open __P((const char *, int, int, DBTYPE, const void *));
+  #else
+  DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+</pre>
+
+</ul>
 <hr>
 
 <a href="index.html">Up one level</a> | Postfix FAQ
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index e1c8d8b6438cdfc70fe86eeae6870ebc28075186..f367ef9c1eb571f15e31a107a5090d5c34a99885 100644 (file)
@@ -57,7 +57,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 alias.o: alias.c
index c92a1b216ce0cbde7d20ad326ed23675d02dd992..68bd3d8ac83b05b8bd4b799043c0866b25665b79 100644 (file)
@@ -143,7 +143,7 @@ case "$SYSTEM.$RELEASE" in
                4)      SYSTYPE=AIX4
                        # How embarrassing...
                        case "$CC" in
-                       cc|*/cc|xlc|*/xlc) OPT=; CCARGS="$CCARGS -w";;
+                       cc|*/cc|xlc|*/xlc) OPT=; CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
                        esac
                        CCARGS="$CCARGS -D_ALL_SOURCE"
                        ;;
@@ -258,4 +258,5 @@ CC  = $CC $CCARGS
 OPT    = $OPT
 DEBUG  = $DEBUG
 AWK    = $AWK
+EXPORT = AUXLIBS="$AUXLIBS" CCARGS="$CCARGS" OPT="$OPT" DEBUG="$DEBUG"
 EOF
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index a499576de6830453eaa142b8b77c9516cc841750..31a0e36c43bc6d79f3bc17203da4041cd264963f 100644 (file)
@@ -75,7 +75,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 master.o: master.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index d3b0f35d95bfbbcc8ab166d62697bb81f57fd9e1..1f20f1934f270056acbd2e2e462fa3761f834aa4 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 pickup.o: pickup.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index aebfd7435aa4779b6076daf7e2361a1f007cec47..f6879fa0a309f57bdba640dc1171e6bc5cfac9ce 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 pipe.o: pipe.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 1304d7844f5ed7878919ee0b770384b162733fe6..1ffd123525aadeb3066a2eb032742cf9ec7668e3 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postalias.o: postalias.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 68175a8ba04a1c0bd7dee8db7c4f7cf6b3374c55..09a49588499b5ba36c5f7c45b18af3f7beed3764 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postcat.o: postcat.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index a0b8cd1a32bce1d7e8689b70901d05e8e385a364..47aab60d0bf2cb09f40f99ae1fde347e341255c1 100644 (file)
@@ -61,7 +61,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postconf.o: postconf.c
index 8cd8cfc0969e25c258c8478dd9311e75b0a9e5f3..ebe866e2993bedc7741f0f15eac00acead270a8d 100644 (file)
@@ -1,18 +1,18 @@
 # Extract initialization tables from actual source code.
 
-/^(static| )*CONFIG_INT_TABLE .*{/,/};/ { 
+/^(static| )*CONFIG_INT_TABLE .*\{/,/\};/ { 
     if ($1 ~ /VAR/) {
        print "int " substr($3,2,length($3)-2) ";" > "int_vars.h"
        print | "sed 's/[       ][      ]*/ /g' | sort -u >int_table.h" 
     }
 }
-/^(static| )*CONFIG_STR_TABLE .*{/,/};/ { 
+/^(static| )*CONFIG_STR_TABLE .*\{/,/\};/ { 
     if ($1 ~ /VAR/) {
        print "char *" substr($3,2,length($3)-2) ";" > "str_vars.h"
        print | "sed 's/[       ][      ]*/ /g' | sort -u >str_table.h" 
     }
 }
-/^(static| )*CONFIG_BOOL_TABLE .*{/,/};/ { 
+/^(static| )*CONFIG_BOOL_TABLE .*\{/,/\};/ { 
     if ($1 ~ /VAR/) {
        print "int " substr($3,2,length($3)-2) ";" > "bool_vars.h"
        print | "sed 's/[       ][      ]*/ /g' | sort -u >bool_table.h" 
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index cb8ed7547aa30da8a4af8756a1d1373022de89da..8f24b00c0264665a900b172c4b5b38dee74b2a86 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postdrop.o: postdrop.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index d807c878b5c66f0fa84ce5daf0ae60e58eea7db6..b1f63de7ccb5d608175ad883a1c8b8a3e8a8103f 100644 (file)
@@ -54,7 +54,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postfix.o: postfix.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 9a0fd6b029d5f31b92de39b3407098d7c628c2bc..c846ca697f5890fefbdb774083a498e2767f9539 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postkick.o: postkick.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index c2ee45d3c418ace7a554fc95ac4a4375609ad151..0d194091b33bbcc58c773bd3073af10f25f9e794 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postlock.o: postlock.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index fbfad473f143037ee20695d0c80ba7958468eed0..e3f00e469c1d256a89e5af529b151067d8b05ccd 100644 (file)
@@ -54,7 +54,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postlog.o: postlog.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 5cd483acd38e272fd899b0f44855c01d275ae18b..db3a6bd5fb060a86a8238c837106cfb35800e031 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postmap.o: postmap.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 1b58244f9c82195dbfbdc0de798175501a4e8ecd..b5caf22cb743a95cde3038c026c2cb8a2c09c747 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 postsuper.o: postsuper.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 144e089f9783dec2c34b5476f452fde195145e4a..99ce9e6eff584234870545a3ab903af3318d83d7 100644 (file)
@@ -55,7 +55,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 qmgr.o: qmgr.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 9a71d3422f2ac17e24978bdacb218fc4cdeed9b1..da946438b5ccef0a313e1f5fb7b8212a912f4f46 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 sendmail.o: sendmail.c
index 90e27bcf12fd098017cd77d0c2cff13b74c53ae2..311350544d82865e9e74f72f9c25022b8212760c 100644 (file)
@@ -18,6 +18,7 @@
 /*     Sendmail command-line options are recognized but silently ignored.
 /*
 /*     By default, \fBsendmail\fR reads a message from standard input
+/*     until EOF or until it reads a line with only a \fB.\fR character,
 /*     and arranges for delivery.  \fBsendmail\fR attempts to create
 /*     a queue file in the \fBmaildrop\fR directory. If that directory
 /*     is not world-writable, the message is piped through the
@@ -95,8 +96,9 @@
 /* .IP "\fB-h \fIhop_count\fR (ignored)"
 /*     Hop count limit. Use the \fBhopcount_limit\fR configuration
 /*     parameter instead.
-/* .IP "\fB-i\fR (ignored)"
-/*     Lines beginning with "." get special treatment only with \fB-bs\fR.
+/* .IP "\fB-i\fR"
+/*     When reading a message from standard input, don\'t treat a line
+/*     with only a \fB.\fR character as the end of input.
 /* .IP "\fB-m\fR (ignored)"
 /*     Backwards compatibility.
 /* .IP "\fB-n\fR (ignored)"
 /* .IP "\fB-o8\fR (ignored)"
 /*     The message body type. Currently, Postfix implements
 /*     \fBjust-send-eight\fR.
+/* .IP "\fB-oi\fR"
+/*     When reading a message from standard input, don\'t treat a line
+/*     with only a \fB.\fR character as the end of input.
 /* .IP "\fB-om\fR (ignored)"
 /*     The sender is never eliminated from alias etc. expansions.
 /* .IP "\fB-o \fIx value\fR (ignored)"
 static char *sendmail_path;
 static void sendmail_cleanup(void);
 
+ /*
+  * Flag parade.
+  */
+#define SM_FLAG_AEOF   (1<<0)          /* archaic EOF */
+
+#define SM_FLAG_DEFAULT        (SM_FLAG_AEOF)
+
  /*
   * Silly little macros (SLMs).
   */
@@ -292,7 +304,8 @@ static void sendmail_cleanup(void);
 
 /* enqueue - post one message */
 
-static void enqueue(const char *sender, const char *full_name, char **recipients)
+static void enqueue(const int flags, const char *sender, const char *full_name,
+                           char **recipients)
 {
     VSTRING *buf;
     VSTREAM *dst;
@@ -425,6 +438,8 @@ static void enqueue(const char *sender, const char *full_name, char **recipients
        if (strip_cr == STRIP_CR_DO && type == REC_TYPE_NORM)
            if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r')
                vstring_truncate(buf, VSTRING_LEN(buf) - 1);
+       if ((flags & SM_FLAG_AEOF) && VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
+           break;
        if (REC_PUT_BUF(dst, type, buf) < 0)
            msg_fatal("%s(%d): error writing queue file: %m", saved_sender, uid);
     }
@@ -572,6 +587,7 @@ int     main(int argc, char **argv)
     int     debug_me = 0;
     int     err;
     int     n;
+    int     flags = SM_FLAG_DEFAULT;
 
     /*
      * Be consistent with file permissions.
@@ -588,6 +604,14 @@ int     main(int argc, char **argv)
            && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
            msg_fatal("open /dev/null: %m");
 
+    /*
+     * The CDE desktop calendar manager leaks a parent file descriptor into
+     * the child process. For the sake of sendmail compatibility we have to
+     * close the file descriptor otherwise mail notification will hang.
+     */
+    for ( /* void */ ; fd < 100; fd++)
+       (void) close(fd);
+
     /*
      * Process environment options as early as we can. We might be called
      * from a set-uid (set-gid) program, so be careful with importing
@@ -720,6 +744,9 @@ int     main(int argc, char **argv)
        case 'f':
            sender = optarg;
            break;
+       case 'i':
+           flags &= ~SM_FLAG_AEOF;
+           break;
        case 'o':
            switch (*optarg) {
            default:
@@ -735,6 +762,10 @@ int     main(int argc, char **argv)
                break;
            case '7':
            case '8':
+               break;
+           case 'i':
+               flags &= ~SM_FLAG_AEOF;
+               break;
            case 'm':
                break;
            }
@@ -780,7 +811,7 @@ int     main(int argc, char **argv)
        msg_panic("unknown operation mode: %d", mode);
        /* NOTREACHED */
     case SM_MODE_ENQUEUE:
-       enqueue(sender, full_name, argv + OPTIND);
+       enqueue(flags, sender, full_name, argv + OPTIND);
        exit(0);
        break;
     case SM_MODE_MAILQ:
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 55a1e0879e051ca6914412a01e194f3fd85045ba..ec75f8c9bc6180c1b72dc3f10b8cbc8a760d277b 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 showq.o: showq.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index c7163fdf41ede9e72da8068b9573701afe45d6ac..4db9cb944b18cf458812ba8ee881d134a4c36304 100644 (file)
@@ -1,9 +1,11 @@
 SHELL  = /bin/sh
 SRCS   = smtp.c quote_821_local.c smtp_connect.c smtp_proto.c smtp_chat.c \
-       smtp_session.c smtp_addr.c smtp_trouble.c smtp_unalias.c smtp_state.c
+       smtp_session.c smtp_addr.c smtp_trouble.c smtp_unalias.c smtp_state.c \
+       smtp_sasl_proto.c smtp_sasl_glue.c
 OBJS   = smtp.o quote_821_local.o smtp_connect.o smtp_proto.o smtp_chat.o \
-       smtp_session.o smtp_addr.o smtp_trouble.o smtp_unalias.o smtp_state.o
-HDRS   = smtp.h
+       smtp_session.o smtp_addr.o smtp_trouble.o smtp_unalias.o smtp_state.o \
+       smtp_sasl_proto.o smtp_sasl_glue.o
+HDRS   = smtp.h smtp_sasl.h
 TESTSRC        = 
 WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
        -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
@@ -59,7 +61,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 quote_821_local.o: quote_821_local.c
@@ -88,6 +90,7 @@ smtp.o: ../include/mail_proto.h
 smtp.o: ../include/iostuff.h
 smtp.o: ../include/mail_server.h
 smtp.o: smtp.h
+smtp.o: smtp_sasl.h
 smtp_addr.o: smtp_addr.c
 smtp_addr.o: ../include/sys_defs.h
 smtp_addr.o: ../include/msg.h
@@ -167,6 +170,37 @@ smtp_proto.o: ../include/mark_corrupt.h
 smtp_proto.o: smtp.h
 smtp_proto.o: ../include/argv.h
 smtp_proto.o: quote_821_local.h
+smtp_proto.o: smtp_sasl.h
+smtp_sasl_glue.o: smtp_sasl_glue.c
+smtp_sasl_glue.o: ../include/sys_defs.h
+smtp_sasl_glue.o: ../include/msg.h
+smtp_sasl_glue.o: ../include/mymalloc.h
+smtp_sasl_glue.o: ../include/stringops.h
+smtp_sasl_glue.o: ../include/split_at.h
+smtp_sasl_glue.o: ../include/mail_params.h
+smtp_sasl_glue.o: ../include/string_list.h
+smtp_sasl_glue.o: ../include/maps.h
+smtp_sasl_glue.o: ../include/dict.h
+smtp_sasl_glue.o: ../include/vstream.h
+smtp_sasl_glue.o: ../include/vbuf.h
+smtp_sasl_glue.o: ../include/argv.h
+smtp_sasl_glue.o: smtp.h
+smtp_sasl_glue.o: ../include/vstring.h
+smtp_sasl_glue.o: ../include/deliver_request.h
+smtp_sasl_glue.o: ../include/recipient_list.h
+smtp_sasl_glue.o: smtp_sasl.h
+smtp_sasl_proto.o: smtp_sasl_proto.c
+smtp_sasl_proto.o: ../include/sys_defs.h
+smtp_sasl_proto.o: ../include/msg.h
+smtp_sasl_proto.o: ../include/mymalloc.h
+smtp_sasl_proto.o: smtp.h
+smtp_sasl_proto.o: ../include/vstream.h
+smtp_sasl_proto.o: ../include/vbuf.h
+smtp_sasl_proto.o: ../include/vstring.h
+smtp_sasl_proto.o: ../include/argv.h
+smtp_sasl_proto.o: ../include/deliver_request.h
+smtp_sasl_proto.o: ../include/recipient_list.h
+smtp_sasl_proto.o: smtp_sasl.h
 smtp_session.o: smtp_session.c
 smtp_session.o: ../include/sys_defs.h
 smtp_session.o: ../include/mymalloc.h
@@ -189,6 +223,7 @@ smtp_state.o: smtp.h
 smtp_state.o: ../include/argv.h
 smtp_state.o: ../include/deliver_request.h
 smtp_state.o: ../include/recipient_list.h
+smtp_state.o: smtp_sasl.h
 smtp_trouble.o: smtp_trouble.c
 smtp_trouble.o: ../include/sys_defs.h
 smtp_trouble.o: ../include/msg.h
index 29dc70dabff23e0ab524969f521110ee381961be..95543bba336388f5c1bc6433fa0cfabdca71035b 100644 (file)
 /* Application-specific. */
 
 #include "smtp.h"
+#include "smtp_sasl.h"
 
  /*
   * Tunable parameters. These have compiled-in defaults that can be overruled
@@ -211,6 +212,14 @@ char   *var_bestmx_transp;
 char   *var_error_rcpt;
 int     var_smtp_always_ehlo;
 
+#ifdef USE_SASL_AUTH
+
+char   *var_smtp_sasl_pwd_maps;
+bool    var_smtp_sasl_enable;
+bool    var_smtp_sasl_anon;
+
+#endif
+
  /*
   * Global variables. smtp_errno is set by the address lookup routines and by
   * the connection management routines.
@@ -318,6 +327,11 @@ static void smtp_service(VSTREAM *client_stream, char *unused_service, char **ar
 static void pre_init(char *unused_name, char **unused_argv)
 {
     debug_peer_init();
+
+#ifdef USE_SASL_AUTH
+    if (var_smtp_sasl_enable)
+       smtp_sasl_initialize();
+#endif
 }
 
 /* pre_accept - see if tables have changed */
@@ -340,6 +354,9 @@ int     main(int argc, char **argv)
        VAR_FALLBACK_RELAY, DEF_FALLBACK_RELAY, &var_fallback_relay, 0, 0,
        VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
        VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
+#ifdef USE_SASL_AUTH
+       VAR_SMTP_SASL_PWD_MAPS, DEF_SMTP_SASL_PWD_MAPS, &var_smtp_sasl_pwd_maps, 0, 0,
+#endif
        0,
     };
     static CONFIG_INT_TABLE int_table[] = {
@@ -360,6 +377,9 @@ int     main(int argc, char **argv)
        VAR_IGN_MX_LOOKUP_ERR, DEF_IGN_MX_LOOKUP_ERR, &var_ign_mx_lookup_err,
        VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
        VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
+#ifdef USE_SASL_AUTH
+       VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
+#endif
        0,
     };
 
index e236d9a07707f7647ea0029a88ad29658455b717..d734948713d3e7a6296999feafd63fd8bd8b3436 100644 (file)
@@ -8,6 +8,14 @@
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * SASL library.
+  */
+#ifdef USE_SASL_AUTH
+#include <sasl.h>
+#include <saslutil.h>
+#endif
+
  /*
   * Utility library.
   */
@@ -35,12 +43,23 @@ typedef struct SMTP_STATE {
     int     features;                  /* server features */
     ARGV   *history;                   /* transaction log */
     int     error_mask;                        /* error classes */
+#ifdef USE_SASL_AUTH
+    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 */
+#endif
 } SMTP_STATE;
 
 #define SMTP_FEATURE_ESMTP     (1<<0)
 #define SMTP_FEATURE_8BITMIME  (1<<1)
 #define SMTP_FEATURE_PIPELINING        (1<<2)
 #define SMTP_FEATURE_SIZE      (1<<3)
+#define SMTP_FEATURE_STARTTLS  (1<<4)
+#define SMTP_FEATURE_AUTH      (1<<5)
 
  /*
   * smtp.c
index 9be06bd45182e3c741a088683c3d66badcc41115..8e0b7c8c24dd2e017e1144d0d6ca3e136b7e4d8e 100644 (file)
 
 #include "smtp.h"
 #include "quote_821_local.h"
+#include "smtp_sasl.h"
 
  /*
   * Sender and receiver state. A session does not necessarily go through a
@@ -220,6 +221,10 @@ int     smtp_helo(SMTP_STATE *state)
                state->features |= SMTP_FEATURE_PIPELINING;
            else if (strcasecmp(word, "SIZE") == 0)
                state->features |= SMTP_FEATURE_SIZE;
+#ifdef USE_SASL_AUTH
+           else if (strcasecmp(word, "AUTH") == 0)
+               smtp_sasl_helo_auth(state, words);
+#endif
            else if (strcasecmp(word, var_myhostname) == 0) {
                msg_warn("host %s replied to HELO/EHLO with my own hostname %s",
                         session->namaddr, var_myhostname);
@@ -231,6 +236,12 @@ int     smtp_helo(SMTP_STATE *state)
     }
     if (msg_verbose)
        msg_info("server features: 0x%x", state->features);
+
+#ifdef USE_SASL_AUTH
+    if (state->features & SMTP_FEATURE_AUTH)
+       return (smtp_sasl_helo_login(state));
+#endif
+
     return (0);
 }
 
diff --git a/postfix/smtp/smtp_sasl.h b/postfix/smtp/smtp_sasl.h
new file mode 100644 (file)
index 0000000..1c6ec6f
--- /dev/null
@@ -0,0 +1,35 @@
+/*++
+/* NAME
+/*     smtp_sasl 3h
+/* SUMMARY
+/*     Postfix SASL interface for SMTP client
+/* SYNOPSIS
+/*     #include "smtp_sasl.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * SASL protocol functions
+ */
+extern void smtp_sasl_initialize(void);
+extern void smtp_sasl_connect(SMTP_STATE *);
+extern void smtp_sasl_start(SMTP_STATE *);
+extern int smtp_sasl_authenticate(SMTP_STATE *, VSTRING *);
+extern void smtp_sasl_cleanup(SMTP_STATE *);
+
+/* 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
+/*--*/
diff --git a/postfix/smtp/smtp_sasl_glue.c b/postfix/smtp/smtp_sasl_glue.c
new file mode 100644 (file)
index 0000000..5d87d14
--- /dev/null
@@ -0,0 +1,461 @@
+/*++
+/* NAME
+/*     smtp_sasl 3
+/* SUMMARY
+/*     Postfix SASL interface for SMTP client
+/* SYNOPSIS
+/*     #include smtp_sasl.h
+/*
+/*     void    smtp_sasl_initialize()
+/*
+/*     void    smtp_sasl_connect(state)
+/*     SMTP_STATE *state;
+/*
+/*     void    smtp_sasl_start(state)
+/*     SMTP_STATE *state;
+/*
+/*     int     smtp_sasl_authenticate(state, why)
+/*     SMTP_STATE *state;
+/*     VSTRING *why;
+/*
+/*     void    smtp_sasl_cleanup(state)
+/*     SMTP_STATE *state;
+/* DESCRIPTION
+/*     smtp_sasl_initialize() initializes the SASL library. This
+/*     routine must be called once at process startup, before any
+/*     chroot operations.
+/*
+/*     smtp_sasl_connect() performs per-session initialization. This
+/*     routine must be called once at the start of each connection.
+/*
+/*     smtp_sasl_start() performs per-session initialization. This
+/*     routine must be called once per session before doing any SASL
+/*     authentication.
+/*
+/*     smtp_sasl_authenticate() implements the SASL authentication
+/*     dialog. The result is < 0 in case of protocol failure, zero in
+/*     case of unsuccessful authentication, > 0 in case of success.
+/*     The why argument is updated with a reason for failure.
+/*
+/*     smtp_sasl_cleanup() cleans up. It must be called at the
+/*     end of every SMTP session that uses SASL authentication.
+/*     This routine is a noop for non-SASL sessions.
+/*
+/*     Arguments:
+/* .IP state
+/*     Session context.
+/* .IP mech_list
+/*     String of SASL mechanisms (separated by blanks)
+/* DIAGNOSTICS
+/*     All errors are fatal.
+/* 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 <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+ /*
+  * Utility library
+  */
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <split_at.h>
+
+ /*
+  * Global library
+  */
+#include <mail_params.h>
+#include <string_list.h>
+#include <maps.h>
+
+ /*
+  * Application-specific
+  */
+#include "smtp.h"
+#include "smtp_sasl.h"
+
+#ifdef USE_SASL_AUTH
+
+ /*
+  * Silly little macros.
+  */
+#define STR(x) vstring_str(x)
+
+ /*
+  * Per-host login/password information.
+  */
+static MAPS *smtp_sasl_passwd_map;
+
+/* 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:
+       msg_fatal("%s", message);
+       break;
+    case SASL_LOG_WARNING:
+       msg_warn("%s", message);
+       break;
+    case SASL_LOG_INFO:
+       if (msg_verbose)
+           msg_info("%s", message);
+       break;
+    }
+    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)
+{
+    SMTP_STATE *state = (SMTP_STATE *) context;
+
+    if (msg_verbose)
+       msg_info("smtp_sasl_get_user: %s", state->sasl_username);
+
+    *result = state->sasl_username;
+    if (len)
+       *len = strlen(state->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)
+{
+    SMTP_STATE *state = (SMTP_STATE *) context;
+    int     len;
+
+    if (msg_verbose)
+       msg_info("smtp_sasl_get_passwd: %s", state->sasl_passwd);
+
+    /*
+     * Sanity check.
+     */
+    if (!conn || !psecret || id != SASL_CB_PASS)
+       return (SASL_BADPARAM);
+
+    /*
+     * Convert the password into a counted string.
+     */
+    len = strlen(state->sasl_passwd);
+    if ((*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len)) == 0)
+       return (SASL_NOMEM);
+    (*psecret)->len = len;
+    strcpy((*psecret)->data, state->sasl_passwd);
+
+    return (SASL_OK);
+}
+
+/* smtp_sasl_passwd_lookup - password lookup routine */
+
+static void smtp_sasl_passwd_lookup(SMTP_STATE *state)
+{
+    char   *myname = "smtp_sasl_passwd_lookup";
+    const char *value;
+    char   *passwd;
+
+    /*
+     * Sanity check.
+     */
+    if (smtp_sasl_passwd_map == 0)
+       msg_panic("%s: passwd map not initialized", myname);
+
+    /*
+     * Look up the per-server password information.
+     */
+
+    if ((value = maps_find(smtp_sasl_passwd_map, state->session->host, 0)) != 0) {
+       state->sasl_username = mystrdup(value);
+       passwd = split_at(state->sasl_username, ':');
+       state->sasl_passwd = mystrdup(passwd ? passwd : "");
+    } else {
+       state->sasl_username = mystrdup(var_myhostname);
+       state->sasl_passwd = mystrdup("");
+    }
+    if (msg_verbose)
+       msg_info("%s: host `%s' user `%s' pass `%s'",
+                myname, state->session->host,
+                state->sasl_username, state->sasl_passwd);
+}
+
+/* smtp_sasl_initialize - per-process initialization (pre jail) */
+
+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}
+    };
+
+    /*
+     * Sanity check.
+     */
+    if (smtp_sasl_passwd_map)
+       msg_panic("smtp_sasl_initialize: repeated call");
+    if (*var_smtp_sasl_pwd_maps == 0)
+       msg_fatal("specify password table via the `%s' configuration parameter",
+                 VAR_SMTP_SASL_PWD_MAPS);
+
+    /*
+     * Open the per-host password table and initialize the SASL library. Use
+     * shared locks for reading, just in case someone updates the table.
+     */
+    smtp_sasl_passwd_map = maps_create("smtp_sasl_passwd",
+                                   var_smtp_sasl_pwd_maps, DICT_FLAG_LOCK);
+    if (sasl_client_init(callbacks) != SASL_OK)
+       msg_fatal("SASL library initialization");
+}
+
+/* smtp_sasl_connect - per-session client initialization */
+
+void    smtp_sasl_connect(SMTP_STATE *state)
+{
+    state->sasl_mechanism_list = 0;
+    state->sasl_username = 0;
+    state->sasl_passwd = 0;
+    state->sasl_conn = 0;
+    state->sasl_encoded = 0;
+    state->sasl_decoded = 0;
+    state->sasl_callbacks = 0;
+}
+
+/* smtp_sasl_start - per-session SASL initialization */
+
+void    smtp_sasl_start(SMTP_STATE *state)
+{
+    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
+
+    state->sasl_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks));
+    memcpy((char *) state->sasl_callbacks, callbacks, sizeof(callbacks));
+    for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++)
+       cp->context = (void *) state;
+    if (sasl_client_new("smtp", state->session->host, callbacks, NULL_SECFLAGS,
+                       (sasl_conn_t **) &state->sasl_conn) != SASL_OK)
+       msg_fatal("per-session SASL client initialization");
+    smtp_sasl_passwd_lookup(state);
+
+    /*
+     * Per-session security properties. XXX This routine is not sufficiently
+     * documented. What is the purpose of all this?
+     */
+    memset(&sec_props, 0L, sizeof(sec_props));
+    sec_props.min_ssf = 0;
+    sec_props.max_ssf = 1;                     /* don't allow real SASL
+                                                * security layer */
+    sec_props.security_flags = 0;
+    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("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.
+     */
+    state->sasl_encoded = vstring_alloc(10);
+    state->sasl_decoded = vstring_alloc(10);
+}
+
+/* smtp_sasl_authenticate - run authentication protocol */
+
+int     smtp_sasl_authenticate(SMTP_STATE *state, VSTRING *why)
+{
+    char   *myname = "smtp_sasl_authenticate";
+    unsigned enc_length;
+    unsigned enc_length_out;
+    char   *clientout;
+    unsigned clientoutlen;
+    unsigned serverinlen;
+    SMTP_RESP *resp;
+    const char *mechanism;
+    int     result;
+    char   *line;
+
+#define NO_SASL_SECRET         0
+#define NO_SASL_INTERACTION    0
+
+    if (msg_verbose)
+       msg_info("%s: %s: SASL mechanisms %s",
+              myname, state->session->namaddr, state->sasl_mechanism_list);
+
+    /*
+     * Start the client side authentication protocol.
+     */
+    result = sasl_client_start((sasl_conn_t *) state->sasl_conn,
+                              state->sasl_mechanism_list,
+                              NO_SASL_SECRET, NO_SASL_INTERACTION,
+                              &clientout, &clientoutlen, &mechanism);
+    if (result != SASL_OK && result != SASL_CONTINUE)
+       msg_fatal("%s: %s: client-side SASL authentication startup",
+                 myname, state->session->namaddr);
+
+    /*
+     * Send 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)
+           msg_info("%s: %s: uncoded initial reply: %.*s",
+                 myname, state->session->namaddr, clientoutlen, clientout);
+       enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
+       VSTRING_SPACE(state->sasl_encoded, enc_length);
+       if (sasl_encode64(clientout, clientoutlen,
+                         STR(state->sasl_encoded), enc_length,
+                         &enc_length_out) != SASL_OK)
+           msg_panic("%s: sasl_encode64 botch", myname);
+       free(clientout);
+       smtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded));
+    } else {
+       smtp_chat_cmd(state, "AUTH %s", mechanism);
+    }
+
+    /*
+     * Step through the authentication protocol until the server tells us
+     * that we are done.
+     */
+    while ((resp = smtp_chat_resp(state))->code % 100 == 3) {
+
+       /*
+        * Process a server challenge.
+        */
+       line = resp->str;
+       (void) mystrtok(&line, "- \t\n");       /* skip over result code */
+       serverinlen = strlen(line);
+       VSTRING_SPACE(state->sasl_decoded, serverinlen);
+       if (sasl_decode64(line, serverinlen,
+                       STR(state->sasl_decoded), &enc_length) != SASL_OK) {
+           vstring_sprintf(why, "unable to decode SASL challenge from %s",
+                           state->session->namaddr);
+           return (-1);
+       }
+       if (msg_verbose)
+           msg_info("%s: %s: decoded challenge: %.*s",
+                    myname, state->session->namaddr,
+                    enc_length, STR(state->sasl_decoded));
+       result = sasl_client_step((sasl_conn_t *) state->sasl_conn,
+                                 STR(state->sasl_decoded), enc_length,
+                           NO_SASL_INTERACTION, &clientout, &clientoutlen);
+       if (result != SASL_OK && result != SASL_CONTINUE)
+           msg_warn("%s: smtp SASL authentication step failed",
+                    state->session->namaddr);
+
+       /*
+        * Send a client response.
+        */
+       if (clientoutlen > 0) {
+           if (msg_verbose)
+               msg_info("%s: %s: uncoded client response %.*s",
+                 myname, state->session->namaddr, clientoutlen, clientout);
+           enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
+           VSTRING_SPACE(state->sasl_encoded, enc_length);
+           if (sasl_encode64(clientout, clientoutlen,
+                             STR(state->sasl_encoded), enc_length,
+                             &enc_length_out) != SASL_OK)
+               msg_panic("%s: sasl_encode64 botch", myname);
+           free(clientout);
+       } else {
+           vstring_strcat(state->sasl_encoded, "");
+       }
+       smtp_chat_cmd(state, "%s", STR(state->sasl_encoded));
+    }
+
+    /*
+     * We completed the authentication protocol.
+     */
+    if (resp->code / 100 != 2) {
+       vstring_sprintf(why, "unable to SASL authenticate with %s",
+                       state->session->namaddr);
+       return (0);
+    }
+    return (1);
+}
+
+/* smtp_sasl_cleanup - per-session cleanup */
+
+void    smtp_sasl_cleanup(SMTP_STATE *state)
+{
+    if (state->sasl_username) {
+       myfree(state->sasl_username);
+       state->sasl_username = 0;
+    }
+    if (state->sasl_passwd) {
+       myfree(state->sasl_passwd);
+       state->sasl_passwd = 0;
+    }
+    if (state->sasl_mechanism_list) {
+       myfree(state->sasl_mechanism_list);     /* allocated in smtp_helo */
+       state->sasl_mechanism_list = 0;
+    }
+    if (state->sasl_conn) {
+       if (msg_verbose)
+           msg_info("disposing SASL state information");
+       sasl_dispose(&state->sasl_conn);
+    }
+    if (state->sasl_callbacks) {
+       myfree((char *) state->sasl_callbacks);
+       state->sasl_callbacks = 0;
+    }
+    if (state->sasl_encoded) {
+       vstring_free(state->sasl_encoded);
+       state->sasl_encoded = 0;
+    }
+    if (state->sasl_decoded) {
+       vstring_free(state->sasl_decoded);
+       state->sasl_decoded = 0;
+    }
+}
+
+#endif
diff --git a/postfix/smtp/smtp_sasl_proto.c b/postfix/smtp/smtp_sasl_proto.c
new file mode 100644 (file)
index 0000000..ed34c35
--- /dev/null
@@ -0,0 +1,113 @@
+/*++
+/* NAME
+/*     smtp_sasl_proto 3
+/* SUMMARY
+/*     Postfix SASL interface for SMTP client
+/* SYNOPSIS
+/*     #include smtp_sasl.h
+/*
+/*     void    smtp_sasl_helo_auth(state, words)
+/*     SMTP_STATE *state;
+/*     const char *words;
+/*
+/*     void    smtp_sasl_helo_login(state)
+/*     SMTP_STATE *state;
+/* DESCRIPTION
+/*     This module contains random chunks of code that implement
+/*     the SMTP protocol interface for SASL negotiation. The goal 
+/*     is to reduce clutter of the main SMTP client source code.
+/*
+/*     smtp_sasl_helo_auth() processes the AUTH option in the
+/*     SMTP server's EHLO response.
+/*
+/*     smtp_sasl_helo_login() authenticates the SMTP client to the
+/*     SMTP server, using the authentication mechanism information
+/*     given by the server.
+/*
+/*     Arguments:
+/* .IP state
+/*     Session context.
+/* .IP words
+/*     List of SASL authentication mechanisms (separated by blanks)
+/* DIAGNOSTICS
+/*     All errors are fatal.
+/* 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 <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+
+/* Application-specific. */
+
+#include "smtp.h"
+#include "smtp_sasl.h"
+
+#ifdef USE_SASL_AUTH
+
+/* smtp_sasl_helo_auth - handle AUTH option in EHLO reply */
+
+void smtp_sasl_helo_auth(SMTP_STATE *state, const char *words)
+{
+
+    /*
+     * XXX If the server offers a null list of authentication mechanisms,
+     * then pretend that the server doesn't support SASL authentication.
+     */
+    if (var_smtp_sasl_enable) {
+       if (state->sasl_mechanism_list) {
+           myfree(state->sasl_mechanism_list);
+           msg_warn("%s offered AUTH option multiple times",
+                    state->session->namaddr);
+           state->sasl_mechanism_list = 0;
+           state->features &= ~SMTP_FEATURE_AUTH;
+       }
+       if (strlen(words) > 0) {
+           state->sasl_mechanism_list = mystrdup(words);
+           state->features |= SMTP_FEATURE_AUTH;
+       }
+    }
+}
+
+/* smtp_sasl_helo_login - perform SASL login */
+
+int smtp_sasl_helo_login(SMTP_STATE *state)
+{
+    VSTRING *why = vstring_alloc(10);
+    int     ret;
+
+    /*
+     * XXX If authentication fails, should we try anonymous authentication?
+     */
+    smtp_sasl_start(state);
+    if (smtp_sasl_authenticate(state, why) <= 0)
+       ret = smtp_site_fail(state, 450, "Authentication failed: %s",
+                            vstring_str(why));
+    vstring_free(why);
+    return (ret);
+}
+
+#endif
index 1ab6a6f1dbbbae8c3b5c089ed3a1ff959517b57e..07696dd91232712efacad7556816ecd5622328e7 100644 (file)
 /*     memory for buffers etc.
 /*
 /*     smtp_cleanup() destroys memory allocated by smtp_state_init().
-/* STANDARDS
-/* DIAGNOSTICS
-/* BUGS
-/* SEE ALSO
 /* LICENSE
 /* .ad
 /* .fi
@@ -47,6 +43,7 @@
 /* Application-specific. */
 
 #include "smtp.h"
+#include "smtp_sasl.h"
 
 /* smtp_state_alloc - initialize */
 
@@ -64,6 +61,9 @@ SMTP_STATE *smtp_state_alloc(void)
     state->features = 0;
     state->history = 0;
     state->error_mask = 0;
+#ifdef USE_SASL_AUTH
+    smtp_sasl_connect(state);
+#endif
     return (state);
 }
 
@@ -74,5 +74,8 @@ void    smtp_state_free(SMTP_STATE *state)
     vstring_free(state->buffer);
     vstring_free(state->scratch);
     vstring_free(state->scratch2);
+#ifdef USE_AUTH
+    smtp_sasl_cleanup(state);
+#endif
     myfree((char *) state);
 }
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 7203499fcf548577d40f4aeee296be610c33166a..67b36092c791a82a45a450b40f7137c708b128be 100644 (file)
@@ -1,9 +1,10 @@
 SHELL  = /bin/sh
 SRCS   = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
-       smtpd_peer.c
+       smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c
 OBJS   = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
-       smtpd_peer.o
-HDRS   = smtpd_token.h smtpd_check.h smtpd_chat.h
+       smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o
+HDRS   = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
+       smtpd_sasl_glue.h
 TESTSRC        = smtpd_token_test.c
 WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
        -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
@@ -64,7 +65,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 tests: smtpd_check_test smtpd_check_test2 smtpd_check_test3 smtpd_token_test
 
@@ -128,6 +129,8 @@ smtpd.o: smtpd_token.h
 smtpd.o: smtpd.h
 smtpd.o: smtpd_check.h
 smtpd.o: smtpd_chat.h
+smtpd.o: smtpd_sasl_proto.h
+smtpd.o: smtpd_sasl_glue.h
 smtpd_chat.o: smtpd_chat.c
 smtpd_chat.o: ../include/sys_defs.h
 smtpd_chat.o: ../include/msg.h
@@ -194,6 +197,40 @@ smtpd_peer.o: ../include/vbuf.h
 smtpd_peer.o: ../include/vstring.h
 smtpd_peer.o: ../include/argv.h
 smtpd_peer.o: ../include/mail_stream.h
+smtpd_sasl_glue.o: smtpd_sasl_glue.c
+smtpd_sasl_glue.o: ../include/sys_defs.h
+smtpd_sasl_glue.o: ../include/msg.h
+smtpd_sasl_glue.o: ../include/mymalloc.h
+smtpd_sasl_glue.o: ../include/namadr_list.h
+smtpd_sasl_glue.o: ../include/mail_params.h
+smtpd_sasl_glue.o: ../include/smtp_stream.h
+smtpd_sasl_glue.o: ../include/vstring.h
+smtpd_sasl_glue.o: ../include/vbuf.h
+smtpd_sasl_glue.o: ../include/vstream.h
+smtpd_sasl_glue.o: smtpd.h
+smtpd_sasl_glue.o: ../include/argv.h
+smtpd_sasl_glue.o: ../include/mail_stream.h
+smtpd_sasl_glue.o: smtpd_sasl_glue.h
+smtpd_sasl_glue.o: smtpd_chat.h
+smtpd_sasl_proto.o: smtpd_sasl_proto.c
+smtpd_sasl_proto.o: ../include/sys_defs.h
+smtpd_sasl_proto.o: ../include/msg.h
+smtpd_sasl_proto.o: ../include/mymalloc.h
+smtpd_sasl_proto.o: ../include/mail_params.h
+smtpd_sasl_proto.o: ../include/mail_proto.h
+smtpd_sasl_proto.o: ../include/vstream.h
+smtpd_sasl_proto.o: ../include/vbuf.h
+smtpd_sasl_proto.o: ../include/iostuff.h
+smtpd_sasl_proto.o: ../include/mail_error.h
+smtpd_sasl_proto.o: ../include/name_mask.h
+smtpd_sasl_proto.o: smtpd.h
+smtpd_sasl_proto.o: ../include/vstring.h
+smtpd_sasl_proto.o: ../include/argv.h
+smtpd_sasl_proto.o: ../include/mail_stream.h
+smtpd_sasl_proto.o: smtpd_token.h
+smtpd_sasl_proto.o: smtpd_chat.h
+smtpd_sasl_proto.o: smtpd_sasl_proto.h
+smtpd_sasl_proto.o: smtpd_sasl_glue.h
 smtpd_state.o: smtpd_state.c
 smtpd_state.o: ../include/sys_defs.h
 smtpd_state.o: ../include/events.h
@@ -201,6 +238,7 @@ smtpd_state.o: ../include/mymalloc.h
 smtpd_state.o: ../include/vstream.h
 smtpd_state.o: ../include/vbuf.h
 smtpd_state.o: ../include/name_mask.h
+smtpd_state.o: ../include/msg.h
 smtpd_state.o: ../include/cleanup_user.h
 smtpd_state.o: ../include/mail_params.h
 smtpd_state.o: ../include/mail_error.h
@@ -209,6 +247,7 @@ smtpd_state.o: ../include/vstring.h
 smtpd_state.o: ../include/argv.h
 smtpd_state.o: ../include/mail_stream.h
 smtpd_state.o: smtpd_chat.h
+smtpd_state.o: smtpd_sasl_glue.h
 smtpd_token.o: smtpd_token.c
 smtpd_token.o: ../include/sys_defs.h
 smtpd_token.o: ../include/mymalloc.h
index 6887e0d8db9b293b523dfe9db670845ffb20dec4..e076c4c3f17af240e067f7e6227e09165825ced8 100644 (file)
@@ -37,6 +37,7 @@
 /*     RFC 1854 (SMTP Pipelining)
 /*     RFC 1870 (Message Size Declaration)
 /*     RFC 1985 (ETRN command) (partial)
+/*     RFC 2554 (AUTH command)
 /* DIAGNOSTICS
 /*     Problems and transactions are logged to \fBsyslogd\fR(8).
 /*
 /* .IP \fBstrict_rfc821_envelopes\fR
 /*     Disallow non-RFC 821 style addresses in envelopes. For example,
 /*     allow RFC822-style address forms with comments, like Sendmail does.
+/* .SH "Authenication controls"
+/* .IP \fBenable_sasl_authentication\fR
+/*     Enable per-session authentication as per RFC 2554 (SASL).
+/*     This functionality is available only when explicitly selected
+/*     at program build time and explicitly enabled at runtime.
 /* .SH Miscellaneous
 /* .ad
 /* .fi
 #include "smtpd.h"
 #include "smtpd_check.h"
 #include "smtpd_chat.h"
+#include "smtpd_sasl_proto.h"
+#include "smtpd_sasl_glue.h"
 
  /*
   * Tunable parameters. Make sure that there is some bound on the length of
@@ -307,6 +315,11 @@ char   *var_alias_maps;
 char   *var_local_rcpt_maps;
 bool    var_allow_untrust_route;
 
+#ifdef USE_SASL_AUTH
+bool    var_smtpd_sasl_enable;
+
+#endif
+
  /*
   * Global state, for stand-alone mode queue file cleanup. When this is
   * non-null at cleanup time, the named file is removed.
@@ -396,6 +409,10 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     else
        smtpd_chat_reply(state, "250-SIZE");
     smtpd_chat_reply(state, "250-ETRN");
+#ifdef USE_SASL_AUTH
+    if (var_smtpd_sasl_enable)
+       smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list);
+#endif
     smtpd_chat_reply(state, "250 8BITMIME");
     return (0);
 }
@@ -592,6 +609,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        } else if (strncasecmp(arg, "SIZE=", 5) == 0) {
            if ((state->msg_size = off_cvt_string(arg + 5)) < 0)
                state->msg_size = 0;
+#ifdef USE_SASL_AUTH
+       } else if (strncasecmp(arg, "AUTH=", 5) == 0) {
+           if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) {
+               smtpd_chat_reply(state, "%s", err);
+               return (-1);
+           }
+#endif
        } else {
            state->error_mask |= MAIL_ERROR_PROTOCOL;
            smtpd_chat_reply(state, "555 Unsupported option: %s", arg);
@@ -615,7 +639,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      * Open queue file or IPC stream.
      */
     mail_open_stream(state);
+#ifdef USE_SASL_AUTH
+    if (var_smtpd_sasl_enable)
+       smtpd_sasl_mail_log(state);
+    else
+#else
     msg_info("%s: client=%s[%s]", state->queue_id, state->name, state->addr);
+#endif
 
     /*
      * Record the time of arrival and the sender envelope address.
@@ -660,6 +690,9 @@ static void mail_reset(SMTPD_STATE *state)
        myfree(state->sender);
        state->sender = 0;
     }
+#ifdef USE_SASL_AUTH
+    smtpd_sasl_mail_reset(state);
+#endif
 }
 
 /* rcpt_cmd - process RCPT TO command */
@@ -1061,6 +1094,11 @@ typedef struct SMTPD_CMD {
 static SMTPD_CMD smtpd_cmd_table[] = {
     "HELO", helo_cmd,
     "EHLO", ehlo_cmd,
+
+#ifdef USE_SASL_AUTH
+    "AUTH", smtpd_sasl_auth_cmd,
+#endif
+
     "MAIL", mail_cmd,
     "RCPT", rcpt_cmd,
     "DATA", data_cmd,
@@ -1182,6 +1220,9 @@ static void smtpd_proto(SMTPD_STATE *state)
      * dialog.
      */
     helo_reset(state);
+#ifdef USE_SASL_AUTH
+    smtpd_sasl_auth_reset(state);
+#endif
     mail_reset(state);
     rcpt_reset(state);
     smtpd_chat_reset(state);
@@ -1304,6 +1345,11 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
     smtpd_check_init();
     debug_peer_init();
     msg_cleanup(smtpd_cleanup);
+
+#ifdef USE_SASL_AUTH
+    if (var_smtpd_sasl_enable)
+       smtpd_sasl_initialize();
+#endif
 }
 
 /* main - the main program */
@@ -1335,6 +1381,9 @@ int     main(int argc, char **argv)
        VAR_STRICT_RFC821_ENV, DEF_STRICT_RFC821_ENV, &var_strict_rfc821_env,
        VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd,
        VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route,
+#ifdef USE_SASL_AUTH
+       VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable,
+#endif
        0,
     };
     static CONFIG_STR_TABLE str_table[] = {
index 13549faca6dfd618547e46386ae5d298587dd5b4..e64971f13c29928575d5c0dd9f004124fc8c39c5 100644 (file)
@@ -8,6 +8,14 @@
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * SASL library.
+  */
+#ifdef USE_SASL_AUTH
+#include <sasl.h>
+#include <saslutil.h>
+#endif
+
  /*
   * Utility library.
   */
@@ -53,6 +61,15 @@ typedef struct SMTPD_STATE {
     char   *where;
     int     recursion;
     off_t   msg_size;
+#ifdef USE_SASL_AUTH
+    char   *sasl_mechanism_list;
+    char   *sasl_method;
+    char   *sasl_username;
+    char   *sasl_sender;
+    sasl_conn_t *sasl_conn;
+    VSTRING *sasl_encoded;
+    VSTRING *sasl_decoded;
+#endif
 } SMTPD_STATE;
 
 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
index 5b63353a614f290f7367170279c36ed1b9c017f0..8677106dc886060aa08c47f440efdd05c0fba302 100644 (file)
@@ -768,6 +768,19 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, char *name,
     return (SMTPD_CHECK_DUNNO);
 }
 
+#ifdef USE_SASL_AUTH
+
+/* permit_sasl_auth - OK for authenticated connection */
+
+static int permit_sasl_auth(SMTPD_STATE *state)
+{
+    if (state->sasl_username)
+       return (SMTPD_CHECK_OK);
+    return (SMTPD_CHECK_DUNNO);
+}
+
+#endif
+
 /* check_relay_domains - OK/FAIL for message relaying */
 
 static int check_relay_domains(SMTPD_STATE *state, char *recipient,
@@ -1665,6 +1678,10 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
            if (cpp[1] != 0)
                msg_warn("restriction `%s' after `%s' is ignored",
                         cpp[1], CHECK_RELAY_DOMAINS);
+#ifdef USE_SASL_AUTH
+       } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) {
+           status = permit_sasl_auth(state);
+#endif
        } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
            if (state->recipient)
                status = reject_unknown_address(state, state->recipient,
diff --git a/postfix/smtpd/smtpd_sasl_glue.c b/postfix/smtpd/smtpd_sasl_glue.c
new file mode 100644 (file)
index 0000000..e861fc2
--- /dev/null
@@ -0,0 +1,370 @@
+/*++
+/* NAME
+/*     smtpd_sasl_glue 3
+/* SUMMARY
+/*     Postfix SMTP server, SASL support interface
+/* SYNOPSIS
+/*     #include "smtpd_sasl_glue.h"
+/*
+/*     void    smtpd_sasl_initialize()
+/*
+/*     void    smtpd_sasl_connect(state)
+/*     SMTPD_STATE *state;
+/*
+/*     char    *smtpd_sasl_authenticate(state, sasl_method, init_response)
+/*     SMTPD_STATE *state;
+/*     const char *sasl_method;
+/*     const char *init_response;
+/*
+/*     void    smtpd_sasl_logout(state)
+/*     SMTPD_STATE *state;
+/*
+/*     void    smtpd_sasl_disconnect(state)
+/*     SMTPD_STATE *state;
+/* DESCRIPTION
+/*     This module encapsulates most of the detail specific to SASL
+/*     authentication.
+/*
+/*     smtpd_sasl_initialize() initializes the SASL library. This
+/*     routine should be called once at process start-up. It may
+/*     need access to the file system for run-time loading of
+/*     plug-in modules. There is no corresponding cleanup routine.
+/*
+/*     smtpd_sasl_connect() performs per-connection initialization.
+/*     This routine should be called once at the start of every
+/*     connection.
+/*
+/*     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:
+/* .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_logout() cleant up after smtpd_sasl_authenticate().
+/*     This routine exists for the sake of symmetry.
+/*
+/*     smtpd_sasl_disconnect() performs per-connection cleanup.
+/*     This routine should be called at the end of every connection.
+/*
+/*     Arguments:
+/* .IP state
+/*     SMTP session context.
+/* .IP sasl_method
+/*     A SASL mechanism name
+/* .IP init_reply
+/*     An optional initial client response.
+/* DIAGNOSTICS
+/*     All errors are fatal.
+/* 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 <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <namadr_list.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <smtp_stream.h>
+
+/* Application-specific. */
+
+#include "smtpd.h"
+#include "smtpd_sasl_glue.h"
+#include "smtpd_chat.h"
+
+#ifdef USE_SASL_AUTH
+
+/*
+ * Silly little macros.
+ */
+#define STR(s) vstring_str(s)
+
+/* 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:
+       msg_fatal("%s", message);
+       break;
+    case SASL_LOG_WARNING:
+       msg_warn("%s", message);
+       break;
+    case SASL_LOG_INFO:
+       if (msg_verbose)
+           msg_info("%s", message);
+       break;
+    }
+    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}
+};
+
+/* smtpd_sasl_initialize - per-process initialization */
+
+void    smtpd_sasl_initialize(void)
+{
+
+    /*
+     * Initialize the library: load SASL plug-in routines, etc.
+     */
+    if (sasl_server_init(callbacks, "smtpd") != SASL_OK)
+       msg_fatal("SASL per-process initialization failed");
+}
+
+/* smtpd_sasl_connect - per-connection initialization */
+
+void    smtpd_sasl_connect(SMTPD_STATE *state)
+{
+    int     sasl_mechanism_count;
+    sasl_security_properties_t sec_props;
+
+    /*
+     * Initialize SASL-specific state variables. Use long-lived storage for
+     * base 64 conversion results, rather than local variables, to avoid
+     * memory leaks when a read or write routine returns abnormally after
+     * timeout or I/O error.
+     */
+    state->sasl_mechanism_list = 0;
+    state->sasl_username = 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 DEFAULT_USER_REALM     ((char *) 0)
+#define NO_SECURITY_LAYERS     (0)
+#define NO_SESSION_CALLBACKS   ((sasl_callback_t *) 0)
+
+    if (sasl_server_new("smtp", var_myhostname, DEFAULT_USER_REALM,
+                       NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS,
+                       &state->sasl_conn) != SASL_OK)
+       msg_fatal("SASL per-connection server initialization");
+
+    /*
+     * Security options. XXX What exactly is this supposed to be doing? The
+     * cyrus-sasl-1.5.15 source code has no documentation at all about this
+     * routine.
+     */
+    memset(&sec_props, 0, sizeof(sec_props));
+    sec_props.min_ssf = 0;
+    sec_props.max_ssf = 1;                     /* don't allow real SASL
+                                                * security layer */
+    sec_props.security_flags = 0;
+    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");
+
+    /*
+     * 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,
+                     "250-AUTH ", " ", "",
+                     &state->sasl_mechanism_list,
+                     IGNORE_MECHANISM_LEN,
+                     &sasl_mechanism_count) != SASL_OK
+       || sasl_mechanism_count <= 0)
+       msg_fatal("no SASL authentication mechanisms");
+}
+
+/* smtpd_sasl_disconnect - per-connection cleanup */
+
+void    smtpd_sasl_disconnect(SMTPD_STATE *state)
+{
+    if (state->sasl_mechanism_list) {
+       free(state->sasl_mechanism_list);
+       state->sasl_mechanism_list = NULL;
+    }
+    if (state->sasl_conn) {
+       sasl_dispose(&state->sasl_conn);
+       state->sasl_conn = 0;
+    }
+    vstring_free(state->sasl_decoded);
+    vstring_free(state->sasl_encoded);
+}
+
+/* smtpd_sasl_authenticate - per-session authentication */
+
+char   *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;
+    char   *serverout;
+    unsigned serveroutlen;
+    int     result;
+    const char *errstr = 0;
+
+#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
+#define LOG_IFSET(text,var) IFELSE((var),(text),""), IFELSE((var),(var),"")
+
+    if (msg_verbose)
+       msg_info("%s: sasl_method %s%s%s", myname, sasl_method,
+                LOG_IFSET(", init_response ", init_response));
+
+    /*
+     * Sanity check.
+     */
+    if (state->sasl_username || state->sasl_method)
+       msg_panic("%s: already authenticated", myname);
+
+    /*
+     * 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, &dec_length) != SASL_OK)
+           return ("501 AUTH 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) {
+
+       /*
+        * 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.
+        */
+       if (msg_verbose)
+           msg_info("%s: uncoded challenge: %.*s",
+                    myname, 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);
+       free(serverout);
+       smtpd_chat_reply(state, "334 %s", STR(state->sasl_encoded));
+
+       /*
+        * Receive the client response. "*" means that the client gives up.
+        * 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.
+        */
+       smtpd_chat_query(state);
+       if (strcmp(vstring_str(state->buffer), "*") == 0)
+           return ("501 Authentication aborted");      /* XXX */
+       reply_len = VSTRING_LEN(state->buffer);
+       VSTRING_SPACE(state->sasl_decoded, reply_len);
+       if (sasl_decode64(vstring_str(state->buffer), reply_len,
+                         STR(state->sasl_decoded), &dec_length) != SASL_OK)
+           return ("501 Error: malformed authentication response");
+       if (msg_verbose)
+           msg_info("%s: decoded response: %.*s",
+                    myname, dec_length, STR(state->sasl_decoded));
+       result = sasl_server_step(state->sasl_conn, STR(state->sasl_decoded),
+                           dec_length, &serverout, &serveroutlen, &errstr);
+    }
+
+    /*
+     * The authentication protocol was completed.
+     */
+    if (result != SASL_OK)
+       return ("535 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.
+     */
+    result = sasl_getprop(state->sasl_conn, SASL_USERNAME,
+                         (void **) &serverout);
+    if (result != SASL_OK || serverout == 0)
+       msg_panic("%s: sasl_getprop SASL_USERNAME botch", myname);
+    state->sasl_username = mystrdup(serverout);
+    state->sasl_method = mystrdup(sasl_method);
+    free(serverout);
+
+    return (0);
+}
+
+/* smtpd_sasl_logout - clean up after smtpd_sasl_authenticate */
+
+void    smtpd_sasl_logout(SMTPD_STATE *state)
+{
+    if (state->sasl_username) {
+       myfree(state->sasl_username);
+       state->sasl_username = 0;
+    }
+    if (state->sasl_method) {
+       myfree(state->sasl_method);
+       state->sasl_method = 0;
+    }
+}
+
+#endif
diff --git a/postfix/smtpd/smtpd_sasl_glue.h b/postfix/smtpd/smtpd_sasl_glue.h
new file mode 100644 (file)
index 0000000..89dce76
--- /dev/null
@@ -0,0 +1,35 @@
+/*++
+/* NAME
+/*     smtpd_sasl_glue 3h
+/* SUMMARY
+/*     Postfix SMTP server, SASL support interface
+/* SYNOPSIS
+/*     #include "smtpd_sasl.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * SASL protocol interface
+  */
+extern void smtpd_sasl_initialize(void);
+extern void smtpd_sasl_connect(SMTPD_STATE *);
+extern void smtpd_sasl_disconnect(SMTPD_STATE *);
+extern char *smtpd_sasl_authenticate(SMTPD_STATE *, const char *, const char *);
+extern void smtpd_sasl_logout(SMTPD_STATE *);
+
+/* 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
+/*--*/
diff --git a/postfix/smtpd/smtpd_sasl_proto.c b/postfix/smtpd/smtpd_sasl_proto.c
new file mode 100644 (file)
index 0000000..db5600a
--- /dev/null
@@ -0,0 +1,198 @@
+/*++
+/* NAME
+/*     smtpd_sasl_proto 3
+/* SUMMARY
+/*     Postfix SMTP protocol support for SASL authentication
+/* SYNOPSIS
+/*     #include "smtpd.h"
+/*     #include "smtpd_sasl.h"
+/*
+/*     void    smtpd_sasl_auth_cmd(state, argc, argv)
+/*     SMTPD_STATE *state;
+/*     int     argc;
+/*     SMTPD_TOKEN *argv;
+/*
+/*     void    smtpd_sasl_auth_reset(state)
+/*     SMTPD_STATE *state;
+/*
+/*     char    *smtpd_sasl_mail_opt(state, sender)
+/*     SMTPD_STATE *state;
+/*     const char *sender;
+/*
+/*     void    smtpd_sasl_mail_log(state)
+/*     SMTPD_STATE *state;
+/*
+/*     void    smtpd_sasl_mail_reset(state)
+/*     SMTPD_STATE *state;
+/* DESCRIPTION
+/*     This module contains random chunks of code that implement
+/*     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_reset() cleans up after the AUTH command.
+/*
+/*     smtpd_sasl_mail_opt() implements the AUTH=sender option
+/*     to the MAIL FROM command. The result is an error response
+/*     in case of problems.
+/*
+/*     smtpd_sasl_mail_log() logs the queue ID and client information.
+/*
+/*     smtpd_sasl_mail_reset() cleans up after the AUTH=sender option.
+/*
+/*     Arguments:
+/* .IP state
+/*     SMTP session context.
+/* .IP argc
+/*     Number of command line tokens.
+/* .IP argv
+/*     The command line parsed into tokens.
+/* .IP sender
+/*     Sender address from the AUTH=sender option in the MAIL FROM
+/*     command.
+/* DIAGNOSTICS
+/*     All errors are fatal.
+/* 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 <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <mail_error.h>
+
+/* Application-specific. */
+
+#include "smtpd.h"
+#include "smtpd_token.h"
+#include "smtpd_chat.h"
+#include "smtpd_sasl_proto.h"
+#include "smtpd_sasl_glue.h"
+
+#ifdef USE_SASL_AUTH
+
+/* smtpd_sasl_auth_cmd - process AUTH command */
+
+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;
+       smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
+       return (-1);
+    }
+    if (!var_smtpd_sasl_enable) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "503 Error: authentication not enabled");
+       return (-1);
+    }
+    if (state->sasl_username) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "503 Error: already authenticated");
+       return (-1);
+    }
+    if (argc < 2 || argc > 3) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "501 Syntax: AUTH mechanism");
+       return (-1);
+    }
+
+    /*
+     * All authentication failures shall be logged. The 5xx reply code
+     * triggers tar-pit delays in order to slow down password guessing
+     * attacks.
+     */
+    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 authentication failed",
+                state->name, state->addr);
+       smtpd_chat_reply(state, "%s", err);
+       return (-1);
+    }
+    smtpd_chat_reply(state, "235 Authentication successful");
+    return (0);
+}
+
+/* smtpd_sasl_auth_reset - clean up after AUTH command */
+
+void    smtpd_sasl_auth_reset(SMTPD_STATE *state)
+{
+    smtpd_sasl_logout(state);
+}
+
+/* smtpd_sasl_mail_opt - SASL-specific AUTH=sender option */
+
+char   *smtpd_sasl_mail_opt(SMTPD_STATE *state, const char *addr)
+{
+    if (!var_smtpd_sasl_enable) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       return ("503 Error: authentication disabled");
+    }
+    if (state->sasl_username == 0) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       return ("503 Error: send AUTH command first");
+    }
+    if (state->sasl_sender != 0) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       return ("503 Error: multiple AUTH= options");
+    }
+    if (strcmp(addr, "<>") != 0)
+       state->sasl_sender = mystrdup(addr);
+    return (0);
+}
+
+/* smtpd_sasl_mail_log - SASL-specific MAIL FROM command logging */
+
+void    smtpd_sasl_mail_log(SMTPD_STATE *state)
+{
+#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
+#define LOG_IFSET(text,var) IFELSE((var),(text),""), IFELSE((var),(var),"")
+
+    msg_info("%s: client=%s[%s]%s%s%s%s",
+            state->queue_id, state->name, state->addr,
+            LOG_IFSET(", sasl_method=", state->sasl_method),
+            LOG_IFSET(", sasl_username=", state->sasl_username),
+            LOG_IFSET(", sasl_sender=", state->sasl_sender));
+}
+
+/* smtpd_sasl_mail_reset - SASL-specific MAIL FROM cleanup */
+
+void    smtpd_sasl_mail_reset(SMTPD_STATE *state)
+{
+    if (state->sasl_sender) {
+       myfree(state->sasl_sender);
+       state->sasl_sender = 0;
+    }
+}
+
+#endif
diff --git a/postfix/smtpd/smtpd_sasl_proto.h b/postfix/smtpd/smtpd_sasl_proto.h
new file mode 100644 (file)
index 0000000..bd326be
--- /dev/null
@@ -0,0 +1,35 @@
+/*++
+/* NAME
+/*     smtpd_sasl_proto 3h
+/* SUMMARY
+/*     Postfix SMTP protocol support for SASL authentication
+/* SYNOPSIS
+/*     #include "smtpd_sasl_proto.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * SMTP protocol interface.
+  */
+extern int smtpd_sasl_auth_cmd(SMTPD_STATE *, int, SMTPD_TOKEN *);
+extern void smtpd_sasl_auth_reset(SMTPD_STATE *);
+extern char *smtpd_sasl_mail_opt(SMTPD_STATE *, const char *);
+extern void smtpd_sasl_mail_log(SMTPD_STATE *);
+extern void smtpd_sasl_mail_reset(SMTPD_STATE *);
+
+/* 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
+/*--*/
index a5d8c7dab9b3cf9649bca81fd204aa1f4feb0a1e..063f40506d91d5e1c660c280dce4d4308df26e9c 100644 (file)
@@ -45,6 +45,7 @@
 #include <mymalloc.h>
 #include <vstream.h>
 #include <name_mask.h>
+#include <msg.h>
 
 /* Global library. */
 
@@ -56,6 +57,7 @@
 
 #include "smtpd.h"
 #include "smtpd_chat.h"
+#include "smtpd_sasl_glue.h"
 
 /* smtpd_state_init - initialize after connection establishment */
 
@@ -88,6 +90,10 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->recursion = 0;
     state->msg_size = 0;
 
+#ifdef USE_SASL_AUTH
+    smtpd_sasl_connect(state);
+#endif
+
     /*
      * Initialize peer information.
      */
@@ -112,4 +118,8 @@ void    smtpd_state_reset(SMTPD_STATE *state)
     if (state->buffer)
        vstring_free(state->buffer);
     smtpd_peer_reset(state);
+
+#ifdef USE_SASL_AUTH
+    smtpd_sasl_disconnect(state);
+#endif
 }
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 90cd11386f81f6ea009caaa66f7097ff759b1165..702f55cf64bf505c3ae2a381670e3727c58dc5c9 100644 (file)
@@ -58,7 +58,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 smtp-sink.o: smtp-sink.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index ecada61882dd37c05f6c3b19c13c7dbc494c3dbf..d535d6df0b20d64438faea114fd48f8ab1966e17 100644 (file)
@@ -50,7 +50,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 spawn.o: spawn.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 8dcbb0c6b91ecd1ee6e0f40c69b4d88d503cb59c..a944bf15350f2fb11c75af0e395008f27de05999 100644 (file)
@@ -56,7 +56,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 resolve.o: resolve.c
index 2cc95193a2e271ac2d20b79713940628056f5b38..f9b8f228726c2683c8e181d688b7c938a9ee6a81 100644 (file)
@@ -64,7 +64,6 @@
 -TNAMADR_LIST
 -TNAME_MASK
 -TPEER_NAME
--TPENDING
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_PARAMS
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-Tsasl_conn_t
+-Tsasl_secret_t
index 6309d53421f7cf97ded0b8922978a49177e716ce..349b29d43647e5cb54eb3981404d4932327ff2a4 100644 (file)
@@ -255,7 +255,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 stream_test: stream_test.c $(LIB)
        $(CC) $(CFLAGS)  -o $@ $@.c $(LIB) $(SYSLIBS)
index 670550245df51dbfabca22eca7f34e4ae9a55567..1eb2471aedcecb4234de25bd2a50b01caa41ed18 100644 (file)
@@ -372,7 +372,7 @@ main(int argc, char **argv)
        if ((cmd = mystrtok(&bufp, " ")) == 0)
            continue;
        key = mystrtok(&bufp, " =");
-       value = mystrtok(&bufp, " ");
+       value = mystrtok(&bufp, " =");
        if (strcmp(cmd, "del") == 0 && key && !value) {
            if (dict_del(dict, key))
                vstream_printf("%s: not found\n", key);