| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Here's the patch for SASL auth failure caching I talked about, it is independent of the soft_bounce feature, so you have caching with or without the soft bounce. There is no point in caching auth success, as you still actually have to go through the SASL protocol, however caching failures I think is generally useful, as it saves both time in processing the mail, and network bandwidth, in the case where you know a particular host/name/password combination is bad (especially if you have soft_bounce set, when every time postfix tries to resend the queued mails it causes another auth request). There are three configuration variables, "smtp_sasl_auth_cache_enable" (obvious), "smtp_sasl_auth_cache_name" (the db file for caching, if blank or not defined, a ram only cache is used), and "smtp_sasl_auth_cache_time" (how long failures remain in the cache, defaults to 90 days). Because caching is based on the host/username/password, updating the SASL password file with a different password will result in a new authentication attempt. Comments etc, appreciated... Is this neat enough to make it into the distributed version? See appended patch. Regards, Keean Schupke, Fry-IT Ltd. diff -r -U5 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-11-29 08:10:41.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_NAME "smtp_sasl_auth_cache_name" +#define DEF_SMTP_SASL_AUTH_CACHE_NAME "" +extern char *var_smtp_sasl_auth_cache_name; + +#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_NAME "lmtp_sasl_auth_fail_cache_name" +#define DEF_LMTP_SASL_AUTH_CACHE_NAME "" +extern char *var_lmtp_sasl_auth_cache_name; + +#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" diff -r -U5 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-11-29 08:29:41.000000000 +0000 @@ -28,10 +28,11 @@ VAR_LMTP_TLS_VFY_CMATCH, DEF_LMTP_TLS_VFY_CMATCH, &var_smtp_tls_vfy_cmatch, 1, 0, VAR_LMTP_TLS_SEC_CMATCH, DEF_LMTP_TLS_SEC_CMATCH, &var_smtp_tls_sec_cmatch, 1, 0, #endif VAR_LMTP_SASL_MECHS, DEF_LMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0, VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, + VAR_LMTP_SASL_AUTH_CACHE_NAME, DEF_LMTP_SASL_AUTH_CACHE_NAME, &var_smtp_sasl_auth_cache_name, 0, 0, VAR_LMTP_BIND_ADDR, DEF_LMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0, VAR_LMTP_BIND_ADDR6, DEF_LMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0, VAR_LMTP_HELO_NAME, DEF_LMTP_HELO_NAME, &var_smtp_helo_name, 1, 0, VAR_LMTP_HOST_LOOKUP, DEF_LMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0, VAR_LMTP_CACHE_DEST, DEF_LMTP_CACHE_DEST, &var_smtp_cache_dest, 0, 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 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-11-30 08:56:27.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_name; +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; @@ -844,10 +847,14 @@ smtp_scache = scache_clnt_create(var_scache_service, var_scache_proto_tmout, var_ipc_idle_limit, var_ipc_ttl_limit); #endif + + if (var_smtp_sasl_enable) { + smtp_sasl_post_init(); + } } /* pre_init - pre-jail initialization */ static void pre_init(char *unused_name, char **unused_argv) @@ -862,11 +869,11 @@ /* * SASL initialization. */ if (var_smtp_sasl_enable) #ifdef USE_SASL_AUTH - smtp_sasl_initialize(); + smtp_sasl_pre_init(); #else msg_warn("%s is true, but SASL support is not compiled in", VAR_SMTP_SASL_ENABLE); #endif diff -r -U5 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-11-29 08:28:41.000000000 +0000 @@ -29,10 +29,11 @@ VAR_SMTP_TLS_VFY_CMATCH, DEF_SMTP_TLS_VFY_CMATCH, &var_smtp_tls_vfy_cmatch, 1, 0, VAR_SMTP_TLS_SEC_CMATCH, DEF_SMTP_TLS_SEC_CMATCH, &var_smtp_tls_sec_cmatch, 1, 0, #endif VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0, VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, + VAR_SMTP_SASL_AUTH_CACHE_NAME, DEF_SMTP_SASL_AUTH_CACHE_NAME, &var_smtp_sasl_auth_cache_name, 0, 0, VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0, VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0, VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0, VAR_SMTP_HOST_LOOKUP, DEF_SMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0, VAR_SMTP_CACHE_DEST, DEF_SMTP_CACHE_DEST, &var_smtp_cache_dest, 0, 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 postfix-2.4.5.orig/src/smtp/smtp_sasl.h postfix-2.4.5/src/smtp/smtp_sasl.h --- postfix-2.4.5.orig/src/smtp/smtp_sasl.h 2005-06-13 23:18:55.000000000 +0100 +++ postfix-2.4.5/src/smtp/smtp_sasl.h 2007-11-30 09:07:28.000000000 +0000 @@ -9,11 +9,12 @@ /* .nf /* * SASL protocol functions */ -extern void smtp_sasl_initialize(void); +extern void smtp_sasl_pre_init(void); +extern void smtp_sasl_post_init(void); extern void smtp_sasl_connect(SMTP_SESSION *); extern int smtp_sasl_passwd_lookup(SMTP_SESSION *); extern void smtp_sasl_start(SMTP_SESSION *, const char *, const char *); extern int smtp_sasl_authenticate(SMTP_SESSION *, DSN_BUF *); extern void smtp_sasl_cleanup(SMTP_SESSION *); diff -r -U5 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-11-29 08:08:53.000000000 +0000 +++ postfix-2.4.5/src/smtp/smtp_sasl_glue.c 2007-11-30 11:38:19.000000000 +0000 @@ -122,10 +122,17 @@ /* * Application-specific */ #include "smtp.h" #include "smtp_sasl.h" +#include "mymalloc.h" +#include "htable.h" +#include "dict.h" +#include "dict_ht.h" +#include <sys/types.h> +#include <sys/stat.h> + #ifdef USE_SASL_AUTH /* * Per-host login/password information. @@ -140,10 +147,15 @@ /* * SASL implementation handle. */ static XSASL_CLIENT_IMPL *smtp_sasl_impl; + /* + * Map for caching. + */ +static DICT *smtp_sasl_auth_cache_map; + /* smtp_sasl_passwd_lookup - password lookup routine */ int smtp_sasl_passwd_lookup(SMTP_SESSION *session) { const char *myname = "smtp_sasl_passwd_lookup"; @@ -196,12 +208,13 @@ } } /* smtp_sasl_initialize - per-process initialization (pre jail) */ -void smtp_sasl_initialize(void) +void smtp_sasl_pre_init(void) { + mode_t saved_mask; /* * Sanity check. */ if (smtp_sasl_passwd_map || smtp_sasl_impl) @@ -225,12 +238,38 @@ * Initialize optional supported mechanism matchlist */ if (*var_smtp_sasl_mechs) smtp_sasl_mechs = string_list_init(MATCH_FLAG_NONE, var_smtp_sasl_mechs); + + /* + * Initialize optional authorization failure caching + */ + +#define SMTP_SASL_AUTH_CACHE_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | DICT_FLAG_LOCK) + + if (var_smtp_sasl_auth_cache_enable) { + if (*var_smtp_sasl_auth_cache_name) { + saved_mask = umask(022); + smtp_sasl_auth_cache_map = dict_open(var_smtp_sasl_auth_cache_name, + O_RDWR | O_CREAT, SMTP_SASL_AUTH_CACHE_OPEN_FLAGS); + (void)umask(saved_mask); + } else { + smtp_sasl_auth_cache_map = dict_ht_open("sasl_smtp_sasl_auth_cache", + htable_create(0), myfree); + } + setsid(); + } } +void smtp_sasl_post_init(void) { + if (*var_smtp_sasl_auth_cache_name == 0) { + var_use_limit = 0; + var_idle_limit = 0; + } +} + /* smtp_sasl_connect - per-session client initialization */ void smtp_sasl_connect(SMTP_SESSION *session) { @@ -257,19 +296,38 @@ session->host, sasl_opts_val)) == 0) msg_fatal("SASL per-connection initialization failed"); session->sasl_reply = vstring_alloc(20); } +static int smtp_sasl_parse_cache_entry(char *buf, long *timestamp, + char **status, char **text) { + if ((*status = split_at(buf,':')) != 0 + && (*text = split_at(*status,':')) != 0 && alldig(buf)) { + *timestamp = atol(buf); + return (0); + } + msg_warn("bad smtp_sasl_auth_cache_map entry: %.100s", buf); + return (-1); +} + /* smtp_sasl_authenticate - run authentication protocol */ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) { const char *myname = "smtp_sasl_authenticate"; SMTP_RESP *resp; const char *mechanism; int result; char *line; + VSTRING *buf = 0; + VSTRING *get_buf = 0; + VSTRING *put_buf = 0; + const char* raw_data = 0; + char *cached_respdsn = 0; + char *cached_respstr = 0; + long now = (long) time((time_t *) 0); + long timestamp = 0; /* * Sanity check. */ if (session->sasl_mechanism_list == 0) @@ -278,10 +336,38 @@ if (msg_verbose) msg_info("%s: %s: SASL mechanisms %s", myname, session->namaddr, session->sasl_mechanism_list); /* + * Check auth failure cache, and fail if this (relayhost,user,pass) + * triple matches an entry that is new enough. + */ + if (var_smtp_sasl_auth_cache_enable && (buf = vstring_alloc(10))) { + vstring_sprintf(buf, "%s:%s:%s", session->sasl_username, + session->host, session->sasl_passwd); + if ((raw_data = dict_get(smtp_sasl_auth_cache_map,STR(buf))) && (get_buf = vstring_alloc(10))) { + if(vstring_strcpy(get_buf, raw_data) + && smtp_sasl_parse_cache_entry(STR(get_buf),×tamp, + &cached_respdsn,&cached_respstr) == 0 + && timestamp + var_smtp_sasl_auth_cache_time > now) { + 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, raw_data); + vstring_free(get_buf); + vstring_free(buf); + return (0); + } else { + /* timeout or corrupt cache entry */ + dict_del(smtp_sasl_auth_cache_map,STR(buf)); + } + vstring_free(get_buf); + } + vstring_free(buf); + } + + /* * Start the client side authentication protocol. */ result = xsasl_client_first(session->sasl_client, session->sasl_mechanism_list, session->sasl_username, @@ -343,10 +429,26 @@ // begin: KPS20071119 - fix: Incorrect authentication data if (var_smtp_sasl_auth_soft_bounce && resp->code / 100 == 5) { STR(resp->dsn_buf)[0] = '4'; } // end: KPS20071119 - fix: Incorrect authentication data + + /* + * Add (relayhost,user,pass) triple to auth failure cache + */ + if (var_smtp_sasl_auth_cache_enable && (buf = vstring_alloc(10))) { + vstring_sprintf(buf, "%s:%s:%s", session->sasl_username, + session->host, session->sasl_passwd); + if (put_buf = vstring_alloc(10)) { + vstring_sprintf(put_buf, "%ld:%s:%s", now, + resp->dsn, resp->str); + dict_put(smtp_sasl_auth_cache_map, STR(buf), STR(put_buf)); + vstring_free(put_buf); + } + vstring_free(buf); + } + 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);
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
© 2004-2008 readlist.com