mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 22:25:24 +00:00
postfix-1.1.11-20020921
This commit is contained in:
committed by
Viktor Dukhovni
parent
9e4b7b9937
commit
a97acc2300
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@@ -131,6 +131,8 @@
|
|||||||
-TSINK_STATE
|
-TSINK_STATE
|
||||||
-TSMTPD_CMD
|
-TSMTPD_CMD
|
||||||
-TSMTPD_DEFER
|
-TSMTPD_DEFER
|
||||||
|
-TSMTPD_RBL_EXPAND_CONTEXT
|
||||||
|
-TSMTPD_RBL_STATE
|
||||||
-TSMTPD_STATE
|
-TSMTPD_STATE
|
||||||
-TSMTPD_TOKEN
|
-TSMTPD_TOKEN
|
||||||
-TSMTP_ADDR
|
-TSMTP_ADDR
|
||||||
|
@@ -6978,6 +6978,15 @@ Apologies for any names omitted.
|
|||||||
Bugfix: pickup should not preserve INSPECT or FILTER records
|
Bugfix: pickup should not preserve INSPECT or FILTER records
|
||||||
from "postsuper -r". File: pickup/pickup.c.
|
from "postsuper -r". File: pickup/pickup.c.
|
||||||
|
|
||||||
|
20020919
|
||||||
|
|
||||||
|
Feature: reject_rbl <domainname> by LaMont Jones.
|
||||||
|
|
||||||
|
20020921
|
||||||
|
|
||||||
|
Internal: generic caching and reject reporting that can be
|
||||||
|
used for both RBL and RHSBL.
|
||||||
|
|
||||||
Open problems:
|
Open problems:
|
||||||
|
|
||||||
Low: smtpd should log queue ID with reject/warn/hold/discard
|
Low: smtpd should log queue ID with reject/warn/hold/discard
|
||||||
|
@@ -1202,6 +1202,11 @@ extern int var_access_map_code;
|
|||||||
|
|
||||||
#define WARN_IF_REJECT "warn_if_reject"
|
#define WARN_IF_REJECT "warn_if_reject"
|
||||||
|
|
||||||
|
#define REJECT_RBL "reject_rbl"
|
||||||
|
#define VAR_RBL_REPLY_MAPS "rbl_reply_maps"
|
||||||
|
#define DEF_RBL_REPLY_MAPS ""
|
||||||
|
extern char *var_rbl_reply_maps;
|
||||||
|
|
||||||
#define REJECT_MAPS_RBL "reject_maps_rbl"
|
#define REJECT_MAPS_RBL "reject_maps_rbl"
|
||||||
#define VAR_MAPS_RBL_CODE "maps_rbl_reject_code"
|
#define VAR_MAPS_RBL_CODE "maps_rbl_reject_code"
|
||||||
#define DEF_MAPS_RBL_CODE 554
|
#define DEF_MAPS_RBL_CODE 554
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change the patchlevel and the release date. Snapshots change the
|
* Patches change the patchlevel and the release date. Snapshots change the
|
||||||
* release date only, unless they include the same bugfix as a patch release.
|
* release date only, unless they include the same bugfix as a patch release.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20020918"
|
#define MAIL_RELEASE_DATE "20020921"
|
||||||
|
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE
|
#define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE
|
||||||
|
@@ -67,26 +67,33 @@ depend: $(MAKES)
|
|||||||
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
|
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
|
||||||
@$(EXPORT) make -f Makefile.in Makefile 1>&2
|
@$(EXPORT) make -f Makefile.in Makefile 1>&2
|
||||||
|
|
||||||
tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_token_test
|
tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_exp_test \
|
||||||
|
smtpd_token_test
|
||||||
|
|
||||||
smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref
|
smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref smtpd_check_access
|
||||||
../postmap/postmap hash:smtpd_check_access
|
../postmap/postmap hash:smtpd_check_access
|
||||||
./smtpd_check <smtpd_check.in >smtpd_check.tmp 2>&1
|
./smtpd_check <smtpd_check.in >smtpd_check.tmp 2>&1
|
||||||
diff smtpd_check.ref smtpd_check.tmp
|
diff smtpd_check.ref smtpd_check.tmp
|
||||||
rm -f smtpd_check.tmp smtpd_check_access.*
|
rm -f smtpd_check.tmp smtpd_check_access.*
|
||||||
|
|
||||||
smtpd_check_test2: smtpd_check smtpd_check.in2 smtpd_check.ref2
|
smtpd_check_test2: smtpd_check smtpd_check.in2 smtpd_check.ref2 smtpd_check_access
|
||||||
../postmap/postmap hash:smtpd_check_access
|
../postmap/postmap hash:smtpd_check_access
|
||||||
./smtpd_check <smtpd_check.in2 >smtpd_check.tmp 2>&1
|
./smtpd_check <smtpd_check.in2 >smtpd_check.tmp 2>&1
|
||||||
diff smtpd_check.ref2 smtpd_check.tmp
|
diff smtpd_check.ref2 smtpd_check.tmp
|
||||||
rm -f smtpd_check.tmp smtpd_check_access.*
|
rm -f smtpd_check.tmp smtpd_check_access.*
|
||||||
|
|
||||||
smtpd_acl_test: smtpd_check smtpd_acl.in smtpd_acl.ref
|
smtpd_acl_test: smtpd_check smtpd_acl.in smtpd_acl.ref smtpd_check_access
|
||||||
../postmap/postmap hash:smtpd_check_access
|
../postmap/postmap hash:smtpd_check_access
|
||||||
./smtpd_check <smtpd_acl.in >smtpd_check.tmp 2>&1
|
./smtpd_check <smtpd_acl.in >smtpd_check.tmp 2>&1
|
||||||
diff smtpd_acl.ref smtpd_check.tmp
|
diff smtpd_acl.ref smtpd_check.tmp
|
||||||
rm -f smtpd_check.tmp smtpd_check_access.*
|
rm -f smtpd_check.tmp smtpd_check_access.*
|
||||||
|
|
||||||
|
smtpd_exp_test: smtpd_check smtpd_exp.in smtpd_exp.ref
|
||||||
|
../postmap/postmap hash:smtpd_check_access
|
||||||
|
./smtpd_check <smtpd_exp.in >smtpd_exp.tmp 2>&1
|
||||||
|
diff smtpd_exp.ref smtpd_exp.tmp
|
||||||
|
rm -f smtpd_exp.tmp smtpd_check_access.*
|
||||||
|
|
||||||
smtpd_token_test: smtpd_token smtpd_token.in smtpd_token.ref
|
smtpd_token_test: smtpd_token smtpd_token.in smtpd_token.ref
|
||||||
./smtpd_token <smtpd_token.in >smtpd_token.tmp 2>&1
|
./smtpd_token <smtpd_token.in >smtpd_token.tmp 2>&1
|
||||||
diff smtpd_token.ref smtpd_token.tmp
|
diff smtpd_token.ref smtpd_token.tmp
|
||||||
|
@@ -362,6 +362,7 @@ int var_relay_code;
|
|||||||
int var_maps_rbl_code;
|
int var_maps_rbl_code;
|
||||||
int var_access_map_code;
|
int var_access_map_code;
|
||||||
char *var_maps_rbl_domains;
|
char *var_maps_rbl_domains;
|
||||||
|
char *var_rbl_reply_maps;
|
||||||
int var_helo_required;
|
int var_helo_required;
|
||||||
int var_reject_code;
|
int var_reject_code;
|
||||||
int var_defer_code;
|
int var_defer_code;
|
||||||
@@ -1616,6 +1617,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_ETRN_CHECKS, DEF_ETRN_CHECKS, &var_etrn_checks, 0, 0,
|
VAR_ETRN_CHECKS, DEF_ETRN_CHECKS, &var_etrn_checks, 0, 0,
|
||||||
VAR_DATA_CHECKS, DEF_DATA_CHECKS, &var_data_checks, 0, 0,
|
VAR_DATA_CHECKS, DEF_DATA_CHECKS, &var_data_checks, 0, 0,
|
||||||
VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 0, 0,
|
VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 0, 0,
|
||||||
|
VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps, 0, 0,
|
||||||
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
|
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
|
||||||
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
|
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
|
||||||
VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0,
|
VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0,
|
||||||
|
@@ -89,6 +89,7 @@ typedef struct SMTPD_STATE {
|
|||||||
int warn_if_reject; /* force reject into warning */
|
int warn_if_reject; /* force reject into warning */
|
||||||
SMTPD_DEFER defer_if_reject; /* force reject into deferral */
|
SMTPD_DEFER defer_if_reject; /* force reject into deferral */
|
||||||
SMTPD_DEFER defer_if_permit; /* force permit into deferral */
|
SMTPD_DEFER defer_if_permit; /* force permit into deferral */
|
||||||
|
VSTRING *expand_buf; /* scratch space for $name expansion */
|
||||||
} SMTPD_STATE;
|
} SMTPD_STATE;
|
||||||
|
|
||||||
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
|
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
|
||||||
|
@@ -89,12 +89,19 @@
|
|||||||
/* .IP "check_recipient_access maptype:mapname"
|
/* .IP "check_recipient_access maptype:mapname"
|
||||||
/* Look up the resolved recipient address in the named access table,
|
/* Look up the resolved recipient address in the named access table,
|
||||||
/* any parent domains of the recipient domain, and the localpart@.
|
/* any parent domains of the recipient domain, and the localpart@.
|
||||||
|
/* .IP reject_rbl rbl.domain
|
||||||
|
/* Look up the reversed client network address in the specified
|
||||||
|
/* real-time blackhole DNS zone. The \fIrbl_reply_maps\fR configuration
|
||||||
|
/* parameter is used to generate the template for the reject message.
|
||||||
|
/* If it is not specified, or the rbl domain cannot be found, then a
|
||||||
|
/* default template is used. The \fImaps_rbl_reject_code\fR
|
||||||
|
/* configuration parameter specifies the reject status code used in
|
||||||
|
/* the default template (default: 554).
|
||||||
/* .IP reject_maps_rbl
|
/* .IP reject_maps_rbl
|
||||||
/* Look up the reversed client network address in the real-time blackhole
|
/* Look up the reversed client network address in the real-time blackhole
|
||||||
/* DNS zones below the domains listed in the "maps_rbl_domains"
|
/* DNS zones below the domains listed in the "maps_rbl_domains"
|
||||||
/* configuration parameter. The \fImaps_rbl_reject_code\fR
|
/* configuration parameter. This is equivalent to using "reject_rbl"
|
||||||
/* configuration parameter specifies the reject status code
|
/* once for each such domain.
|
||||||
/* (default: 554).
|
|
||||||
/* .IP permit_naked_ip_address
|
/* .IP permit_naked_ip_address
|
||||||
/* Permit the use of a naked IP address (without enclosing [])
|
/* Permit the use of a naked IP address (without enclosing [])
|
||||||
/* in HELO/EHLO commands.
|
/* in HELO/EHLO commands.
|
||||||
@@ -277,6 +284,7 @@
|
|||||||
#include <dict.h>
|
#include <dict.h>
|
||||||
#include <htable.h>
|
#include <htable.h>
|
||||||
#include <ctable.h>
|
#include <ctable.h>
|
||||||
|
#include <mac_expand.h>
|
||||||
|
|
||||||
/* DNS library. */
|
/* DNS library. */
|
||||||
|
|
||||||
@@ -326,6 +334,7 @@ static jmp_buf smtpd_check_buf;
|
|||||||
*/
|
*/
|
||||||
static VSTRING *error_text;
|
static VSTRING *error_text;
|
||||||
static CTABLE *smtpd_resolve_cache;
|
static CTABLE *smtpd_resolve_cache;
|
||||||
|
static CTABLE *smtpd_rbl_cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pre-opened SMTP recipient maps so we can reject mail for unknown users.
|
* Pre-opened SMTP recipient maps so we can reject mail for unknown users.
|
||||||
@@ -339,6 +348,11 @@ static MAPS *virtual_maps;
|
|||||||
static MAPS *virt_mailbox_maps;
|
static MAPS *virt_mailbox_maps;
|
||||||
static MAPS *relocated_maps;
|
static MAPS *relocated_maps;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response templates for various rbl domains.
|
||||||
|
*/
|
||||||
|
static MAPS *rbl_reply_maps;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pre-opened sender to login name mapping.
|
* Pre-opened sender to login name mapping.
|
||||||
*/
|
*/
|
||||||
@@ -413,6 +427,23 @@ static void PRINTFLIKE(3, 4) defer_if(SMTPD_DEFER *, int, const char *,...);
|
|||||||
defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
|
defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
|
||||||
#define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) \
|
#define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) \
|
||||||
defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2))
|
defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cached RBL lookup state.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
char *txt; /* TXT record or null */
|
||||||
|
} SMTPD_RBL_STATE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context for RBL $name expansion.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
SMTPD_STATE *state; /* general state */
|
||||||
|
SMTPD_RBL_STATE *rbl_state; /* cached RBL state */
|
||||||
|
const char *domain; /* query domain */
|
||||||
|
} SMTPD_RBL_EXPAND_CONTEXT;
|
||||||
|
|
||||||
/* resolve_pagein - page in an address resolver result */
|
/* resolve_pagein - page in an address resolver result */
|
||||||
|
|
||||||
static void *resolve_pagein(const char *addr, void *unused_context)
|
static void *resolve_pagein(const char *addr, void *unused_context)
|
||||||
@@ -455,6 +486,53 @@ static void resolve_pageout(void *data, void *unused_context)
|
|||||||
myfree((void *) reply);
|
myfree((void *) reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rbl_pagein - page in an RBL lookup result */
|
||||||
|
|
||||||
|
static void *rbl_pagein(const char *query, void *unused_context)
|
||||||
|
{
|
||||||
|
DNS_RR *txt_list;
|
||||||
|
VSTRING *why;
|
||||||
|
int dns_status;
|
||||||
|
SMTPD_RBL_STATE *rbl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the query.
|
||||||
|
*/
|
||||||
|
why = vstring_alloc(10);
|
||||||
|
dns_status = dns_lookup(query, T_A, 0, (DNS_RR **) 0,
|
||||||
|
(VSTRING *) 0, why);
|
||||||
|
if (dns_status != DNS_OK && dns_status != DNS_NOTFOUND)
|
||||||
|
msg_warn("%s: RBL lookup error: %s", query, STR(why));
|
||||||
|
vstring_free(why);
|
||||||
|
if (dns_status != DNS_OK)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the result.
|
||||||
|
*/
|
||||||
|
rbl = (SMTPD_RBL_STATE *) mymalloc(sizeof(*rbl));
|
||||||
|
if (dns_lookup(query, T_TXT, 0, &txt_list,
|
||||||
|
(VSTRING *) 0, (VSTRING *) 0) == DNS_OK) {
|
||||||
|
rbl->txt = mystrdup(txt_list->data);
|
||||||
|
dns_rr_free(txt_list);
|
||||||
|
} else
|
||||||
|
rbl->txt = 0;
|
||||||
|
return ((void *) rbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rbl_pageout - page out an RBL lookup result */
|
||||||
|
|
||||||
|
static void rbl_pageout(void *data, void *unused_context)
|
||||||
|
{
|
||||||
|
SMTPD_RBL_STATE *rbl = (SMTPD_RBL_STATE *) data;
|
||||||
|
|
||||||
|
if (rbl != 0) {
|
||||||
|
if (rbl->txt)
|
||||||
|
myfree(rbl->txt);
|
||||||
|
myfree((char *) rbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* smtpd_check_parse - pre-parse restrictions */
|
/* smtpd_check_parse - pre-parse restrictions */
|
||||||
|
|
||||||
static ARGV *smtpd_check_parse(const char *checks)
|
static ARGV *smtpd_check_parse(const char *checks)
|
||||||
@@ -581,6 +659,12 @@ void smtpd_check_init(void)
|
|||||||
|
|
||||||
access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS);
|
access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Templates for RBL rejection replies.
|
||||||
|
*/
|
||||||
|
rbl_reply_maps = maps_create(VAR_RBL_REPLY_MAPS, var_rbl_reply_maps,
|
||||||
|
DICT_FLAG_LOCK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sender to login name mapping.
|
* Sender to login name mapping.
|
||||||
*/
|
*/
|
||||||
@@ -596,8 +680,13 @@ void smtpd_check_init(void)
|
|||||||
/*
|
/*
|
||||||
* Initialize the resolved address cache.
|
* Initialize the resolved address cache.
|
||||||
*/
|
*/
|
||||||
smtpd_resolve_cache = ctable_create(100, resolve_pagein,
|
smtpd_resolve_cache = ctable_create(100, resolve_pagein, resolve_pageout,
|
||||||
resolve_pageout, (void *) 0);
|
(void *) 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the RBL lookup cache.
|
||||||
|
*/
|
||||||
|
smtpd_rbl_cache = ctable_create(100, rbl_pagein, rbl_pageout, (void *) 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pre-parse the restriction lists. At the same time, pre-open tables
|
* Pre-parse the restriction lists. At the same time, pre-open tables
|
||||||
@@ -2034,24 +2123,190 @@ static int check_mail_access(SMTPD_STATE *state, const char *table,
|
|||||||
CHECK_MAIL_ACCESS_RETURN(SMTPD_CHECK_DUNNO);
|
CHECK_MAIL_ACCESS_RETURN(SMTPD_CHECK_DUNNO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reject_maps_rbl - reject if client address in real-time blackhole list */
|
/* edit_addr - return address or substring thereof */
|
||||||
|
|
||||||
static int reject_maps_rbl(SMTPD_STATE *state)
|
static const char *edit_addr(VSTRING *buf, const char *addr, const char *name)
|
||||||
{
|
{
|
||||||
char *myname = "reject_maps_rbl";
|
const char *p;
|
||||||
ARGV *octets = argv_split(state->addr, ".");
|
|
||||||
VSTRING *query = vstring_alloc(100);
|
/*
|
||||||
char *saved_domains = mystrdup(var_maps_rbl_domains);
|
* Return "undefined" when the address is unavailable.
|
||||||
char *bp = saved_domains;
|
*/
|
||||||
char *rbl_domain;
|
if (addr == 0)
|
||||||
char *rbl_reason;
|
return (0);
|
||||||
char *rbl_fodder;
|
|
||||||
DNS_RR *txt_list;
|
/*
|
||||||
int reverse_len;
|
* "sender" or "recipient".
|
||||||
int dns_status = DNS_FAIL;
|
*/
|
||||||
|
if (*name == 0) {
|
||||||
|
if (*addr)
|
||||||
|
return (addr);
|
||||||
|
else
|
||||||
|
return ("<>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "sender_name" or "recipient_name".
|
||||||
|
*/
|
||||||
|
#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
|
||||||
|
|
||||||
|
else if (STREQ(name, "_name")) {
|
||||||
|
if (*addr) {
|
||||||
|
if ((p = strrchr(addr, '@')) != 0) {
|
||||||
|
vstring_strncpy(buf, addr, p - addr);
|
||||||
|
return (STR(buf));
|
||||||
|
} else {
|
||||||
|
return (addr);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return ("<>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "sender_domain" or "recipient_domain".
|
||||||
|
*/
|
||||||
|
else if (STREQ(name, "_domain")) {
|
||||||
|
if (*addr) {
|
||||||
|
if ((p = strrchr(addr, '@')) != 0) {
|
||||||
|
return (p + 1);
|
||||||
|
} else {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unknown.
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_expand_lookup - generic SMTP attribute $name expansion */
|
||||||
|
|
||||||
|
static const char *smtpd_expand_lookup(const char *name, int unused_mode,
|
||||||
|
char *context)
|
||||||
|
{
|
||||||
|
SMTPD_STATE *state = (SMTPD_STATE *) context;
|
||||||
|
|
||||||
|
if (state->expand_buf == 0)
|
||||||
|
state->expand_buf = vstring_alloc(10);
|
||||||
|
|
||||||
|
if (msg_verbose > 1)
|
||||||
|
msg_info("smtpd_expand_lookup: ${%s}", name);
|
||||||
|
|
||||||
|
#define STREQN(x,y,n) (*(x) == *(y) && strncmp((x), (y), (n)) == 0)
|
||||||
|
#define CONST_LEN(x) (sizeof(x) - 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't query main.cf parameters, as the result of expansion could
|
||||||
|
* reveal system-internal information in server replies.
|
||||||
|
*/
|
||||||
|
if (STREQ(name, "client")) {
|
||||||
|
return (state->namaddr);
|
||||||
|
} else if (STREQ(name, "client_address")) {
|
||||||
|
return (state->addr);
|
||||||
|
} else if (STREQ(name, "client_name")) {
|
||||||
|
return (state->name);
|
||||||
|
} else if (STREQ(name, "helo_name")) {
|
||||||
|
return (state->helo_name ? state->helo_name : 0);
|
||||||
|
} else if (STREQN(name, "sender", CONST_LEN("sender"))) {
|
||||||
|
return (edit_addr(state->expand_buf, state->sender,
|
||||||
|
name + CONST_LEN("sender")));
|
||||||
|
} else if (STREQN(name, "recipient", CONST_LEN("recipient"))) {
|
||||||
|
return (edit_addr(state->expand_buf, state->recipient,
|
||||||
|
name + CONST_LEN("recipient")));
|
||||||
|
} else {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rbl_expand_lookup - RBL specific $name expansion */
|
||||||
|
|
||||||
|
static const char *rbl_expand_lookup(const char *name, int mode,
|
||||||
|
char *context)
|
||||||
|
{
|
||||||
|
SMTPD_RBL_EXPAND_CONTEXT *rbl_exp = (SMTPD_RBL_EXPAND_CONTEXT *) context;
|
||||||
|
SMTPD_RBL_STATE *rbl = rbl_exp->rbl_state;
|
||||||
|
SMTPD_STATE *state = rbl_exp->state;
|
||||||
|
|
||||||
|
if (state->expand_buf == 0)
|
||||||
|
state->expand_buf = vstring_alloc(10);
|
||||||
|
|
||||||
|
if (msg_verbose > 1)
|
||||||
|
msg_info("rbl_expand_lookup: ${%s}", name);
|
||||||
|
|
||||||
|
if (STREQ(name, "rbl_code")) {
|
||||||
|
vstring_sprintf(state->expand_buf, "%d", var_maps_rbl_code);
|
||||||
|
return (STR(state->expand_buf));
|
||||||
|
} else if (STREQ(name, "rbl_domain")) {
|
||||||
|
return (rbl_exp->domain);
|
||||||
|
} else if (STREQ(name, "rbl_txt")) {
|
||||||
|
return (rbl->txt);
|
||||||
|
} else {
|
||||||
|
return (smtpd_expand_lookup(name, mode, (char *) state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rbl_reject_reply - format reply after RBL reject */
|
||||||
|
|
||||||
|
static int rbl_reject_reply(SMTPD_STATE *state, SMTPD_RBL_STATE *rbl,
|
||||||
|
const char *rbl_domain)
|
||||||
|
{
|
||||||
|
const char *myname = "rbl_reject_reply";
|
||||||
|
VSTRING *why = 0;
|
||||||
|
const char *template = 0;
|
||||||
|
char *low_name;
|
||||||
|
SMTPD_RBL_EXPAND_CONTEXT rbl_exp;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (*var_rbl_reply_maps) {
|
||||||
|
low_name = lowercase(mystrdup(rbl_domain));
|
||||||
|
template = maps_find(rbl_reply_maps, low_name, 0);
|
||||||
|
myfree(low_name);
|
||||||
|
}
|
||||||
|
if (template) {
|
||||||
|
why = vstring_alloc(10);
|
||||||
|
rbl_exp.state = state; /* XXX */
|
||||||
|
rbl_exp.rbl_state = rbl;
|
||||||
|
rbl_exp.domain = rbl_domain;
|
||||||
|
#define NO_SMTPD_EXP_FILTER ((char *) 0) /* XXX */
|
||||||
|
if (mac_expand(why, template, MAC_EXP_FLAG_NONE,
|
||||||
|
NO_SMTPD_EXP_FILTER, rbl_expand_lookup,
|
||||||
|
(char *) &rbl_exp) & MAC_PARSE_ERROR) {
|
||||||
|
msg_warn("%s: bad rbl template: %s", myname, template);
|
||||||
|
template = 0; /* pretend not found */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (template) {
|
||||||
|
result = smtpd_check_reject(state, MAIL_ERROR_POLICY, STR(why));
|
||||||
|
} else {
|
||||||
|
result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||||
|
"%d Service unavailable; [%s] blocked using %s%s%s",
|
||||||
|
var_maps_rbl_code, state->addr,
|
||||||
|
rbl_domain, rbl->txt ? ", reason: " : "", rbl->txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up.
|
||||||
|
*/
|
||||||
|
if (why)
|
||||||
|
vstring_free(why);
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reject_rbl - reject if client address in real-time blackhole list */
|
||||||
|
|
||||||
|
static int reject_rbl(SMTPD_STATE *state, const char *rbl_domain)
|
||||||
|
{
|
||||||
|
char *myname = "reject_rbl";
|
||||||
|
ARGV *octets;
|
||||||
|
VSTRING *query;
|
||||||
int i;
|
int i;
|
||||||
int result;
|
int result;
|
||||||
VSTRING *why;
|
SMTPD_RBL_STATE *rbl;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s", myname, state->addr);
|
msg_info("%s: %s", myname, state->addr);
|
||||||
@@ -2065,57 +2320,62 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build the constant part of the RBL query: the reverse client address.
|
* Initialize.
|
||||||
*/
|
*/
|
||||||
|
query = vstring_alloc(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reverse the client IPV4 address, tack on the RBL domain name and query
|
||||||
|
* the DNS for an A record. If the record exists, the client address is
|
||||||
|
* blacklisted. If the DNS lookup produces no definitive reply, give the
|
||||||
|
* client the benefit of the doubt. We can't block all email simply
|
||||||
|
* because an RBL server is unavailable.
|
||||||
|
*/
|
||||||
|
octets = argv_split(state->addr, ".");
|
||||||
for (i = octets->argc - 1; i >= 0; i--) {
|
for (i = octets->argc - 1; i >= 0; i--) {
|
||||||
vstring_strcat(query, octets->argv[i]);
|
vstring_strcat(query, octets->argv[i]);
|
||||||
vstring_strcat(query, ".");
|
vstring_strcat(query, ".");
|
||||||
}
|
}
|
||||||
reverse_len = VSTRING_LEN(query);
|
argv_free(octets);
|
||||||
|
|
||||||
/*
|
|
||||||
* Tack on each RBL domain name and query the DNS for an A record. If the
|
|
||||||
* record exists, the client address is blacklisted.
|
|
||||||
*/
|
|
||||||
why = vstring_alloc(10);
|
|
||||||
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
|
|
||||||
vstring_truncate(query, reverse_len);
|
|
||||||
vstring_strcat(query, rbl_domain);
|
vstring_strcat(query, rbl_domain);
|
||||||
dns_status = dns_lookup(STR(query), T_A, 0, (DNS_RR **) 0,
|
rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query));
|
||||||
(VSTRING *) 0, why);
|
|
||||||
if (dns_status == DNS_OK)
|
|
||||||
break;
|
|
||||||
if (dns_status != DNS_NOTFOUND)
|
|
||||||
msg_warn("%s: RBL lookup error: %s", STR(query), STR(why));
|
|
||||||
}
|
|
||||||
vstring_free(why);
|
|
||||||
|
|
||||||
/*
|
if (rbl == 0) {
|
||||||
* Report the result.
|
|
||||||
*/
|
|
||||||
if (dns_status == DNS_OK) {
|
|
||||||
if (dns_lookup(STR(query), T_TXT, 0, &txt_list,
|
|
||||||
(VSTRING *) 0, (VSTRING *) 0) == DNS_OK) {
|
|
||||||
rbl_fodder = ", reason: ";
|
|
||||||
rbl_reason = (char *) txt_list->data;
|
|
||||||
} else {
|
|
||||||
txt_list = 0;
|
|
||||||
rbl_fodder = rbl_reason = "";
|
|
||||||
}
|
|
||||||
result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
|
||||||
"%d Service unavailable; [%s] blocked using %s%s%s",
|
|
||||||
var_maps_rbl_code, state->addr, rbl_domain,
|
|
||||||
rbl_fodder, rbl_reason);
|
|
||||||
if (txt_list)
|
|
||||||
dns_rr_free(txt_list);
|
|
||||||
} else
|
|
||||||
result = SMTPD_CHECK_DUNNO;
|
result = SMTPD_CHECK_DUNNO;
|
||||||
|
} else {
|
||||||
|
result = rbl_reject_reply(state, rbl, rbl_domain);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up.
|
* Clean up.
|
||||||
*/
|
*/
|
||||||
argv_free(octets);
|
|
||||||
vstring_free(query);
|
vstring_free(query);
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reject_maps_rbl - reject if client address in real-time blackhole list */
|
||||||
|
|
||||||
|
static int reject_maps_rbl(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
char *myname = "reject_maps_rbl";
|
||||||
|
char *saved_domains = mystrdup(var_maps_rbl_domains);
|
||||||
|
char *bp = saved_domains;
|
||||||
|
char *rbl_domain;
|
||||||
|
int result = SMTPD_CHECK_DUNNO;
|
||||||
|
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: %s", myname, state->addr);
|
||||||
|
|
||||||
|
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
|
||||||
|
result = reject_rbl(state, rbl_domain);
|
||||||
|
if (result != SMTPD_CHECK_DUNNO)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up.
|
||||||
|
*/
|
||||||
myfree(saved_domains);
|
myfree(saved_domains);
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
@@ -2268,6 +2528,12 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
|||||||
SMTPD_NAME_CLIENT, def_acl);
|
SMTPD_NAME_CLIENT, def_acl);
|
||||||
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
|
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
|
||||||
status = reject_maps_rbl(state);
|
status = reject_maps_rbl(state);
|
||||||
|
} else if (strcasecmp(name, REJECT_RBL) == 0) {
|
||||||
|
if (*(cpp += 1) == 0)
|
||||||
|
msg_warn("restriction %s requires domain name argument",
|
||||||
|
REJECT_RBL);
|
||||||
|
else
|
||||||
|
status = reject_rbl(state, *cpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2894,6 +3160,7 @@ char *var_par_dom_match;
|
|||||||
char *var_smtpd_null_key;
|
char *var_smtpd_null_key;
|
||||||
char *var_smtpd_snd_auth_maps;
|
char *var_smtpd_snd_auth_maps;
|
||||||
char *var_double_bounce_sender;
|
char *var_double_bounce_sender;
|
||||||
|
char *var_rbl_reply_maps;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
@@ -2920,6 +3187,7 @@ static STRING_TABLE string_table[] = {
|
|||||||
VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps,
|
VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps,
|
||||||
VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key,
|
VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key,
|
||||||
VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender,
|
VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender,
|
||||||
|
VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3258,6 +3526,13 @@ int main(int argc, char **argv)
|
|||||||
resp = 0;
|
resp = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (strcasecmp(args->argv[0], "rbl_reply_maps") == 0) {
|
||||||
|
UPDATE_STRING(var_rbl_reply_maps, args->argv[1]);
|
||||||
|
UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS,
|
||||||
|
var_rbl_reply_maps, DICT_FLAG_LOCK);
|
||||||
|
resp = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (strcasecmp(args->argv[0], "mynetworks") == 0) {
|
if (strcasecmp(args->argv[0], "mynetworks") == 0) {
|
||||||
namadr_list_free(mynetworks);
|
namadr_list_free(mynetworks);
|
||||||
mynetworks =
|
mynetworks =
|
||||||
|
@@ -30,3 +30,10 @@ reject@ok.domain REJECT
|
|||||||
ok@ok.domain OK
|
ok@ok.domain OK
|
||||||
ok.domain OK
|
ok.domain OK
|
||||||
<> 550 Go away postmaster
|
<> 550 Go away postmaster
|
||||||
|
|
||||||
|
blackholes.mail-abuse.org $rbl_code client=$client
|
||||||
|
client_address=$client_address
|
||||||
|
client_name=$client_name helo_name=$helo_name
|
||||||
|
sender=$sender sender_name=$sender_name
|
||||||
|
recipient=$recipient recipient_name=$recipient_name
|
||||||
|
rbl_code=$rbl_code rbl_domain=$rbl_domain rbl_txt=$rbl_txt
|
||||||
|
16
postfix/src/smtpd/smtpd_exp.in
Normal file
16
postfix/src/smtpd/smtpd_exp.in
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Initialize.
|
||||||
|
#
|
||||||
|
#! ../bin/postmap smtpd_check_access
|
||||||
|
#msg_verbose 1
|
||||||
|
smtpd_delay_reject 0
|
||||||
|
mynetworks 127.0.0.0/8,168.100.189.0/28
|
||||||
|
relay_domains porcupine.org
|
||||||
|
maps_rbl_domains blackholes.mail-abuse.org
|
||||||
|
rbl_reply_maps hash:smtpd_check_access
|
||||||
|
#
|
||||||
|
# RBL
|
||||||
|
#
|
||||||
|
client_restrictions reject_maps_rbl
|
||||||
|
client spike.porcupine.org 168.100.189.2
|
||||||
|
client foo 127.0.0.2
|
25
postfix/src/smtpd/smtpd_exp.ref
Normal file
25
postfix/src/smtpd/smtpd_exp.ref
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
>>> #
|
||||||
|
>>> # Initialize.
|
||||||
|
>>> #
|
||||||
|
>>> #! ../bin/postmap smtpd_check_access
|
||||||
|
>>> #msg_verbose 1
|
||||||
|
>>> smtpd_delay_reject 0
|
||||||
|
OK
|
||||||
|
>>> mynetworks 127.0.0.0/8,168.100.189.0/28
|
||||||
|
OK
|
||||||
|
>>> relay_domains porcupine.org
|
||||||
|
OK
|
||||||
|
>>> maps_rbl_domains blackholes.mail-abuse.org
|
||||||
|
OK
|
||||||
|
>>> rbl_reply_maps hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> #
|
||||||
|
>>> # RBL
|
||||||
|
>>> #
|
||||||
|
>>> client_restrictions reject_maps_rbl
|
||||||
|
OK
|
||||||
|
>>> client spike.porcupine.org 168.100.189.2
|
||||||
|
OK
|
||||||
|
>>> client foo 127.0.0.2
|
||||||
|
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name= sender= sender_name= recipient= recipient_name= rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
|
||||||
|
554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name= sender= sender_name= recipient= recipient_name= rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
|
@@ -93,6 +93,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
|||||||
state->junk_cmds = 0;
|
state->junk_cmds = 0;
|
||||||
state->defer_if_reject.reason = 0;
|
state->defer_if_reject.reason = 0;
|
||||||
state->defer_if_permit.reason = 0;
|
state->defer_if_permit.reason = 0;
|
||||||
|
state->expand_buf = 0;
|
||||||
|
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
if (SMTPD_STAND_ALONE(state))
|
if (SMTPD_STAND_ALONE(state))
|
||||||
@@ -129,6 +130,8 @@ void smtpd_state_reset(SMTPD_STATE *state)
|
|||||||
vstring_free(state->defer_if_permit.reason);
|
vstring_free(state->defer_if_permit.reason);
|
||||||
if (state->defer_if_reject.reason)
|
if (state->defer_if_reject.reason)
|
||||||
vstring_free(state->defer_if_reject.reason);
|
vstring_free(state->defer_if_reject.reason);
|
||||||
|
if (state->expand_buf)
|
||||||
|
vstring_free(state->expand_buf);
|
||||||
|
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
if (var_smtpd_sasl_enable)
|
if (var_smtpd_sasl_enable)
|
||||||
|
Reference in New Issue
Block a user