From bb268b56ef84113e888f3e9c41f01d386d11ae62 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Thu, 16 Mar 2000 00:00:00 +0000 Subject: [PATCH] snapshot-20000316 --- postfix/.indent.pro | 3 +- postfix/HISTORY | 30 ++ postfix/Makefile | 4 +- postfix/Makefile.in | 8 + postfix/Makefile.init | 4 +- postfix/RELEASE_NOTES | 4 + postfix/SASL_README | 74 +++++ postfix/bounce/.indent.pro | 3 +- postfix/bounce/Makefile.in | 2 +- postfix/cleanup/.indent.pro | 3 +- postfix/cleanup/Makefile.in | 2 +- postfix/cleanup/cleanup_message.c | 16 + postfix/conf/sample-auth.cf | 72 +++++ postfix/conf/sample-tls.cf | 277 +++++++++++++++++ postfix/dns/.indent.pro | 3 +- postfix/dns/Makefile.in | 2 +- postfix/error/.indent.pro | 3 +- postfix/error/Makefile.in | 2 +- postfix/fsstone/.indent.pro | 3 +- postfix/fsstone/Makefile.in | 2 +- postfix/global/.indent.pro | 3 +- postfix/global/Makefile.in | 2 +- postfix/global/mail_params.h | 21 ++ postfix/global/mail_version.h | 2 +- postfix/html/faq.html | 41 ++- postfix/local/.indent.pro | 3 +- postfix/local/Makefile.in | 2 +- postfix/makedefs | 3 +- postfix/master/.indent.pro | 3 +- postfix/master/Makefile.in | 2 +- postfix/pickup/.indent.pro | 3 +- postfix/pickup/Makefile.in | 2 +- postfix/pipe/.indent.pro | 3 +- postfix/pipe/Makefile.in | 2 +- postfix/postalias/.indent.pro | 3 +- postfix/postalias/Makefile.in | 2 +- postfix/postcat/.indent.pro | 3 +- postfix/postcat/Makefile.in | 2 +- postfix/postconf/.indent.pro | 3 +- postfix/postconf/Makefile.in | 2 +- postfix/postconf/extract.awk | 6 +- postfix/postdrop/.indent.pro | 3 +- postfix/postdrop/Makefile.in | 2 +- postfix/postfix/.indent.pro | 3 +- postfix/postfix/Makefile.in | 2 +- postfix/postkick/.indent.pro | 3 +- postfix/postkick/Makefile.in | 2 +- postfix/postlock/.indent.pro | 3 +- postfix/postlock/Makefile.in | 2 +- postfix/postlog/.indent.pro | 3 +- postfix/postlog/Makefile.in | 2 +- postfix/postmap/.indent.pro | 3 +- postfix/postmap/Makefile.in | 2 +- postfix/postsuper/.indent.pro | 3 +- postfix/postsuper/Makefile.in | 2 +- postfix/qmgr/.indent.pro | 3 +- postfix/qmgr/Makefile.in | 2 +- postfix/sendmail/.indent.pro | 3 +- postfix/sendmail/Makefile.in | 2 +- postfix/sendmail/sendmail.c | 39 ++- postfix/showq/.indent.pro | 3 +- postfix/showq/Makefile.in | 2 +- postfix/smtp/.indent.pro | 3 +- postfix/smtp/Makefile.in | 43 ++- postfix/smtp/smtp.c | 20 ++ postfix/smtp/smtp.h | 19 ++ postfix/smtp/smtp_proto.c | 11 + postfix/smtp/smtp_sasl.h | 35 +++ postfix/smtp/smtp_sasl_glue.c | 461 ++++++++++++++++++++++++++++ postfix/smtp/smtp_sasl_proto.c | 113 +++++++ postfix/smtp/smtp_state.c | 11 +- postfix/smtpd/.indent.pro | 3 +- postfix/smtpd/Makefile.in | 47 ++- postfix/smtpd/smtpd.c | 49 +++ postfix/smtpd/smtpd.h | 17 + postfix/smtpd/smtpd_check.c | 17 + postfix/smtpd/smtpd_sasl_glue.c | 370 ++++++++++++++++++++++ postfix/smtpd/smtpd_sasl_glue.h | 35 +++ postfix/smtpd/smtpd_sasl_proto.c | 198 ++++++++++++ postfix/smtpd/smtpd_sasl_proto.h | 35 +++ postfix/smtpd/smtpd_state.c | 10 + postfix/smtpstone/.indent.pro | 3 +- postfix/smtpstone/Makefile.in | 2 +- postfix/spawn/.indent.pro | 3 +- postfix/spawn/Makefile.in | 2 +- postfix/trivial-rewrite/.indent.pro | 3 +- postfix/trivial-rewrite/Makefile.in | 2 +- postfix/util/.indent.pro | 3 +- postfix/util/Makefile.in | 2 +- postfix/util/dict_open.c | 2 +- 90 files changed, 2154 insertions(+), 84 deletions(-) create mode 100644 postfix/SASL_README create mode 100644 postfix/conf/sample-auth.cf create mode 100644 postfix/conf/sample-tls.cf create mode 100644 postfix/smtp/smtp_sasl.h create mode 100644 postfix/smtp/smtp_sasl_glue.c create mode 100644 postfix/smtp/smtp_sasl_proto.c create mode 100644 postfix/smtpd/smtpd_sasl_glue.c create mode 100644 postfix/smtpd/smtpd_sasl_glue.h create mode 100644 postfix/smtpd/smtpd_sasl_proto.c create mode 100644 postfix/smtpd/smtpd_sasl_proto.h diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/HISTORY b/postfix/HISTORY index 58fd9eb63..d627a1b85 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/Makefile b/postfix/Makefile index 424db7120..8d9e069d9 100644 --- a/postfix/Makefile +++ b/postfix/Makefile @@ -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 diff --git a/postfix/Makefile.in b/postfix/Makefile.in index ec3d76ba3..7bf601f1c 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -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 diff --git a/postfix/Makefile.init b/postfix/Makefile.init index 424db7120..8d9e069d9 100644 --- a/postfix/Makefile.init +++ b/postfix/Makefile.init @@ -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 diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index c83265f39..bdcdaedc4 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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 index 000000000..de366bc49 --- /dev/null +++ b/postfix/SASL_README @@ -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. diff --git a/postfix/bounce/.indent.pro b/postfix/bounce/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/bounce/.indent.pro +++ b/postfix/bounce/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/bounce/Makefile.in b/postfix/bounce/Makefile.in index 44d5b7ed2..1298eee45 100644 --- a/postfix/bounce/Makefile.in +++ b/postfix/bounce/Makefile.in @@ -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 diff --git a/postfix/cleanup/.indent.pro b/postfix/cleanup/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/cleanup/.indent.pro +++ b/postfix/cleanup/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/cleanup/Makefile.in b/postfix/cleanup/Makefile.in index 073c93006..8b1da52c8 100644 --- a/postfix/cleanup/Makefile.in +++ b/postfix/cleanup/Makefile.in @@ -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 diff --git a/postfix/cleanup/cleanup_message.c b/postfix/cleanup/cleanup_message.c index c9a48f11c..2c6276357 100644 --- a/postfix/cleanup/cleanup_message.c +++ b/postfix/cleanup/cleanup_message.c @@ -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 index 000000000..412fc8134 --- /dev/null +++ b/postfix/conf/sample-auth.cf @@ -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 index 000000000..97444df4f --- /dev/null +++ b/postfix/conf/sample-tls.cf @@ -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 diff --git a/postfix/dns/.indent.pro b/postfix/dns/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/dns/.indent.pro +++ b/postfix/dns/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/dns/Makefile.in b/postfix/dns/Makefile.in index be767bef2..245fc77ee 100644 --- a/postfix/dns/Makefile.in +++ b/postfix/dns/Makefile.in @@ -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 diff --git a/postfix/error/.indent.pro b/postfix/error/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/error/.indent.pro +++ b/postfix/error/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/error/Makefile.in b/postfix/error/Makefile.in index 5e0542b9c..7d43663d0 100644 --- a/postfix/error/Makefile.in +++ b/postfix/error/Makefile.in @@ -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 diff --git a/postfix/fsstone/.indent.pro b/postfix/fsstone/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/fsstone/.indent.pro +++ b/postfix/fsstone/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/fsstone/Makefile.in b/postfix/fsstone/Makefile.in index 92dbdc3f6..a463020f8 100644 --- a/postfix/fsstone/Makefile.in +++ b/postfix/fsstone/Makefile.in @@ -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 diff --git a/postfix/global/.indent.pro b/postfix/global/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/global/.indent.pro +++ b/postfix/global/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/global/Makefile.in b/postfix/global/Makefile.in index 1eefc0ee1..0b207fe35 100644 --- a/postfix/global/Makefile.in +++ b/postfix/global/Makefile.in @@ -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 diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index e81bb0a62..aaf7468c0 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -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. diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index 7b9ffd13b..60a9586e9 100644 --- a/postfix/global/mail_version.h +++ b/postfix/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20000309" +#define DEF_MAIL_VERSION "Snapshot-20000316" extern char *var_mail_version; /* LICENSE diff --git a/postfix/html/faq.html b/postfix/html/faq.html index 8e582d89c..bff21f6ff 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -2311,12 +2311,51 @@ include directory and of the object library.

-One problem: older DB versions install a file +When building with a third-party DB library you may into one of the +following problems: + +

+ +


Up one level | Postfix FAQ diff --git a/postfix/local/.indent.pro b/postfix/local/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/local/.indent.pro +++ b/postfix/local/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/local/Makefile.in b/postfix/local/Makefile.in index e1c8d8b64..f367ef9c1 100644 --- a/postfix/local/Makefile.in +++ b/postfix/local/Makefile.in @@ -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 diff --git a/postfix/makedefs b/postfix/makedefs index c92a1b216..68bd3d8ac 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -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 diff --git a/postfix/master/.indent.pro b/postfix/master/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/master/.indent.pro +++ b/postfix/master/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/master/Makefile.in b/postfix/master/Makefile.in index a499576de..31a0e36c4 100644 --- a/postfix/master/Makefile.in +++ b/postfix/master/Makefile.in @@ -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 diff --git a/postfix/pickup/.indent.pro b/postfix/pickup/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/pickup/.indent.pro +++ b/postfix/pickup/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/pickup/Makefile.in b/postfix/pickup/Makefile.in index d3b0f35d9..1f20f1934 100644 --- a/postfix/pickup/Makefile.in +++ b/postfix/pickup/Makefile.in @@ -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 diff --git a/postfix/pipe/.indent.pro b/postfix/pipe/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/pipe/.indent.pro +++ b/postfix/pipe/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/pipe/Makefile.in b/postfix/pipe/Makefile.in index aebfd7435..f6879fa0a 100644 --- a/postfix/pipe/Makefile.in +++ b/postfix/pipe/Makefile.in @@ -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 diff --git a/postfix/postalias/.indent.pro b/postfix/postalias/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postalias/.indent.pro +++ b/postfix/postalias/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postalias/Makefile.in b/postfix/postalias/Makefile.in index 1304d7844..1ffd12352 100644 --- a/postfix/postalias/Makefile.in +++ b/postfix/postalias/Makefile.in @@ -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 diff --git a/postfix/postcat/.indent.pro b/postfix/postcat/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postcat/.indent.pro +++ b/postfix/postcat/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postcat/Makefile.in b/postfix/postcat/Makefile.in index 68175a8ba..09a495884 100644 --- a/postfix/postcat/Makefile.in +++ b/postfix/postcat/Makefile.in @@ -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 diff --git a/postfix/postconf/.indent.pro b/postfix/postconf/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postconf/.indent.pro +++ b/postfix/postconf/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postconf/Makefile.in b/postfix/postconf/Makefile.in index a0b8cd1a3..47aab60d0 100644 --- a/postfix/postconf/Makefile.in +++ b/postfix/postconf/Makefile.in @@ -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 diff --git a/postfix/postconf/extract.awk b/postfix/postconf/extract.awk index 8cd8cfc09..ebe866e29 100644 --- a/postfix/postconf/extract.awk +++ b/postfix/postconf/extract.awk @@ -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" diff --git a/postfix/postdrop/.indent.pro b/postfix/postdrop/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postdrop/.indent.pro +++ b/postfix/postdrop/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postdrop/Makefile.in b/postfix/postdrop/Makefile.in index cb8ed7547..8f24b00c0 100644 --- a/postfix/postdrop/Makefile.in +++ b/postfix/postdrop/Makefile.in @@ -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 diff --git a/postfix/postfix/.indent.pro b/postfix/postfix/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postfix/.indent.pro +++ b/postfix/postfix/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postfix/Makefile.in b/postfix/postfix/Makefile.in index d807c878b..b1f63de7c 100644 --- a/postfix/postfix/Makefile.in +++ b/postfix/postfix/Makefile.in @@ -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 diff --git a/postfix/postkick/.indent.pro b/postfix/postkick/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postkick/.indent.pro +++ b/postfix/postkick/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postkick/Makefile.in b/postfix/postkick/Makefile.in index 9a0fd6b02..c846ca697 100644 --- a/postfix/postkick/Makefile.in +++ b/postfix/postkick/Makefile.in @@ -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 diff --git a/postfix/postlock/.indent.pro b/postfix/postlock/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postlock/.indent.pro +++ b/postfix/postlock/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postlock/Makefile.in b/postfix/postlock/Makefile.in index c2ee45d3c..0d194091b 100644 --- a/postfix/postlock/Makefile.in +++ b/postfix/postlock/Makefile.in @@ -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 diff --git a/postfix/postlog/.indent.pro b/postfix/postlog/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postlog/.indent.pro +++ b/postfix/postlog/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postlog/Makefile.in b/postfix/postlog/Makefile.in index fbfad473f..e3f00e469 100644 --- a/postfix/postlog/Makefile.in +++ b/postfix/postlog/Makefile.in @@ -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 diff --git a/postfix/postmap/.indent.pro b/postfix/postmap/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postmap/.indent.pro +++ b/postfix/postmap/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postmap/Makefile.in b/postfix/postmap/Makefile.in index 5cd483acd..db3a6bd5f 100644 --- a/postfix/postmap/Makefile.in +++ b/postfix/postmap/Makefile.in @@ -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 diff --git a/postfix/postsuper/.indent.pro b/postfix/postsuper/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/postsuper/.indent.pro +++ b/postfix/postsuper/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/postsuper/Makefile.in b/postfix/postsuper/Makefile.in index 1b58244f9..b5caf22cb 100644 --- a/postfix/postsuper/Makefile.in +++ b/postfix/postsuper/Makefile.in @@ -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 diff --git a/postfix/qmgr/.indent.pro b/postfix/qmgr/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/qmgr/.indent.pro +++ b/postfix/qmgr/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/qmgr/Makefile.in b/postfix/qmgr/Makefile.in index 144e089f9..99ce9e6ef 100644 --- a/postfix/qmgr/Makefile.in +++ b/postfix/qmgr/Makefile.in @@ -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 diff --git a/postfix/sendmail/.indent.pro b/postfix/sendmail/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/sendmail/.indent.pro +++ b/postfix/sendmail/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/sendmail/Makefile.in b/postfix/sendmail/Makefile.in index 9a71d3422..da946438b 100644 --- a/postfix/sendmail/Makefile.in +++ b/postfix/sendmail/Makefile.in @@ -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 diff --git a/postfix/sendmail/sendmail.c b/postfix/sendmail/sendmail.c index 90e27bcf1..311350544 100644 --- a/postfix/sendmail/sendmail.c +++ b/postfix/sendmail/sendmail.c @@ -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)" @@ -109,6 +111,9 @@ /* .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)" @@ -285,6 +290,13 @@ 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: diff --git a/postfix/showq/.indent.pro b/postfix/showq/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/showq/.indent.pro +++ b/postfix/showq/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/showq/Makefile.in b/postfix/showq/Makefile.in index 55a1e0879..ec75f8c9b 100644 --- a/postfix/showq/Makefile.in +++ b/postfix/showq/Makefile.in @@ -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 diff --git a/postfix/smtp/.indent.pro b/postfix/smtp/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/smtp/.indent.pro +++ b/postfix/smtp/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/smtp/Makefile.in b/postfix/smtp/Makefile.in index c7163fdf4..4db9cb944 100644 --- a/postfix/smtp/Makefile.in +++ b/postfix/smtp/Makefile.in @@ -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 diff --git a/postfix/smtp/smtp.c b/postfix/smtp/smtp.c index 29dc70dab..95543bba3 100644 --- a/postfix/smtp/smtp.c +++ b/postfix/smtp/smtp.c @@ -185,6 +185,7 @@ /* 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, }; diff --git a/postfix/smtp/smtp.h b/postfix/smtp/smtp.h index e236d9a07..d73494871 100644 --- a/postfix/smtp/smtp.h +++ b/postfix/smtp/smtp.h @@ -8,6 +8,14 @@ /* DESCRIPTION /* .nf + /* + * SASL library. + */ +#ifdef USE_SASL_AUTH +#include +#include +#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 diff --git a/postfix/smtp/smtp_proto.c b/postfix/smtp/smtp_proto.c index 9be06bd45..8e0b7c8c2 100644 --- a/postfix/smtp/smtp_proto.c +++ b/postfix/smtp/smtp_proto.c @@ -103,6 +103,7 @@ #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 index 000000000..1c6ec6f76 --- /dev/null +++ b/postfix/smtp/smtp_sasl.h @@ -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 index 000000000..5d87d1440 --- /dev/null +++ b/postfix/smtp/smtp_sasl_glue.c @@ -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 +#include +#include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + + /* + * Utility library + */ +#include +#include +#include +#include + + /* + * Global library + */ +#include +#include +#include + + /* + * 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 index 000000000..ed34c3522 --- /dev/null +++ b/postfix/smtp/smtp_sasl_proto.c @@ -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 + +/* Utility library. */ + +#include +#include + +/* Global library. */ + +#include + +/* 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 diff --git a/postfix/smtp/smtp_state.c b/postfix/smtp/smtp_state.c index 1ab6a6f1d..07696dd91 100644 --- a/postfix/smtp/smtp_state.c +++ b/postfix/smtp/smtp_state.c @@ -15,10 +15,6 @@ /* 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); } diff --git a/postfix/smtpd/.indent.pro b/postfix/smtpd/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/smtpd/.indent.pro +++ b/postfix/smtpd/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/smtpd/Makefile.in b/postfix/smtpd/Makefile.in index 7203499fc..67b36092c 100644 --- a/postfix/smtpd/Makefile.in +++ b/postfix/smtpd/Makefile.in @@ -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 diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index 6887e0d8d..e076c4c3f 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -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). /* @@ -58,6 +59,11 @@ /* .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 @@ -257,6 +263,8 @@ #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[] = { diff --git a/postfix/smtpd/smtpd.h b/postfix/smtpd/smtpd.h index 13549faca..e64971f13 100644 --- a/postfix/smtpd/smtpd.h +++ b/postfix/smtpd/smtpd.h @@ -8,6 +8,14 @@ /* DESCRIPTION /* .nf + /* + * SASL library. + */ +#ifdef USE_SASL_AUTH +#include +#include +#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 *); diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index 5b63353a6..8677106dc 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -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 index 000000000..e861fc22b --- /dev/null +++ b/postfix/smtpd/smtpd_sasl_glue.c @@ -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 +#include +#include + +/* Utility library. */ + +#include +#include +#include + +/* Global library. */ + +#include +#include + +/* 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 index 000000000..89dce7643 --- /dev/null +++ b/postfix/smtpd/smtpd_sasl_glue.h @@ -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 index 000000000..db5600a59 --- /dev/null +++ b/postfix/smtpd/smtpd_sasl_proto.c @@ -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 +#include + +/* Utility library. */ + +#include +#include + +/* Global library. */ + +#include +#include +#include + +/* 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 index 000000000..bd326be58 --- /dev/null +++ b/postfix/smtpd/smtpd_sasl_proto.h @@ -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 +/*--*/ diff --git a/postfix/smtpd/smtpd_state.c b/postfix/smtpd/smtpd_state.c index a5d8c7dab..063f40506 100644 --- a/postfix/smtpd/smtpd_state.c +++ b/postfix/smtpd/smtpd_state.c @@ -45,6 +45,7 @@ #include #include #include +#include /* 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 } diff --git a/postfix/smtpstone/.indent.pro b/postfix/smtpstone/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/smtpstone/.indent.pro +++ b/postfix/smtpstone/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/smtpstone/Makefile.in b/postfix/smtpstone/Makefile.in index 90cd11386..702f55cf6 100644 --- a/postfix/smtpstone/Makefile.in +++ b/postfix/smtpstone/Makefile.in @@ -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 diff --git a/postfix/spawn/.indent.pro b/postfix/spawn/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/spawn/.indent.pro +++ b/postfix/spawn/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/spawn/Makefile.in b/postfix/spawn/Makefile.in index ecada6188..d535d6df0 100644 --- a/postfix/spawn/Makefile.in +++ b/postfix/spawn/Makefile.in @@ -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 diff --git a/postfix/trivial-rewrite/.indent.pro b/postfix/trivial-rewrite/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/trivial-rewrite/.indent.pro +++ b/postfix/trivial-rewrite/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/trivial-rewrite/Makefile.in b/postfix/trivial-rewrite/Makefile.in index 8dcbb0c6b..a944bf153 100644 --- a/postfix/trivial-rewrite/Makefile.in +++ b/postfix/trivial-rewrite/Makefile.in @@ -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 diff --git a/postfix/util/.indent.pro b/postfix/util/.indent.pro index 2cc95193a..f9b8f2287 100644 --- a/postfix/util/.indent.pro +++ b/postfix/util/.indent.pro @@ -64,7 +64,6 @@ -TNAMADR_LIST -TNAME_MASK -TPEER_NAME --TPENDING -TPICKUP_INFO -TPIPE_ATTR -TPIPE_PARAMS @@ -110,3 +109,5 @@ -TWAIT_STATUS_T -TWATCHDOG -TWATCH_FD +-Tsasl_conn_t +-Tsasl_secret_t diff --git a/postfix/util/Makefile.in b/postfix/util/Makefile.in index 6309d5342..349b29d43 100644 --- a/postfix/util/Makefile.in +++ b/postfix/util/Makefile.in @@ -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) diff --git a/postfix/util/dict_open.c b/postfix/util/dict_open.c index 670550245..1eb2471ae 100644 --- a/postfix/util/dict_open.c +++ b/postfix/util/dict_open.c @@ -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);