Loading ...
Sorry, an error occurred while loading the content.

Re: SMTP-SASL auth failure caching.

Expand Messages
  • Keean Schupke
    Hi, here is V2.1 of the smtp-sasl auth cachine patch with generic cache. Regards, Keean Schupke, Fry-IT Ltd. diff -r -U5 -N postfix-2.4.5.orig/Makefile.in
    Message 1 of 77 , Dec 2, 2007
    • 0 Attachment
      Hi, here is V2.1 of the smtp-sasl auth cachine patch with generic cache.

      Regards,
      Keean Schupke, Fry-IT Ltd.


      diff -r -U5 -N postfix-2.4.5.orig/Makefile.in postfix-2.4.5/Makefile.in
      --- postfix-2.4.5.orig/Makefile.in 2007-11-20 08:24:25.000000000 +0000
      +++ postfix-2.4.5/Makefile.in 2007-12-01 10:32:01.000000000 +0000
      @@ -5,11 +5,11 @@
      src/postfix src/smtpstone \
      src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \
      src/trivial-rewrite src/qmgr src/oqmgr src/smtp src/bounce \
      src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \
      src/postkick src/postlock src/postlog src/postmap src/postqueue \
      - src/postsuper src/qmqpd src/spawn src/flush src/verify \
      + src/postsuper src/qmqpd src/spawn src/flush src/verify src/cache \
      rmail \
      src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr
      MANDIRS = proto man html

      default: update
      diff -r -U5 -N postfix-2.4.5.orig/conf/master.cf postfix-2.4.5/conf/master.cf
      --- postfix-2.4.5.orig/conf/master.cf 2007-11-22 09:25:13.000000000 +0000
      +++ postfix-2.4.5/conf/master.cf 2007-12-01 21:00:11.000000000 +0000
      @@ -24,10 +24,12 @@
      rewrite unix - - - - - trivial-rewrite
      bounce unix - - - - 0 bounce
      defer unix - - - - 0 bounce
      trace unix - - - - 0 bounce
      verify unix - - - - 1 verify
      +auth_cache unix - - - - 1 cache
      + -o cache_map = $smtp_sasl_auth_cache_map
      flush unix n - - 1000? 0 flush
      proxymap unix - - n - - proxymap
      smtp unix - - - - - smtp
      smtp1 unix - - - - - smtp
      -o smtp_destination_concurrency_limit = 1
      diff -r -U5 -N postfix-2.4.5.orig/src/cache/Makefile.in
      postfix-2.4.5/src/cache/Makefile.in
      --- postfix-2.4.5.orig/src/cache/Makefile.in 1970-01-01
      01:00:00.000000000 +0100
      +++ postfix-2.4.5/src/cache/Makefile.in 2007-12-01 08:47:23.000000000 +0000
      @@ -0,0 +1,58 @@
      +SHELL = /bin/sh
      +SRCS = cache.c
      +OBJS = cache.o
      +HDRS =
      +TESTSRC =
      +DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
      +CFLAGS = $(DEBUG) $(OPT) $(DEFS)
      +TESTPROG=
      +PROG = cache
      +INC_DIR = ../../include
      +LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
      +
      +.c.o:; $(CC) $(CFLAGS) -c $*.c
      +
      +$(PROG): $(OBJS) $(LIBS)
      + $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
      +
      +$(OBJS): ../../conf/makedefs.out
      +
      +Makefile: Makefile.in
      + cat ../../conf/makedefs.out $? >$@
      +
      +test: $(TESTPROG)
      +
      +tests: test
      +
      +root_tests:
      +
      +update: ../../libexec/$(PROG)
      +
      +../../libexec/$(PROG): $(PROG)
      + cp $(PROG) ../../libexec
      +
      +printfck: $(OBJS) $(PROG)
      + rm -rf printfck
      + mkdir printfck
      + sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
      + set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
      + cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
      +
      +lint:
      + lint $(DEFS) $(SRCS) $(LINTFIX)
      +
      +clean:
      + rm -f *.o *core $(PROG) $(TESTPROG) junk
      + rm -rf printfck
      +
      +tidy: clean
      +
      +depend: $(MAKES)
      + (sed '1,/^# do not edit/!d' Makefile.in; \
      + set -e; for i in [a-z][a-z0-9]*.c; do \
      + $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e
      '/^# *1 *"\([^"]*\)".*/{' \
      + -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
      + -e 's/o: \.\//o: /' -e p -e '}' ; \
      + done | sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
      + @$(EXPORT) make -f Makefile.in Makefile 1>&2
      +
      diff -r -U5 -N postfix-2.4.5.orig/src/cache/cache.c
      postfix-2.4.5/src/cache/cache.c
      --- postfix-2.4.5.orig/src/cache/cache.c 1970-01-01
      01:00:00.000000000 +0100
      +++ postfix-2.4.5/src/cache/cache.c 2007-12-01 21:43:07.000000000 +0000
      @@ -0,0 +1,237 @@
      +/* System library. */
      +
      +#include <sys_defs.h>
      +#include <sys/stat.h>
      +#include <time.h>
      +#include <string.h>
      +#include <stdlib.h>
      +#include <unistd.h>
      +
      +/* Utility library. */
      +
      +#include <msg.h>
      +#include <mymalloc.h>
      +#include <htable.h>
      +#include <dict_ht.h>
      +#include <dict.h>
      +#include <split_at.h>
      +#include <stringops.h>
      +
      +/* Global library. */
      +
      +#include <mail_conf.h>
      +#include <mail_params.h>
      +#include <mail_version.h>
      +#include <mail_proto.h>
      +#include <cache_client.h>
      +
      +/* Server skeleton. */
      +
      +#include <mail_server.h>
      +
      +/* Application-specific. */
      +
      + /*
      + * Tunable parameters.
      + */
      +char *var_cache_map;
      +
      + /*
      + * State.
      + */
      +static DICT *cache_map;
      +
      + /*
      + * Silly little macros.
      + */
      +#define STR(x) vstring_str(x)
      +#define STREQ(x,y) (strcmp(x,y) == 0)
      +
      +/* cache_update_service */
      +
      +static void cache_update_service(VSTREAM *client_stream)
      +{
      + VSTRING *key = vstring_alloc(10);
      + VSTRING *value = vstring_alloc(10);
      +
      + if (attr_scan(client_stream, ATTR_FLAG_STRICT,
      + ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
      + ATTR_TYPE_STR, MAIL_ATTR_VALUE, value,
      + ATTR_TYPE_END) == 2) {
      + dict_put(cache_map, STR(key),STR(value));
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_OK,
      + ATTR_TYPE_END);
      + } else {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_BAD,
      + ATTR_TYPE_END);
      + }
      +
      + vstring_free(key);
      + vstring_free(value);
      +}
      +
      +/* cache_query_service */
      +
      +static void cache_query_service(VSTREAM *client_stream)
      +{
      + VSTRING *key = vstring_alloc(10);
      + const char *raw_data;
      +
      + if (attr_scan(client_stream, ATTR_FLAG_STRICT,
      + ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
      + ATTR_TYPE_END) == 1) {
      + if ((raw_data = dict_get(cache_map, STR(key)))) {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_OK,
      + ATTR_TYPE_STR, MAIL_ATTR_VALUE, raw_data,
      + ATTR_TYPE_END);
      + } else {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_FAIL,
      + ATTR_TYPE_STR, MAIL_ATTR_VALUE, "",
      + ATTR_TYPE_END);
      + }
      + } else {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_BAD,
      + ATTR_TYPE_END);
      + }
      +
      + vstring_free(key);
      +}
      +
      +/* cache delete service */
      +
      +static void cache_delete_service(VSTREAM *client_stream)
      +{
      + VSTRING *key = vstring_alloc(10);
      +
      + if (attr_scan(client_stream, ATTR_FLAG_STRICT,
      + ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
      + ATTR_TYPE_END) == 1) {
      + if (dict_del(cache_map, STR(key))) {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_FAIL,
      + ATTR_TYPE_END);
      + } else {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_OK,
      + ATTR_TYPE_END);
      + }
      + } else {
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_BAD,
      + ATTR_TYPE_END);
      + }
      +
      + vstring_free(key);
      +}
      +
      +/* cache_service */
      +
      +static void cache_service(VSTREAM *client_stream, char *unused_service,
      + char **argv)
      +{
      + VSTRING *request = vstring_alloc(10);
      +
      + /*
      + * Sanity check. This service takes no command-line arguments.
      + */
      + if (argv[0])
      + msg_fatal("unexpected command-line argument: %s", argv[0]);
      +
      + /*
      + * This routine runs whenever a client connects to the socket dedicated
      + * to the cache service. All connection-management stuff
      + * is handled by the common code in multi_server.c.
      + */
      + if (attr_scan(client_stream,
      + ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
      + ATTR_TYPE_STR, MAIL_ATTR_REQ, request,
      + ATTR_TYPE_END) == 1) {
      + if (STREQ(STR(request), CACHE_REQ_UPDATE)) {
      + cache_update_service(client_stream);
      + } else if (STREQ(STR(request), CACHE_REQ_QUERY)) {
      + cache_query_service(client_stream);
      + } else if (STREQ(STR(request), CACHE_REQ_DELETE)) {
      + cache_delete_service(client_stream);
      + } else {
      + msg_warn("unrecognized request: \"%s\", ignored", STR(request));
      + attr_print(client_stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, CACHE_STAT_BAD,
      + ATTR_TYPE_END);
      + }
      + }
      + vstream_fflush(client_stream);
      + vstring_free(request);
      +}
      +
      +/* post_jail_init - post-jail initialization */
      +
      +static void post_jail_init(char *unused_name, char **unused_argv)
      +{
      +
      + /*
      + * If the database is in volatile memory only, prevent automatic process
      + * suicide after a limited number of client requests or after a limited
      + * amount of idle time.
      + */
      + if (*var_cache_map == 0) {
      + var_use_limit = 0;
      + var_idle_limit = 0;
      + }
      +}
      +
      +/* pre_jail_init - pre-jail initialization */
      +
      +static void pre_jail_init(char *unused_name, char **unused_argv)
      +{
      + mode_t saved_mask;
      +
      + /*
      + * Keep state in persistent (external) or volatile (internal) map.
      + */
      +#define CACHE_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
      +
      + if (*var_cache_map) {
      + saved_mask = umask(022);
      + cache_map = dict_open(var_cache_map,
      + O_CREAT | O_RDWR,
      + CACHE_DICT_OPEN_FLAGS);
      + (void) umask(saved_mask);
      + } else {
      + cache_map = dict_ht_open("verify", htable_create(0), myfree);
      + }
      +
      + /*
      + * Never, ever, get killed by a master signal, as that would corrupt the
      + * database when we're in the middle of an update.
      + */
      + setsid();
      +}
      +
      +MAIL_VERSION_STAMP_DECLARE;
      +
      +/* main - pass control to the multi-threaded skeleton */
      +
      +int main(int argc, char **argv)
      +{
      + static CONFIG_STR_TABLE str_table[] = {
      + VAR_CACHE_MAP, DEF_CACHE_MAP, &var_cache_map, 0, 0,
      + 0,
      + };
      +
      + /*
      + * Fingerprint executables and core dumps.
      + */
      + MAIL_VERSION_STAMP_ALLOCATE;
      +
      + multi_server_main(argc, argv, cache_service,
      + MAIL_SERVER_STR_TABLE, str_table,
      + MAIL_SERVER_PRE_INIT, pre_jail_init,
      + MAIL_SERVER_POST_INIT, post_jail_init,
      + MAIL_SERVER_SOLITARY,
      + 0);
      +}
      diff -r -U5 -N postfix-2.4.5.orig/src/global/Makefile.in
      postfix-2.4.5/src/global/Makefile.in
      --- postfix-2.4.5.orig/src/global/Makefile.in 2007-11-20
      08:38:28.000000000 +0000
      +++ postfix-2.4.5/src/global/Makefile.in 2007-12-01
      10:31:34.000000000 +0000
      @@ -53,11 +53,11 @@
      recipient_list.o record.o remove.o resolve_clnt.o resolve_local.o \
      rewrite_clnt.o scache_clnt.o scache_multi.o scache_single.o \
      sent.o smtp_stream.o split_addr.o string_list.o strip_addr.o \
      sys_exits.o timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
      tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o \
      - user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
      + user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o cache_client.o\
      verp_sender.o wildcard_inet_addr.o xtext.o
      HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
      canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
      conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
      deliver_completed.h deliver_flock.h deliver_pass.h deliver_request.h \
      @@ -76,11 +76,11 @@
      qmgr_user.h qmqp_proto.h quote_821_local.h quote_822_local.h \
      quote_flags.h rcpt_buf.h rcpt_print.h rec_attr_map.h rec_streamlf.h \
      rec_type.h recipient_list.h record.h resolve_clnt.h resolve_local.h \
      rewrite_clnt.h scache.h sent.h smtp_stream.h split_addr.h \
      string_list.h strip_addr.h sys_exits.h timed_ipc.h tok822.h \
      - trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
      + trace.h user_acl.h valid_mailhost_addr.h verify.h
      verify_clnt.h cache_client.h\
      verp_sender.h wildcard_inet_addr.h xtext.h
      TESTSRC = rec2stream.c stream2rec.c recdump.c
      DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
      CFLAGS = $(DEBUG) $(OPT) $(DEFS)
      INCL =
      @@ -88,11 +88,11 @@
      TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
      mail_addr_map mail_date maps mynetworks mypwd namadr_list \
      off_cvt quote_822_local rec2stream recdump resolve_clnt \
      resolve_local rewrite_clnt stream2rec string_list tok822_parse \
      quote_821_local mail_conf_time mime_state strip_addr \
      - verify_clnt xtext anvil_clnt scache ehlo_mask \
      + verify_clnt cache_client xtext anvil_clnt scache ehlo_mask \
      valid_mailhost_addr own_inet_addr

      LIBS = ../../lib/libutil.a
      LIB_DIR = ../../lib
      INC_DIR = ../../include
      @@ -263,10 +263,15 @@
      verify_clnt: $(LIB) $(LIBS)
      mv $@.o junk
      $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
      mv junk $@.o

      +cache_client: $(LIB) $(LIBS)
      + mv $@.o junk
      + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
      + mv junk $@.o
      +
      xtext: $(LIB) $(LIBS)
      mv $@.o junk
      $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
      mv junk $@.o

      diff -r -U5 -N postfix-2.4.5.orig/src/global/cache_client.c
      postfix-2.4.5/src/global/cache_client.c
      --- postfix-2.4.5.orig/src/global/cache_client.c 1970-01-01
      01:00:00.000000000 +0100
      +++ postfix-2.4.5/src/global/cache_client.c 2007-12-01
      23:17:49.000000000 +0000
      @@ -0,0 +1,309 @@
      +/*++
      +/* NAME
      +/* cache_client 3
      +/* SUMMARY
      +/* generic cache client interface
      +/* SYNOPSIS
      +/* #include <cache_client.h>
      +/*
      +/* int cache_client_query(service, stream, key, value)
      +/* const char *service;
      +/* CLNT_STREAM **stream;
      +/* const char *key;
      +/* VSTRING *value;
      +/*
      +/* int cache_client_update(service, stream, key, value)
      +/* const char *service;
      +/* CLNT_STREAM **stream;
      +/* const char *key;
      +/* const char *value;
      +/*
      +/* int cache_client_delete(service,stream, key)
      +/* const char *service;
      +/* CLNT_STREAM **stream;
      +/* const char *key;
      +/*
      +/* DIAGNOSTICS
      +/* These functions return CACHE_STAT_OK in case of success,
      +/* CACHE_STAT_BAD in case of a malformed request, and
      +/* CACHE_STAT_FAIL when the operation failed, for a missing
      +/* key on lookup or delete.
      +/*--*/
      +
      +/* System library. */
      +
      +#include <sys_defs.h>
      +#include <unistd.h>
      +#include <errno.h>
      +
      +/* Utility library. */
      +
      +#include <msg.h>
      +#include <vstream.h>
      +#include <vstring.h>
      +#include <attr.h>
      +
      +/* Global library. */
      +
      +#include <mail_params.h>
      +#include <mail_proto.h>
      +#include <clnt_stream.h>
      +#include <cache_client.h>
      +
      +/* cache_client_init - initialize */
      +
      +static void cache_client_init(const char *cache_service, CLNT_STREAM
      **cache_client)
      +{
      + if (*cache_client != 0)
      + msg_panic("cache_client_init: multiple initialization");
      + *cache_client = clnt_stream_create(MAIL_CLASS_PRIVATE, cache_service,
      + var_ipc_idle_limit, var_ipc_ttl_limit);
      +}
      +
      +/* cache_client_query */
      +
      +int cache_client_query(const char *cache_service, CLNT_STREAM
      **cache_client, const char *key, VSTRING *value)
      +{
      + VSTREAM *stream;
      + int request_status;
      + int count = 0;
      +
      + /*
      + * Do client-server plumbing.
      + */
      + if (*cache_client == 0)
      + cache_client_init(cache_service,cache_client);
      +
      + for (;;) {
      + stream = clnt_stream_access(*cache_client);
      + errno = 0;
      + count += 1;
      + if (attr_print(stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_STR, MAIL_ATTR_REQ, CACHE_REQ_QUERY,
      + ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
      + ATTR_TYPE_END) != 0
      + || vstream_fflush(stream)
      + || attr_scan(stream, ATTR_FLAG_MISSING,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status,
      + ATTR_TYPE_STR, MAIL_ATTR_VALUE, value,
      + ATTR_TYPE_END) != 2) {
      + if (msg_verbose || count > 1 || (errno && errno != EPIPE
      && errno != ENOENT))
      + msg_warn("problem talking to service %s: %m",
      + cache_service);
      + } else {
      + break;
      + }
      + sleep(1);
      + clnt_stream_recover(*cache_client);
      + }
      + return (request_status);
      +}
      +
      +/* cache_client_delete */
      +
      +int cache_client_delete(const char* cache_service, CLNT_STREAM
      **cache_client, const char *key)
      +{
      + VSTREAM *stream;
      + int request_status;
      + int count = 0;
      +
      + /*
      + * Do client-server plumbing.
      + */
      + if (*cache_client == 0)
      + cache_client_init(cache_service,cache_client);
      +
      + for (;;) {
      + stream = clnt_stream_access(*cache_client);
      + errno = 0;
      + count += 1;
      + if (attr_print(stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_STR, MAIL_ATTR_REQ, CACHE_REQ_DELETE,
      + ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
      + ATTR_TYPE_END) != 0
      + || vstream_fflush(stream)
      + || attr_scan(stream, ATTR_FLAG_MISSING,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status,
      + ATTR_TYPE_END) != 1) {
      + if (msg_verbose || count > 1 || (errno && errno != EPIPE
      && errno != ENOENT))
      + msg_warn("problem talking to service %s: %m",
      + cache_service);
      + } else {
      + break;
      + }
      + sleep(1);
      + clnt_stream_recover(*cache_client);
      + }
      + return (request_status);
      +}
      +
      +/* verify_clnt_update - request address status update */
      +
      +int cache_client_update(const char *cache_service, CLNT_STREAM
      **cache_client, const char *key, const char *value)
      +{
      + VSTREAM *stream;
      + int request_status;
      +
      + /*
      + * Do client-server plumbing.
      + */
      + if (*cache_client == 0)
      + cache_client_init(cache_service,cache_client);
      +
      + for (;;) {
      + stream = clnt_stream_access(*cache_client);
      + errno = 0;
      + if (attr_print(stream, ATTR_FLAG_NONE,
      + ATTR_TYPE_STR, MAIL_ATTR_REQ, CACHE_REQ_UPDATE,
      + ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
      + ATTR_TYPE_STR, MAIL_ATTR_VALUE, value,
      + ATTR_TYPE_END) != 0
      + || attr_scan(stream, ATTR_FLAG_MISSING,
      + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status,
      + ATTR_TYPE_END) != 1) {
      + if (msg_verbose || (errno != EPIPE && errno != ENOENT))
      + msg_warn("problem talking to service %s: %m",
      + cache_service);
      + } else {
      + break;
      + }
      + sleep(1);
      + clnt_stream_recover(*cache_client);
      + }
      + return (request_status);
      +}
      +
      + /*
      + * Proof-of-concept test client program.
      + */
      +#ifdef TEST
      +
      +#include <stdlib.h>
      +#include <ctype.h>
      +#include <stdlib.h>
      +#include <unistd.h>
      +#include <signal.h>
      +#include <msg_vstream.h>
      +#include <stringops.h>
      +#include <vstring_vstream.h>
      +#include <mail_conf.h>
      +
      +#define STR(x) vstring_str(x)
      +
      +CLNT_STREAM *auth_cache_client;
      +
      +static NORETURN usage(char *myname)
      +{
      + msg_fatal("usage: %s [-v]", myname);
      +}
      +
      +static void query(char *query, VSTRING *buf)
      +{
      + switch (cache_client_query(MAIL_SERVICE_AUTH_CACHE,
      &auth_cache_client, query, buf)) {
      + case CACHE_STAT_OK:
      + vstream_printf("value %s\n", STR(buf));
      + vstream_fflush(VSTREAM_OUT);
      + break;
      + case CACHE_STAT_BAD:
      + msg_warn("bad request format");
      + break;
      + case CACHE_STAT_FAIL:
      + vstream_printf("FAIL\n");
      + vstream_fflush(VSTREAM_OUT);
      + break;
      + }
      +}
      +
      +static void delete(char *query)
      +{
      + switch (cache_client_delete(MAIL_SERVICE_AUTH_CACHE,
      &auth_cache_client, query)) {
      + case CACHE_STAT_OK:
      + vstream_printf("OK\n");
      + vstream_fflush(VSTREAM_OUT);
      + break;
      + case CACHE_STAT_BAD:
      + msg_warn("bad request format");
      + break;
      + case CACHE_STAT_FAIL:
      + vstream_printf("FAIL\n");
      + vstream_fflush(VSTREAM_OUT);
      + break;
      + }
      +}
      +
      +static void update(char *query)
      +{
      + char *key;
      + char *value;
      + char *cp = query;
      +
      + if ((query = mystrtok(&cp, " \t\r\n")) == 0) {
      + msg_warn("bad request format");
      + return;
      + }
      + while (*cp && ISSPACE(*cp))
      + cp++;
      + if (*cp == 0) {
      + msg_warn("bad request format");
      + return;
      + }
      + switch (cache_client_update(MAIL_SERVICE_AUTH_CACHE,
      &auth_cache_client, query, cp)) {
      + case CACHE_STAT_OK:
      + vstream_printf("OK\n");
      + vstream_fflush(VSTREAM_OUT);
      + break;
      + case CACHE_STAT_BAD:
      + msg_warn("bad request format");
      + break;
      + case CACHE_STAT_FAIL:
      + msg_warn("request failed");
      + break;
      + }
      +}
      +
      +int main(int argc, char **argv)
      +{
      + VSTRING *buffer = vstring_alloc(1);
      + char *cp;
      + int ch;
      + char *command;
      +
      + signal(SIGPIPE, SIG_IGN);
      +
      + msg_vstream_init(argv[0], VSTREAM_ERR);
      +
      + mail_conf_read();
      + msg_info("using config files in %s", var_config_dir);
      + if (chdir(var_queue_dir) < 0)
      + msg_fatal("chdir %s: %m", var_queue_dir);
      +
      + while ((ch = GETOPT(argc, argv, "v")) > 0) {
      + switch (ch) {
      + case 'v':
      + msg_verbose++;
      + break;
      + default:
      + usage(argv[0]);
      + }
      + }
      + if (argc - optind > 1)
      + usage(argv[0]);
      +
      + while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
      + cp = STR(buffer);
      + if ((command = mystrtok(&cp, " \t\r\n")) == 0)
      + continue;
      + if (strcmp(command, "query") == 0)
      + query(cp, buffer);
      + else if (strcmp(command, "delete") == 0)
      + delete(cp);
      + else if (strcmp(command, "update") == 0)
      + update(cp);
      + else
      + msg_warn("unrecognized command: %s", command);
      + }
      + vstring_free(buffer);
      + return (0);
      +}
      +
      +#endif
      diff -r -U5 -N postfix-2.4.5.orig/src/global/cache_client.h
      postfix-2.4.5/src/global/cache_client.h
      --- postfix-2.4.5.orig/src/global/cache_client.h 1970-01-01
      01:00:00.000000000 +0100
      +++ postfix-2.4.5/src/global/cache_client.h 2007-12-01
      22:38:31.000000000 +0000
      @@ -0,0 +1,46 @@
      +#ifndef _CACHE_CLIENT_H_INCLUDED_
      +#define _CACHE_CLIENT_H_INCLUDED_
      +
      +/*++
      +/* NAME
      +/* cache_client 3h
      +/* SUMMARY
      +/* genric cache client interface
      +/* SYNOPSIS
      +/* #include <cache_client.h>
      +/* DESCRIPTION
      +/* .nf
      +
      + /*
      + * System library.
      + */
      +#include <stdarg.h>
      +
      + /*
      + * Global library.
      + */
      +#include <deliver_request.h>
      +#include <clnt_stream.h>
      +
      + /*
      + * Address verification requests.
      + */
      +#define CACHE_REQ_QUERY "query"
      +#define CACHE_REQ_UPDATE "update"
      +#define CACHE_REQ_DELETE "delete"
      +
      + /*
      + * Request (NOT: address) status codes.
      + */
      +#define CACHE_STAT_OK 0
      +#define CACHE_STAT_FAIL 1
      +#define CACHE_STAT_BAD (-1)
      +
      + /*
      + * Functional interface.
      + */
      +extern int cache_client_query(const char*, CLNT_STREAM **, const char
      *, VSTRING *);
      +extern int cache_client_update(const char*, CLNT_STREAM **, const
      char *, const char *);
      +extern int cache_client_delete(const char*, CLNT_STREAM **, const char *);
      +
      +#endif
      diff -r -U5 -N postfix-2.4.5.orig/src/global/mail_params.h
      postfix-2.4.5/src/global/mail_params.h
      --- postfix-2.4.5.orig/src/global/mail_params.h 2007-11-29
      08:01:46.000000000 +0000
      +++ postfix-2.4.5/src/global/mail_params.h 2007-12-01
      22:15:36.000000000 +0000
      @@ -1429,10 +1429,22 @@

      #define VAR_SMTP_SASL_AUTH_SOFT_BOUNCE "smtp_sasl_auth_soft_bounce"
      #define DEF_SMTP_SASL_AUTH_SOFT_BOUNCE 0
      extern bool var_smtp_sasl_auth_soft_bounce;

      +#define VAR_SMTP_SASL_AUTH_CACHE_ENABLE "smtp_sasl_auth_cache_enable"
      +#define DEF_SMTP_SASL_AUTH_CACHE_ENABLE 0
      +extern bool var_smtp_sasl_auth_cache_enable;
      +
      +#define VAR_SMTP_SASL_AUTH_CACHE_SERVICE
      "smtp_sasl_auth_cache_service"
      +#define DEF_SMTP_SASL_AUTH_CACHE_SERVICE "auth_cache"
      +extern char *var_smtp_sasl_auth_cache_service;
      +
      +#define VAR_SMTP_SASL_AUTH_CACHE_TIME "smtp_sasl_auth_cache_time"
      +#define DEF_SMTP_SASL_AUTH_CACHE_TIME "90d"
      +extern int var_smtp_sasl_auth_cache_time;
      +
      #define VAR_SMTP_SASL_PASSWD "smtp_sasl_password_maps"
      #define DEF_SMTP_SASL_PASSWD ""
      extern char *var_smtp_sasl_passwd;

      #define VAR_SMTP_SASL_OPTS "smtp_sasl_security_options"
      @@ -1528,10 +1540,22 @@

      #define VAR_LMTP_SASL_AUTH_SOFT_BOUNCE "lmtp_sasl_auth_soft_bounce"
      #define DEF_LMTP_SASL_AUTH_SOFT_BOUNCE 0
      extern bool var_lmtp_sasl_auth_soft_bounce;

      +#define VAR_LMTP_SASL_AUTH_CACHE_ENABLE
      "lmtp_sasl_auth_fail_cache_enable"
      +#define DEF_LMTP_SASL_AUTH_CACHE_ENABLE 0
      +extern bool var_lmtp_sasl_auth_fail_enable;
      +
      +#define VAR_LMTP_SASL_AUTH_CACHE_SERVICE
      "lmtp_sasl_auth_cache_service"
      +#define DEF_LMTP_SASL_AUTH_CACHE_SERVICE "auth_cache"
      +extern char *var_lmtp_sasl_auth_cache_service;
      +
      +#define VAR_LMTP_SASL_AUTH_CACHE_TIME "lmtp_sasl_auth_cache_time"
      +#define DEF_LMTP_SASL_AUTH_CACHE_TIME "90d"
      +extern int var_lmtp_sasl_auth_cache_time;
      +
      #define VAR_LMTP_SASL_PASSWD "lmtp_sasl_password_maps"
      #define DEF_LMTP_SASL_PASSWD ""
      extern char *var_lmtp_sasl_passwd;

      #define VAR_LMTP_SASL_OPTS "lmtp_sasl_security_options"
      @@ -2420,10 +2444,17 @@
      #define VAR_VRFY_XPORT_MAPS "address_verify_transport_maps"
      #define DEF_VRFY_XPORT_MAPS "$" VAR_TRANSPORT_MAPS
      extern char *var_vrfy_xport_maps;

      /*
      + * generic cache service.
      + */
      +#define VAR_CACHE_MAP "cache_map"
      +#define DEF_CACHE_MAP ""
      +extern char *var_cache_map;
      +
      + /*
      * Message delivery trace service.
      */
      #define VAR_TRACE_SERVICE "trace_service_name"
      #define DEF_TRACE_SERVICE MAIL_SERVICE_TRACE
      extern char *var_trace_service;
      diff -r -U5 -N postfix-2.4.5.orig/src/global/mail_proto.h
      postfix-2.4.5/src/global/mail_proto.h
      --- postfix-2.4.5.orig/src/global/mail_proto.h 2006-11-01
      20:03:12.000000000 +0000
      +++ postfix-2.4.5/src/global/mail_proto.h 2007-12-01
      21:52:11.000000000 +0000
      @@ -51,10 +51,11 @@
      #define MAIL_SERVICE_SHOWQ "showq"
      #define MAIL_SERVICE_ERROR "error"
      #define MAIL_SERVICE_RETRY "retry"
      #define MAIL_SERVICE_FLUSH "flush"
      #define MAIL_SERVICE_VERIFY "verify"
      +#define MAIL_SERVICE_AUTH_CACHE "auth_cache"
      #define MAIL_SERVICE_TRACE "trace"
      #define MAIL_SERVICE_RELAY "relay"
      #define MAIL_SERVICE_PROXYMAP "proxymap"
      #define MAIL_SERVICE_SCACHE "scache"

      diff -r -U5 -N postfix-2.4.5.orig/src/smtp/lmtp_params.c
      postfix-2.4.5/src/smtp/lmtp_params.c
      --- postfix-2.4.5.orig/src/smtp/lmtp_params.c 2007-11-29
      08:17:20.000000000 +0000
      +++ postfix-2.4.5/src/smtp/lmtp_params.c 2007-12-01
      22:08:32.000000000 +0000
      @@ -44,10 +44,11 @@
      VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
      VAR_LMTP_GENERIC_MAPS, DEF_LMTP_GENERIC_MAPS,
      &var_smtp_generic_maps, 0, 0,
      VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_lmtp_tcp_port, 0, 0,
      VAR_LMTP_PIX_BUG_WORDS, DEF_LMTP_PIX_BUG_WORDS,
      &var_smtp_pix_bug_words, 0, 0,
      VAR_LMTP_PIX_BUG_MAPS, DEF_LMTP_PIX_BUG_MAPS,
      &var_smtp_pix_bug_maps, 0, 0,
      + VAR_LMTP_SASL_AUTH_CACHE_SERVICE,
      DEF_LMTP_SASL_AUTH_CACHE_SERVICE, &var_smtp_sasl_auth_cache_service,
      1, 0,
      0,
      };
      static CONFIG_TIME_TABLE lmtp_time_table[] = {
      VAR_LMTP_CONN_TMOUT, DEF_LMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
      VAR_LMTP_HELO_TMOUT, DEF_LMTP_HELO_TMOUT, &var_smtp_helo_tmout, 1, 0,
      @@ -65,10 +66,11 @@
      VAR_LMTP_REUSE_TIME, DEF_LMTP_REUSE_TIME, &var_smtp_reuse_time, 1, 0,
      #ifdef USE_TLS
      VAR_LMTP_STARTTLS_TMOUT, DEF_LMTP_STARTTLS_TMOUT,
      &var_smtp_starttls_tmout, 1, 0,
      #endif
      VAR_SCACHE_PROTO_TMOUT, DEF_SCACHE_PROTO_TMOUT,
      &var_scache_proto_tmout, 1, 0,
      + VAR_LMTP_SASL_AUTH_CACHE_TIME, DEF_LMTP_SASL_AUTH_CACHE_TIME,
      &var_smtp_sasl_auth_cache_time, 0, 0,
      0,
      };
      static CONFIG_INT_TABLE lmtp_int_table[] = {
      VAR_LMTP_LINE_LIMIT, DEF_LMTP_LINE_LIMIT, &var_smtp_line_limit, 0, 0,
      VAR_LMTP_MXADDR_LIMIT, DEF_LMTP_MXADDR_LIMIT,
      &var_smtp_mxaddr_limit, 0, 0,
      @@ -83,10 +85,11 @@
      static CONFIG_BOOL_TABLE lmtp_bool_table[] = {
      VAR_LMTP_SKIP_5XX, DEF_LMTP_SKIP_5XX, &var_smtp_skip_5xx_greeting,
      VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
      VAR_LMTP_SASL_ENABLE, DEF_LMTP_SASL_ENABLE, &var_smtp_sasl_enable,
      VAR_LMTP_SASL_AUTH_SOFT_BOUNCE,
      DEF_LMTP_SASL_AUTH_SOFT_BOUNCE, &var_smtp_sasl_auth_soft_bounce,
      + VAR_LMTP_SASL_AUTH_CACHE_ENABLE,
      DEF_LMTP_SASL_AUTH_CACHE_ENABLE, &var_smtp_sasl_auth_cache_enable,
      VAR_LMTP_RAND_ADDR, DEF_LMTP_RAND_ADDR, &var_smtp_rand_addr,
      VAR_LMTP_QUOTE_821_ENV, DEF_LMTP_QUOTE_821_ENV, &var_smtp_quote_821_env,
      VAR_LMTP_DEFER_MXADDR, DEF_LMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
      VAR_LMTP_SEND_XFORWARD, DEF_LMTP_SEND_XFORWARD, &var_smtp_send_xforward,
      VAR_LMTP_CACHE_DEMAND, DEF_LMTP_CACHE_DEMAND, &var_smtp_cache_demand,
      diff -r -U5 -N postfix-2.4.5.orig/src/smtp/smtp.c postfix-2.4.5/src/smtp/smtp.c
      --- postfix-2.4.5.orig/src/smtp/smtp.c 2007-11-29 08:03:17.000000000 +0000
      +++ postfix-2.4.5/src/smtp/smtp.c 2007-12-01 22:00:42.000000000 +0000
      @@ -653,10 +653,13 @@
      char *var_smtp_sasl_opts;
      char *var_smtp_sasl_path;
      char *var_smtp_sasl_passwd;
      bool var_smtp_sasl_enable;
      bool var_smtp_sasl_auth_soft_bounce;
      +bool var_smtp_sasl_auth_cache_enable;
      +char *var_smtp_sasl_auth_cache_service;
      +int var_smtp_sasl_auth_cache_time;
      char *var_smtp_sasl_mechs;
      char *var_smtp_sasl_type;
      char *var_smtp_bind_addr;
      char *var_smtp_bind_addr6;
      bool var_smtp_rand_addr;
      diff -r -U5 -N postfix-2.4.5.orig/src/smtp/smtp_params.c
      postfix-2.4.5/src/smtp/smtp_params.c
      --- postfix-2.4.5.orig/src/smtp/smtp_params.c 2007-11-29
      08:16:48.000000000 +0000
      +++ postfix-2.4.5/src/smtp/smtp_params.c 2007-12-01
      21:58:29.000000000 +0000
      @@ -45,10 +45,11 @@
      VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
      VAR_SMTP_GENERIC_MAPS, DEF_SMTP_GENERIC_MAPS,
      &var_smtp_generic_maps, 0, 0,
      VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_lmtp_tcp_port, 0, 0,
      VAR_SMTP_PIX_BUG_WORDS, DEF_SMTP_PIX_BUG_WORDS,
      &var_smtp_pix_bug_words, 0, 0,
      VAR_SMTP_PIX_BUG_MAPS, DEF_SMTP_PIX_BUG_MAPS,
      &var_smtp_pix_bug_maps, 0, 0,
      + VAR_SMTP_SASL_AUTH_CACHE_SERVICE,
      DEF_SMTP_SASL_AUTH_CACHE_SERVICE, &var_smtp_sasl_auth_cache_service,
      1, 0,
      0,
      };
      static CONFIG_TIME_TABLE smtp_time_table[] = {
      VAR_SMTP_CONN_TMOUT, DEF_SMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
      VAR_SMTP_HELO_TMOUT, DEF_SMTP_HELO_TMOUT, &var_smtp_helo_tmout, 1, 0,
      @@ -66,10 +67,11 @@
      VAR_SMTP_REUSE_TIME, DEF_SMTP_REUSE_TIME, &var_smtp_reuse_time, 1, 0,
      #ifdef USE_TLS
      VAR_SMTP_STARTTLS_TMOUT, DEF_SMTP_STARTTLS_TMOUT,
      &var_smtp_starttls_tmout, 1, 0,
      #endif
      VAR_SCACHE_PROTO_TMOUT, DEF_SCACHE_PROTO_TMOUT,
      &var_scache_proto_tmout, 1, 0,
      + VAR_SMTP_SASL_AUTH_CACHE_TIME, DEF_SMTP_SASL_AUTH_CACHE_TIME,
      &var_smtp_sasl_auth_cache_time, 0, 0,
      0,
      };
      static CONFIG_INT_TABLE smtp_int_table[] = {
      VAR_SMTP_LINE_LIMIT, DEF_SMTP_LINE_LIMIT, &var_smtp_line_limit, 0, 0,
      VAR_SMTP_MXADDR_LIMIT, DEF_SMTP_MXADDR_LIMIT,
      &var_smtp_mxaddr_limit, 0, 0,
      @@ -87,10 +89,11 @@
      VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
      VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
      VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
      VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
      VAR_SMTP_SASL_AUTH_SOFT_BOUNCE,
      DEF_SMTP_SASL_AUTH_SOFT_BOUNCE, &var_smtp_sasl_auth_soft_bounce,
      + VAR_SMTP_SASL_AUTH_CACHE_ENABLE,
      DEF_SMTP_SASL_AUTH_CACHE_ENABLE, &var_smtp_sasl_auth_cache_enable,
      VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
      VAR_SMTP_QUOTE_821_ENV, DEF_SMTP_QUOTE_821_ENV, &var_smtp_quote_821_env,
      VAR_SMTP_DEFER_MXADDR, DEF_SMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
      VAR_SMTP_SEND_XFORWARD, DEF_SMTP_SEND_XFORWARD, &var_smtp_send_xforward,
      VAR_SMTP_CACHE_DEMAND, DEF_SMTP_CACHE_DEMAND, &var_smtp_cache_demand,
      diff -r -U5 -N postfix-2.4.5.orig/src/smtp/smtp_sasl_glue.c
      postfix-2.4.5/src/smtp/smtp_sasl_glue.c
      --- postfix-2.4.5.orig/src/smtp/smtp_sasl_glue.c 2007-12-01
      12:03:04.000000000 +0000
      +++ postfix-2.4.5/src/smtp/smtp_sasl_glue.c 2007-12-01
      23:33:31.000000000 +0000
      @@ -122,10 +122,14 @@
      /*
      * Application-specific
      */
      #include "smtp.h"
      #include "smtp_sasl.h"
      +#include "cache_client.h"
      +#include "base64_code.h"
      +#include "dsn_util.h"
      +#include <openssl/sha.h>

      #ifdef USE_SASL_AUTH

      /*
      * Per-host login/password information.
      @@ -140,10 +144,15 @@
      /*
      * SASL implementation handle.
      */
      static XSASL_CLIENT_IMPL *smtp_sasl_impl;

      + /*
      + * SASL auth cache handle.
      + */
      +CLNT_STREAM *auth_cache_client;
      +
      /* smtp_sasl_passwd_lookup - password lookup routine */

      int smtp_sasl_passwd_lookup(SMTP_SESSION *session)
      {
      const char *myname = "smtp_sasl_passwd_lookup";
      @@ -257,10 +266,101 @@
      session->host, sasl_opts_val)) == 0)
      msg_fatal("SASL per-connection initialization failed");
      session->sasl_reply = vstring_alloc(20);
      }

      +static void smtp_sasl_make_cache_key(VSTRING *buf,const char *host,
      + const char *user,const char *pass)
      +{
      + VSTRING *tmp = vstring_alloc(10);
      +
      + vstring_sprintf(tmp,"%s;%s;%s",host,user,pass);
      + base64_encode(buf,(const char*)SHA1((unsigned char*)STR(tmp),
      + (unsigned long)VSTRING_LEN(tmp),0),SHA_DIGEST_LENGTH);
      + vstring_free(tmp);
      +}
      +
      +static void smtp_sasl_make_cache_value(VSTRING *buf,unsigned long timestamp,
      + const char *respdsn, const char *respstr)
      +{
      + vstring_sprintf(buf, "%lu:%s:%s", timestamp, respdsn, respstr);
      +}
      +
      +static int smtp_sasl_parse_cache_value(char *buf, unsigned long *timestamp,
      + char **respdsn, char **respstr)
      +{
      + char *end;
      +
      + if ((*respdsn = split_at(buf,':')) != 0
      + && (*respstr = split_at(*respdsn,':')) != 0
      + && dsn_valid(*respdsn)) {
      + *timestamp = strtoul(buf,&end,10);
      + if (*end == 0 && *buf != 0) { /* entire string valid number */
      + return (0);
      + }
      + }
      + msg_warn("bad smtp_sasl_auth_cache_map entry: %.100s", buf);
      + return (-1);
      +}
      +
      +/*
      + * Check auth failure cache, and fail if this (relayhost,user,pass)
      + * triple matches an entry that is new enough.
      + */
      +static int smtp_sasl_cache_query(SMTP_SESSION *session, DSN_BUF *why)
      +{
      + VSTRING *buf = vstring_alloc(10);
      + VSTRING *get_buf = vstring_alloc(10);
      + VSTRING *put_buf = vstring_alloc(10);
      + char *cached_respdsn = 0;
      + char *cached_respstr = 0;
      + unsigned long now = (unsigned long) time((time_t *) 0);
      + unsigned long timestamp = 0;
      + int status = 0;
      +
      + smtp_sasl_make_cache_key(buf, session->host,
      session->sasl_username, session->sasl_passwd);
      + if (cache_client_query(var_smtp_sasl_auth_cache_service,
      &auth_cache_client, STR(buf), get_buf) == 0) {
      + if (vstring_strcpy(put_buf,STR(get_buf))
      + && smtp_sasl_parse_cache_value(STR(get_buf),×tamp,
      + &cached_respdsn,&cached_respstr) == 0
      + && timestamp + var_smtp_sasl_auth_cache_time > now) {
      + if (var_smtp_sasl_auth_soft_bounce && cached_respdsn[0] == '5') {
      + cached_respdsn[0] = '4';
      + }
      + dsb_update(why, cached_respdsn, DSB_DEF_ACTION, DSB_MTYPE_DNS,
      + session->host, var_procname, cached_respstr,
      + "SASL [CACHED] authentication failed; server %s : %s",
      + session->namaddr, STR(put_buf));
      + status = -1;
      + } else {
      + /* timeout or corrupt cache entry */
      + cache_client_delete(var_smtp_sasl_auth_cache_service,
      &auth_cache_client, STR(buf));
      + }
      + }
      + vstring_free(put_buf);
      + vstring_free(get_buf);
      + vstring_free(buf);
      + return (status);
      +}
      +
      +/*
      + * Add (relayhost,user,pass) triple to auth failure cache
      + */
      +static void smtp_sasl_cache_update(SMTP_SESSION *session, SMTP_RESP *resp)
      +{
      + VSTRING *buf = vstring_alloc(10);
      + VSTRING *put_buf = vstring_alloc(10);
      + unsigned long now = (unsigned long) time((time_t *) 0);
      +
      + smtp_sasl_make_cache_key(buf, session->host,
      session->sasl_username, session->sasl_passwd);
      + smtp_sasl_make_cache_value(put_buf, now, resp->dsn, resp->str);
      + cache_client_update(var_smtp_sasl_auth_cache_service,
      &auth_cache_client, STR(buf), STR(put_buf));
      +
      + vstring_free(put_buf);
      + vstring_free(buf);
      +}
      +
      /* smtp_sasl_authenticate - run authentication protocol */

      int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
      {
      const char *myname = "smtp_sasl_authenticate";
      @@ -277,10 +377,14 @@

      if (msg_verbose)
      msg_info("%s: %s: SASL mechanisms %s",
      myname, session->namaddr, session->sasl_mechanism_list);

      + if (var_smtp_sasl_auth_cache_enable) {
      + if (smtp_sasl_cache_query(session,why)) { return (0); }
      + }
      +
      /*
      * Start the client side authentication protocol.
      */
      result = xsasl_client_first(session->sasl_client,
      session->sasl_mechanism_list,
      @@ -338,20 +442,25 @@

      /*
      * We completed the authentication protocol.
      */
      if (resp->code / 100 != 2) {
      - /* begin: KPS20071119 - soft bounce patch */
      +
      + if (var_smtp_sasl_auth_cache_enable && resp->code == 535) {
      + smtp_sasl_cache_update(session, resp);
      + }
      +
      if (var_smtp_sasl_auth_soft_bounce && resp->code / 100 == 5) {
      STR(resp->dsn_buf)[0] = '4';
      }
      - /* end: KPS20071119 - soft bounce patch */
      +
      dsb_update(why, resp->dsn, DSB_DEF_ACTION,
      DSB_MTYPE_DNS, session->host,
      var_procname, resp->str,
      "SASL authentication failed; server %s said: %s",
      session->namaddr, resp->str);
      +
      return (0);
      }
      return (1);
      }

      diff -r -U5 -N postfix-2.4.5.orig/src/util/dict_open.c
      postfix-2.4.5/src/util/dict_open.c
      --- postfix-2.4.5.orig/src/util/dict_open.c 2007-11-20
      08:38:28.000000000 +0000
      +++ postfix-2.4.5/src/util/dict_open.c 2007-12-01 16:32:05.000000000 +0000
      @@ -142,11 +142,11 @@
      /*
      /* dict_put() stores the specified key and value into the named
      /* dictionary.
      /*
      /* dict_del() removes a dictionary entry, and returns non-zero
      -/* in case of success.
      +/* if the specified key does not exist in the named dictionary.
      /*
      /* dict_seq() iterates over all members in the named dictionary.
      /* func is define DICT_SEQ_FUN_FIRST (select first member) or
      /* DICT_SEQ_FUN_NEXT (select next member). A null result means
      /* there is more.
    • Victor Duchovni
      ... Yes, that s the idea. Also CPUs have historically gotten faster year-by-year. Moore s law is looking a bit more feeble lately, we are getting the
      Message 77 of 77 , Dec 4, 2007
      • 0 Attachment
        On Tue, Dec 04, 2007 at 09:04:19PM +0000, Keean Schupke wrote:

        > How about we make the key iterations a config variable, and let the
        > user make the balance between speed and security?

        Yes, that's the idea. Also CPUs have historically gotten faster
        year-by-year. Moore's law is looking a bit more feeble lately, we are
        getting the feature-size scaling (more cores per die) but the clock-rate
        seems to have stalled for a bit.

        Finally, the table will not be in the chroot jail, proxymap/proxywrite
        won't be chrooted even when other processes are. So some "postfix"
        processes will have less access to the table than others.

        Anyway this is all coverging to something sensible. The question for
        the smtp(8) side is whether making the password hash the key is the
        best choice. We could make "nexthop user" the key, and stick the
        password hash in the result. That way deletion will actually work.

        Otherwise, new passwords will be set before the fail map entry expires,
        and the table entry becomes orphaned.

        If this change is made, the entry is valid only if not expired, and the
        password hash matches. Looks a lot an /etc/shadow entry with a user name
        and PKCS#5 v2 password hash, only it perversely records invalid passwords!

        --
        Viktor.

        Disclaimer: off-list followups get on-list replies or get ignored.
        Please do not ignore the "Reply-To" header.

        To unsubscribe from the postfix-users list, visit
        http://www.postfix.org/lists.html or click the link below:
        <mailto:majordomo@...?body=unsubscribe%20postfix-users>

        If my response solves your problem, the best way to thank me is to not
        send an "it worked, thanks" follow-up. If you must respond, please put
        "It worked, thanks" in the "Subject" so I can delete these quickly.
      Your message has been successfully submitted and would be delivered to recipients shortly.