mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
postfix-2.0.16-20030917
This commit is contained in:
committed by
Viktor Dukhovni
parent
b7fe5bb669
commit
116a98032d
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@@ -77,6 +77,7 @@
|
|||||||
-TINTV
|
-TINTV
|
||||||
-TINT_TABLE
|
-TINT_TABLE
|
||||||
-TJMP_BUF_WRAPPER
|
-TJMP_BUF_WRAPPER
|
||||||
|
-TLDAP_CONN
|
||||||
-TLMTP_ATTR
|
-TLMTP_ATTR
|
||||||
-TLMTP_RESP
|
-TLMTP_RESP
|
||||||
-TLMTP_SESSION
|
-TLMTP_SESSION
|
||||||
|
@@ -8558,6 +8558,38 @@ Apologies for any names omitted.
|
|||||||
Cleanup: postcat is now null-byte transparent. File:
|
Cleanup: postcat is now null-byte transparent. File:
|
||||||
postcat/postcat.c.
|
postcat/postcat.c.
|
||||||
|
|
||||||
|
20030916
|
||||||
|
|
||||||
|
Feature: ``check_{sender,recipient}_mx_access maptype:mapname''
|
||||||
|
applies the named Postfix access table to the MX host name
|
||||||
|
and IP addresses for the sender or recipient address. If
|
||||||
|
no MX record is found, the A record is used instead. File:
|
||||||
|
smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
Experimental feature: ``check_{sender,recipient}_ns_access
|
||||||
|
maptype:mapname'' applies the named Postfix access table
|
||||||
|
to the DNS server hostname and IP addresses for the sender
|
||||||
|
or recipient address. If no NS record is found, the parent
|
||||||
|
domain is used instead. File: smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
20030917
|
||||||
|
|
||||||
|
Feature: ``check_helo_{ns,mx}_access maptype:mapname'',
|
||||||
|
same semantics as sender and recipient.
|
||||||
|
|
||||||
|
Multiple LDAP lookup tables in the one Postfix process now
|
||||||
|
share one LDAP connection. Code by Victor Duchovni, Morgan
|
||||||
|
Stanley. File: util/dict_ldap.c.
|
||||||
|
|
||||||
|
Performance: with prefix_domain specified for an LDAP lookup
|
||||||
|
table, lookups of @domain are skipped. Code by Victor
|
||||||
|
Duchovni, Morgan Stanley. File: util/dict_ldap.c.
|
||||||
|
|
||||||
|
Safety: check_mumble_{mx,ns}_access refuses to be used for
|
||||||
|
whitelisting. The Postfix SMTP server will reject the
|
||||||
|
request with "451 server configuration error" and will log
|
||||||
|
a warning explaining why. File: smtpd/smtpd_check.c.
|
||||||
|
|
||||||
Open problems:
|
Open problems:
|
||||||
|
|
||||||
High: when virtual aliasing is turned off after content
|
High: when virtual aliasing is turned off after content
|
||||||
|
@@ -423,6 +423,12 @@ NOTES AND THINGS TO THINK ABOUT
|
|||||||
they won't be a bottleneck, but it's a good idea to know how to tune
|
they won't be a bottleneck, but it's a good idea to know how to tune
|
||||||
your directory service.
|
your directory service.
|
||||||
|
|
||||||
|
- Multiple LDAP maps share the same LDAP connection if they differ
|
||||||
|
only in their query related parameters: base, scope, query_filter, and
|
||||||
|
so on. To take advantage of this avoid spurious differences in the
|
||||||
|
definitions of LDAP maps: host selection order, version, bind, tls
|
||||||
|
parameters, ... should be the same for multiple maps whenever possible.
|
||||||
|
|
||||||
FEEDBACK
|
FEEDBACK
|
||||||
========
|
========
|
||||||
|
|
||||||
@@ -450,9 +456,10 @@ Samuel Tardieu: Noticed that searches could include wildcards, prompting
|
|||||||
Sami Haahtinen: Referral chasing and v3 support.
|
Sami Haahtinen: Referral chasing and v3 support.
|
||||||
Victor Duchovni: ldap_bind() timeout. With fixes from LaMont Jones:
|
Victor Duchovni: ldap_bind() timeout. With fixes from LaMont Jones:
|
||||||
OpenLDAP cache deprecation. Limits on recursion, expansion
|
OpenLDAP cache deprecation. Limits on recursion, expansion
|
||||||
and query results size.
|
and query results size. LDAP connection sharing for maps
|
||||||
|
differing only in the query parameters.
|
||||||
Liviu Daia: Support for SSL/STARTTLS. Support for storing map definitions in
|
Liviu Daia: Support for SSL/STARTTLS. Support for storing map definitions in
|
||||||
external files (ldap:/path/ldap.cf) need to securely store
|
external files (ldap:/path/ldap.cf) needed to securely store
|
||||||
passwords for plain auth.
|
passwords for plain auth.
|
||||||
|
|
||||||
And of course Wietse.
|
And of course Wietse.
|
||||||
|
@@ -22,14 +22,42 @@ snapshot release). Patches change the patchlevel and the release
|
|||||||
date. Snapshots change only the release date, unless they include
|
date. Snapshots change only the release date, unless they include
|
||||||
the same bugfixes as a patch release.
|
the same bugfixes as a patch release.
|
||||||
|
|
||||||
Incompatible changes with Postfix snapshot 2.0.13-20030914
|
Major changes with Postfix snapshot 2.0.16-20030917
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
New check_{helo,sender,recipient}_{ns,mx}_access maptype:mapname
|
||||||
|
restriction that applies the specified access table to the NS or
|
||||||
|
MX hosts of the host/domain given in HELO, EHLO, MAIL FROM or RCPT
|
||||||
|
TO commands.
|
||||||
|
|
||||||
|
This can be used to block mail from so-called spammer havens, or
|
||||||
|
from sender addresses that resolve to Verisign's wild-card mail
|
||||||
|
responder, currently at IP address 64.94.110.11.
|
||||||
|
|
||||||
|
/etc/postfix/main.cf:
|
||||||
|
smtpd_mumble_restrictions =
|
||||||
|
...
|
||||||
|
reject_unknown_sender_domain
|
||||||
|
check_sender_mx_access hash:/etc/postfix/mx_access
|
||||||
|
...
|
||||||
|
|
||||||
|
/etc/postfix/mx_access:
|
||||||
|
spammer.haven.tld reject spammer mx host
|
||||||
|
64.94.110.11 reject verisign wild-card domain
|
||||||
|
|
||||||
|
Note: OK actions are not allowed for security reasons. Instead of
|
||||||
|
OK, use DUNNO in order to exclude specific hosts from blacklists.
|
||||||
|
If an OK result is found for an NS or MX host, Postfix rejects the
|
||||||
|
SMTP command with "451 Server configuration error".
|
||||||
|
|
||||||
|
Incompatible changes with Postfix snapshot 2.0.16-20030915
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
In header/body_checks actions, the OK action is being phased out,
|
In header/body_checks actions, the OK action is being phased out,
|
||||||
and the DUNNO action is being phased in. Both actions still work
|
and the DUNNO action is being phased in. Both actions still work
|
||||||
and do the same thing, but hopefully DUNNO causes less confusion.
|
and do the same thing, but hopefully DUNNO causes less confusion.
|
||||||
|
|
||||||
Major changes with Postfix snapshot 2.0.13-20030914
|
Major changes with Postfix snapshot 2.0.16-20030915
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
LDAP parameters can now be defined in external files. Specify the
|
LDAP parameters can now be defined in external files. Specify the
|
||||||
|
@@ -358,6 +358,11 @@ smtpd_helo_required = no
|
|||||||
# check_helo_access maptype:mapname
|
# check_helo_access maptype:mapname
|
||||||
# look up HELO hostname or parent domains.
|
# look up HELO hostname or parent domains.
|
||||||
# see access(5) for possible lookup results.
|
# see access(5) for possible lookup results.
|
||||||
|
# check_helo_mx_access maptype:mapname
|
||||||
|
# check_helo_ns_access maptype:mapname
|
||||||
|
# look up the helo hostname MX hosts (or name servers) and apply the
|
||||||
|
# specified access table to those hosts.
|
||||||
|
# Note: the OK result is not allowed here for security reasons.
|
||||||
# check_policy_service transport:endpoint: delegate the decision to
|
# check_policy_service transport:endpoint: delegate the decision to
|
||||||
# an external policy server. See SMTPD_POLICY_README for details.
|
# an external policy server. See SMTPD_POLICY_README for details.
|
||||||
# reject_rhsbl_helo domain.tld: reject if the helo argument is listed
|
# reject_rhsbl_helo domain.tld: reject if the helo argument is listed
|
||||||
@@ -396,6 +401,11 @@ smtpd_helo_restrictions =
|
|||||||
# check_sender_access maptype:mapname
|
# check_sender_access maptype:mapname
|
||||||
# look up sender address, parent domain, or localpart@.
|
# look up sender address, parent domain, or localpart@.
|
||||||
# see access(5) for possible lookup results.
|
# see access(5) for possible lookup results.
|
||||||
|
# check_sender_mx_access maptype:mapname
|
||||||
|
# check_sender_ns_access maptype:mapname
|
||||||
|
# look up sender address MX hosts (or name servers) and apply the
|
||||||
|
# specified access table to those hosts.
|
||||||
|
# Note: the OK result is not allowed here for security reasons.
|
||||||
# reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies
|
# reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies
|
||||||
# a MAIL FROM address owner, but the client is not (SASL) logged in as
|
# a MAIL FROM address owner, but the client is not (SASL) logged in as
|
||||||
# that MAIL FROM address owner; or if the client is (SASL) logged in, but
|
# that MAIL FROM address owner; or if the client is (SASL) logged in, but
|
||||||
@@ -467,6 +477,11 @@ smtpd_sender_restrictions =
|
|||||||
# check_recipient_access maptype:mapname
|
# check_recipient_access maptype:mapname
|
||||||
# look up recipient address, parent domain, or localpart@.
|
# look up recipient address, parent domain, or localpart@.
|
||||||
# see access(5) for possible lookup results.
|
# see access(5) for possible lookup results.
|
||||||
|
# check_recipient_mx_access maptype:mapname
|
||||||
|
# check_recipient_ns_access maptype:mapname
|
||||||
|
# look up the recipient address MX hosts (or name servers) and apply the
|
||||||
|
# specified access table to those hosts.
|
||||||
|
# Note: the OK result is not allowed here for security reasons.
|
||||||
# reject_non_fqdn_recipient: reject recipient address that is not in FQDN form
|
# reject_non_fqdn_recipient: reject recipient address that is not in FQDN form
|
||||||
# check_policy_service transport:endpoint: delegate the decision to
|
# check_policy_service transport:endpoint: delegate the decision to
|
||||||
# an external policy server. See SMTPD_POLICY_README for details.
|
# an external policy server. See SMTPD_POLICY_README for details.
|
||||||
|
@@ -599,6 +599,22 @@ or parent domains.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
<a name="check_helo_ns_access">
|
||||||
|
|
||||||
|
<dt> <b>check_helo_ns_access</b> <i>maptype</i>:<i>mapname</i>
|
||||||
|
|
||||||
|
<a name="check_helo_mx_access">
|
||||||
|
|
||||||
|
<dt> <b>check_helo_mx_access</b> <i>maptype</i>:<i>mapname</i>
|
||||||
|
|
||||||
|
<dd> Apply the specified <a href="access.5.html">access database</a>
|
||||||
|
to the DNS (or MX) servers for the host or domain name given with
|
||||||
|
the HELO (or EHLO) command.
|
||||||
|
|
||||||
|
<dd> Note: an OK result is not allowed for safety reasons.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
<a name="reject_rhsbl_helo">
|
<a name="reject_rhsbl_helo">
|
||||||
|
|
||||||
<dt> <b>reject_rhsbl_helo</b> <i>domain.tld=127.0.0.2</i>
|
<dt> <b>reject_rhsbl_helo</b> <i>domain.tld=127.0.0.2</i>
|
||||||
@@ -783,6 +799,22 @@ sender domain and parent domain, or <i>localpart</i>@.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
<a name="check_sender_ns_access">
|
||||||
|
|
||||||
|
<dt> <b>check_sender_ns_access</b> <i>maptype</i>:<i>mapname</i>
|
||||||
|
|
||||||
|
<a name="check_sender_mx_access">
|
||||||
|
|
||||||
|
<dt> <b>check_sender_mx_access</b> <i>maptype</i>:<i>mapname</i>
|
||||||
|
|
||||||
|
<dd> Apply the specified <a href="access.5.html">access database</a>
|
||||||
|
to the DNS (or MX) servers for the host or domain name given with
|
||||||
|
the MAIL FROM command.
|
||||||
|
|
||||||
|
<dd> Note: an OK result is not allowed for safety reasons.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
<a name="reject_non_fqdn_sender">
|
<a name="reject_non_fqdn_sender">
|
||||||
|
|
||||||
<dt> <b>reject_non_fqdn_sender</b> <dd> Reject the request when
|
<dt> <b>reject_non_fqdn_sender</b> <dd> Reject the request when
|
||||||
@@ -995,6 +1027,22 @@ address, recipient domain or parent domain, or <i>localpart</i>@.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
<a name="check_recipient_ns_access">
|
||||||
|
|
||||||
|
<dt> <b>check_recipient_ns_access</b> <i>maptype</i>:<i>mapname</i>
|
||||||
|
|
||||||
|
<a name="check_recipient_mx_access">
|
||||||
|
|
||||||
|
<dt> <b>check_recipient_mx_access</b> <i>maptype</i>:<i>mapname</i>
|
||||||
|
|
||||||
|
<dd> Apply the specified <a href="access.5.html">access database</a>
|
||||||
|
to the DNS servers (or MX hosts) for the host or domain name given
|
||||||
|
with the RCPT TO command.
|
||||||
|
|
||||||
|
<dd> Note: an OK result is not allowed for safety reasons.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
<a name="check_recipient_maps">
|
<a name="check_recipient_maps">
|
||||||
|
|
||||||
<dt> <b>check_recipient_maps</b> <dd> Reject the request
|
<dt> <b>check_recipient_maps</b> <dd> Reject the request
|
||||||
|
@@ -509,6 +509,7 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
|
|||||||
vstring_sprintf(why,
|
vstring_sprintf(why,
|
||||||
"Name service error for %s: invalid host or domain name",
|
"Name service error for %s: invalid host or domain name",
|
||||||
name);
|
name);
|
||||||
|
h_errno = HOST_NOT_FOUND;
|
||||||
return (DNS_NOTFOUND);
|
return (DNS_NOTFOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,6 +521,7 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
|
|||||||
vstring_sprintf(why,
|
vstring_sprintf(why,
|
||||||
"Name service error for %s: invalid host or domain name",
|
"Name service error for %s: invalid host or domain name",
|
||||||
name);
|
name);
|
||||||
|
h_errno = HOST_NOT_FOUND;
|
||||||
return (DNS_NOTFOUND);
|
return (DNS_NOTFOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1314,6 +1314,13 @@ extern int var_access_map_code;
|
|||||||
#define CHECK_RECIP_ACL "check_recipient_access"
|
#define CHECK_RECIP_ACL "check_recipient_access"
|
||||||
#define CHECK_ETRN_ACL "check_etrn_access"
|
#define CHECK_ETRN_ACL "check_etrn_access"
|
||||||
|
|
||||||
|
#define CHECK_HELO_MX_ACL "check_helo_mx_access"
|
||||||
|
#define CHECK_SENDER_MX_ACL "check_sender_mx_access"
|
||||||
|
#define CHECK_RECIP_MX_ACL "check_recipient_mx_access"
|
||||||
|
#define CHECK_HELO_NS_ACL "check_helo_ns_access"
|
||||||
|
#define CHECK_SENDER_NS_ACL "check_sender_ns_access"
|
||||||
|
#define CHECK_RECIP_NS_ACL "check_recipient_ns_access"
|
||||||
|
|
||||||
#define WARN_IF_REJECT "warn_if_reject"
|
#define WARN_IF_REJECT "warn_if_reject"
|
||||||
|
|
||||||
#define REJECT_RBL "reject_rbl" /* LaMont compatibility */
|
#define REJECT_RBL "reject_rbl" /* LaMont compatibility */
|
||||||
|
@@ -20,10 +20,10 @@
|
|||||||
* 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 "20030915"
|
#define MAIL_RELEASE_DATE "20030917"
|
||||||
|
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "2.0.14-" MAIL_RELEASE_DATE
|
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||||
extern char *var_mail_version;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -89,6 +89,18 @@
|
|||||||
/* .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 "check_helo_mx_access maptype:mapname"
|
||||||
|
/* .IP "check_sender_mx_access maptype:mapname"
|
||||||
|
/* .IP "check_recipient_mx_access maptype:mapname"
|
||||||
|
/* Apply the specified access table to the MX server host name and IP
|
||||||
|
/* addresses for the helo hostname, sender, or recipient, respectively.
|
||||||
|
/* If no MX record is found the A record is used instead.
|
||||||
|
/* .IP "check_helo_ns_access maptype:mapname"
|
||||||
|
/* .IP "check_sender_ns_access maptype:mapname"
|
||||||
|
/* .IP "check_recipient_ns_access maptype:mapname"
|
||||||
|
/* Apply the specified access table to the DNS server host name and IP
|
||||||
|
/* addresses for the helo hostname, sender, or recipient, respectively.
|
||||||
|
/* If no NS record is found, the parent domain is used instead.
|
||||||
/* .IP "check_recipient_maps"
|
/* .IP "check_recipient_maps"
|
||||||
/* Reject recipients not listed as valid local, virtual or relay
|
/* Reject recipients not listed as valid local, virtual or relay
|
||||||
/* recipients.
|
/* recipients.
|
||||||
@@ -482,6 +494,12 @@ static void PRINTFLIKE(3, 4) defer_if(SMTPD_DEFER *, int, const char *,...);
|
|||||||
else \
|
else \
|
||||||
(void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3)); \
|
(void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define DEFER_IF_PERMIT4(state, class, fmt, a1, a2, a3, a4) do { \
|
||||||
|
if ((state)->warn_if_reject == 0) \
|
||||||
|
defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \
|
||||||
|
else \
|
||||||
|
(void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3), (a4)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cached RBL lookup state.
|
* Cached RBL lookup state.
|
||||||
@@ -2153,6 +2171,127 @@ static int check_namadr_access(SMTPD_STATE *state, const char *table,
|
|||||||
return (SMTPD_CHECK_DUNNO);
|
return (SMTPD_CHECK_DUNNO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check_server_access - access control by server host name or address */
|
||||||
|
|
||||||
|
static int check_server_access(SMTPD_STATE *state, const char *table,
|
||||||
|
const char *name,
|
||||||
|
int type,
|
||||||
|
const char *reply_name,
|
||||||
|
const char *reply_class,
|
||||||
|
const char *def_acl)
|
||||||
|
{
|
||||||
|
const char *myname = "check_server_access";
|
||||||
|
const char *domain;
|
||||||
|
int dns_status;
|
||||||
|
DNS_RR *server_list;
|
||||||
|
DNS_RR *server;
|
||||||
|
int found = 0;
|
||||||
|
struct in_addr addr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *addr_string;
|
||||||
|
int status;
|
||||||
|
char **cpp;
|
||||||
|
static DNS_FIXED fixed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity check.
|
||||||
|
*/
|
||||||
|
if (type != T_MX && type != T_NS)
|
||||||
|
msg_panic("%s: unexpected resource type \"%s\" in request",
|
||||||
|
myname, dns_strtype(type));
|
||||||
|
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: %s %s", myname, dns_strtype(type), name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip over local-part.
|
||||||
|
*/
|
||||||
|
if ((domain = strrchr(name, '@')) != 0)
|
||||||
|
domain += 1;
|
||||||
|
else
|
||||||
|
domain = name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the domain does not exist then we apply no restriction. In all
|
||||||
|
* other cases, DNS lookup failure results in a "try again" status.
|
||||||
|
*
|
||||||
|
* If the domain name exists but MX lookup fails, fabricate an MX record
|
||||||
|
* that points to the domain name itself.
|
||||||
|
*
|
||||||
|
* If the domain name exists but NS lookup fails, look up the parent domain
|
||||||
|
* NS record.
|
||||||
|
*/
|
||||||
|
dns_status = dns_lookup(domain, type, 0, &server_list,
|
||||||
|
(VSTRING *) 0, (VSTRING *) 0);
|
||||||
|
if (dns_status == DNS_NOTFOUND && h_errno != HOST_NOT_FOUND) {
|
||||||
|
if (type == T_MX) {
|
||||||
|
server_list = dns_rr_create(domain, &fixed, 0,
|
||||||
|
domain, strlen(domain) + 1);
|
||||||
|
dns_status = DNS_OK;
|
||||||
|
} else if (type == T_NS && (domain = strchr(domain, '.')) != 0
|
||||||
|
&& strchr(++domain, '.') != 0) {
|
||||||
|
dns_status = dns_lookup(domain, T_NS, 0, &server_list,
|
||||||
|
(VSTRING *) 0, (VSTRING *) 0);
|
||||||
|
if (dns_status != DNS_OK)
|
||||||
|
dns_status = DNS_RETRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dns_status == DNS_NOTFOUND)
|
||||||
|
return (SMTPD_CHECK_DUNNO);
|
||||||
|
if (dns_status != DNS_OK) {
|
||||||
|
DEFER_IF_PERMIT3(state, MAIL_ERROR_POLICY,
|
||||||
|
"450 <%s>: %s rejected: unable to look up %s host",
|
||||||
|
reply_name, reply_class, dns_strtype(type));
|
||||||
|
return (SMTPD_CHECK_DUNNO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No bare returns after this point or we have a memory leak.
|
||||||
|
*/
|
||||||
|
#define CHECK_SERVER_RETURN(x) { dns_rr_free(server_list); return(x); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the hostnames first, then the addresses.
|
||||||
|
*/
|
||||||
|
for (server = server_list; server != 0; server = server->next) {
|
||||||
|
if ((hp = gethostbyname((char *) server->data)) == 0) {
|
||||||
|
DEFER_IF_PERMIT4(state, MAIL_ERROR_POLICY,
|
||||||
|
"450 <%s>: %s rejected: "
|
||||||
|
"Unable to look up %s host %s",
|
||||||
|
reply_name, reply_class,
|
||||||
|
dns_strtype(type), (char *) server->data);
|
||||||
|
CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
|
||||||
|
}
|
||||||
|
if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_warn("address type %d length %d for %s",
|
||||||
|
hp->h_addrtype, hp->h_length, (char *) server->data);
|
||||||
|
continue; /* XXX */
|
||||||
|
}
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: %s hostname check: %s",
|
||||||
|
myname, dns_strtype(type), (char *) server->data);
|
||||||
|
if ((status = check_domain_access(state, table, (char *) server->data,
|
||||||
|
FULL, &found, reply_name, reply_class,
|
||||||
|
def_acl)) != 0 || found)
|
||||||
|
CHECK_SERVER_RETURN(status);
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: %s host address check: %s",
|
||||||
|
myname, dns_strtype(type), (char *) server->data);
|
||||||
|
for (cpp = hp->h_addr_list; *cpp; cpp++) {
|
||||||
|
memcpy((char *) &addr, *cpp, sizeof(addr));
|
||||||
|
addr_string = mystrdup(inet_ntoa(addr));
|
||||||
|
status = check_addr_access(state, table, addr_string, FULL,
|
||||||
|
&found, reply_name, reply_class,
|
||||||
|
def_acl);
|
||||||
|
myfree(addr_string);
|
||||||
|
if (status != 0 || found)
|
||||||
|
CHECK_SERVER_RETURN(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
|
||||||
|
}
|
||||||
|
|
||||||
/* check_mail_access - OK/FAIL based on mail address lookup */
|
/* check_mail_access - OK/FAIL based on mail address lookup */
|
||||||
|
|
||||||
static int check_mail_access(SMTPD_STATE *state, const char *table,
|
static int check_mail_access(SMTPD_STATE *state, const char *table,
|
||||||
@@ -2818,6 +2957,20 @@ static int is_map_command(SMTPD_STATE *state, const char *name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* forbid_whitelist - disallow whitelisting */
|
||||||
|
|
||||||
|
static void forbid_whitelist(SMTPD_STATE *state, const char *name,
|
||||||
|
int status, const char *target)
|
||||||
|
{
|
||||||
|
if (status == SMTPD_CHECK_OK) {
|
||||||
|
msg_warn("restriction %s returns OK for %s", name, target);
|
||||||
|
msg_warn("this is not allowed for security reasons");
|
||||||
|
msg_warn("use DUNNO instead of OK if you want to make an exception");
|
||||||
|
longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_SOFTWARE,
|
||||||
|
"451 Server configuration error"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* generic_checks - generic restrictions */
|
/* generic_checks - generic restrictions */
|
||||||
|
|
||||||
static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||||
@@ -2979,6 +3132,20 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
|||||||
state->helo_name, SMTPD_NAME_HELO)) == 0)
|
state->helo_name, SMTPD_NAME_HELO)) == 0)
|
||||||
status = SMTPD_CHECK_OK;
|
status = SMTPD_CHECK_OK;
|
||||||
}
|
}
|
||||||
|
} else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
|
||||||
|
if (state->helo_name) {
|
||||||
|
status = check_server_access(state, *cpp, state->helo_name,
|
||||||
|
T_NS, state->helo_name,
|
||||||
|
SMTPD_NAME_HELO, def_acl);
|
||||||
|
forbid_whitelist(state, name, status, state->helo_name);
|
||||||
|
}
|
||||||
|
} else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) {
|
||||||
|
if (state->helo_name) {
|
||||||
|
status = check_server_access(state, *cpp, state->helo_name,
|
||||||
|
T_MX, state->helo_name,
|
||||||
|
SMTPD_NAME_HELO, def_acl);
|
||||||
|
forbid_whitelist(state, name, status, state->helo_name);
|
||||||
|
}
|
||||||
} else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
|
} else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
|
||||||
if (state->helo_name) {
|
if (state->helo_name) {
|
||||||
if (*state->helo_name != '[')
|
if (*state->helo_name != '[')
|
||||||
@@ -3032,6 +3199,20 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
|||||||
} else if (strcasecmp(name, REJECT_SENDER_LOGIN_MISMATCH) == 0) {
|
} else if (strcasecmp(name, REJECT_SENDER_LOGIN_MISMATCH) == 0) {
|
||||||
if (state->sender && *state->sender)
|
if (state->sender && *state->sender)
|
||||||
status = reject_sender_login_mismatch(state, state->sender);
|
status = reject_sender_login_mismatch(state, state->sender);
|
||||||
|
} else if (is_map_command(state, name, CHECK_SENDER_NS_ACL, &cpp)) {
|
||||||
|
if (state->sender && *state->sender) {
|
||||||
|
status = check_server_access(state, *cpp, state->sender,
|
||||||
|
T_NS, state->sender,
|
||||||
|
SMTPD_NAME_SENDER, def_acl);
|
||||||
|
forbid_whitelist(state, name, status, state->sender);
|
||||||
|
}
|
||||||
|
} else if (is_map_command(state, name, CHECK_SENDER_MX_ACL, &cpp)) {
|
||||||
|
if (state->sender && *state->sender) {
|
||||||
|
status = check_server_access(state, *cpp, state->sender,
|
||||||
|
T_MX, state->sender,
|
||||||
|
SMTPD_NAME_SENDER, def_acl);
|
||||||
|
forbid_whitelist(state, name, status, state->sender);
|
||||||
|
}
|
||||||
} else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) {
|
} else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) {
|
||||||
if (cpp[1] == 0)
|
if (cpp[1] == 0)
|
||||||
msg_warn("restriction %s requires domain name argument", name);
|
msg_warn("restriction %s requires domain name argument", name);
|
||||||
@@ -3084,6 +3265,20 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
|||||||
if (state->recipient)
|
if (state->recipient)
|
||||||
status = reject_non_fqdn_address(state, state->recipient,
|
status = reject_non_fqdn_address(state, state->recipient,
|
||||||
state->recipient, SMTPD_NAME_RECIPIENT);
|
state->recipient, SMTPD_NAME_RECIPIENT);
|
||||||
|
} else if (is_map_command(state, name, CHECK_RECIP_NS_ACL, &cpp)) {
|
||||||
|
if (state->recipient && *state->recipient) {
|
||||||
|
status = check_server_access(state, *cpp, state->recipient,
|
||||||
|
T_NS, state->recipient,
|
||||||
|
SMTPD_NAME_RECIPIENT, def_acl);
|
||||||
|
forbid_whitelist(state, name, status, state->recipient);
|
||||||
|
}
|
||||||
|
} else if (is_map_command(state, name, CHECK_RECIP_MX_ACL, &cpp)) {
|
||||||
|
if (state->recipient && *state->recipient) {
|
||||||
|
status = check_server_access(state, *cpp, state->recipient,
|
||||||
|
T_MX, state->recipient,
|
||||||
|
SMTPD_NAME_RECIPIENT, def_acl);
|
||||||
|
forbid_whitelist(state, name, status, state->recipient);
|
||||||
|
}
|
||||||
} else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) {
|
} else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) {
|
||||||
if (cpp[1] == 0)
|
if (cpp[1] == 0)
|
||||||
msg_warn("restriction %s requires domain name argument", name);
|
msg_warn("restriction %s requires domain name argument", name);
|
||||||
|
@@ -56,3 +56,5 @@ holdtext@hold.domain hold text
|
|||||||
discard@hold.domain discard
|
discard@hold.domain discard
|
||||||
discardtext@hold.domain discard text
|
discardtext@hold.domain discard text
|
||||||
dunnotext@dunno.domain dunno text
|
dunnotext@dunno.domain dunno text
|
||||||
|
64.94.110.11 reject Verisign wild-card
|
||||||
|
topica.com reject
|
||||||
|
@@ -60,3 +60,32 @@ recipient_restrictions reject_rhsbl_helo,abuse.rfc-ignorant.org
|
|||||||
helo example.tld
|
helo example.tld
|
||||||
mail sname@sdomain
|
mail sname@sdomain
|
||||||
rcpt rname@rdomain
|
rcpt rname@rdomain
|
||||||
|
#
|
||||||
|
# Check MX access
|
||||||
|
#
|
||||||
|
helo_restrictions check_helo_mx_access,hash:smtpd_check_access
|
||||||
|
helo verisign-wildcard.com
|
||||||
|
helo verisign.com
|
||||||
|
helo example.tld
|
||||||
|
sender_restrictions check_sender_mx_access,hash:smtpd_check_access
|
||||||
|
mail foo@verisign-wildcard.com
|
||||||
|
mail foo@verisign.com
|
||||||
|
recipient_restrictions check_recipient_mx_access,hash:smtpd_check_access
|
||||||
|
rcpt foo@verisign-wildcard.com
|
||||||
|
rcpt foo@verisign.com
|
||||||
|
#
|
||||||
|
# Check NS access
|
||||||
|
#
|
||||||
|
helo_restrictions check_helo_ns_access,hash:smtpd_check_access
|
||||||
|
helo email-publisher.com
|
||||||
|
helo ns1.topica.com
|
||||||
|
helo verisign-wildcard.com
|
||||||
|
helo example.tld
|
||||||
|
sender_restrictions check_sender_ns_access,hash:smtpd_check_access
|
||||||
|
mail foo@email-publisher.com
|
||||||
|
mail foo@ns1.topica.com
|
||||||
|
mail foo@verisign-wildcard.com
|
||||||
|
recipient_restrictions check_recipient_ns_access,hash:smtpd_check_access
|
||||||
|
rcpt foo@email-publisher.com
|
||||||
|
rcpt foo@ns1.topica.com
|
||||||
|
rcpt foo@verisign-wildcard.com
|
||||||
|
@@ -109,3 +109,64 @@ OK
|
|||||||
>>> rcpt rname@rdomain
|
>>> rcpt rname@rdomain
|
||||||
./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
|
./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
|
||||||
554 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain
|
554 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain
|
||||||
|
>>> #
|
||||||
|
>>> # Check MX access
|
||||||
|
>>> #
|
||||||
|
>>> helo_restrictions check_helo_mx_access,hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> helo verisign-wildcard.com
|
||||||
|
./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.189.2]: 554 <verisign-wildcard.com>: Helo command rejected: Verisign wild-card; from=<sname@sdomain> proto=SMTP helo=<verisign-wildcard.com>
|
||||||
|
554 <verisign-wildcard.com>: Helo command rejected: Verisign wild-card
|
||||||
|
>>> helo verisign.com
|
||||||
|
OK
|
||||||
|
>>> helo example.tld
|
||||||
|
OK
|
||||||
|
>>> sender_restrictions check_sender_mx_access,hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> mail foo@verisign-wildcard.com
|
||||||
|
./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.189.2]: 554 <foo@verisign-wildcard.com>: Sender address rejected: Verisign wild-card; from=<foo@verisign-wildcard.com> proto=SMTP helo=<example.tld>
|
||||||
|
554 <foo@verisign-wildcard.com>: Sender address rejected: Verisign wild-card
|
||||||
|
>>> mail foo@verisign.com
|
||||||
|
OK
|
||||||
|
>>> recipient_restrictions check_recipient_mx_access,hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> rcpt foo@verisign-wildcard.com
|
||||||
|
./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 <foo@verisign-wildcard.com>: Recipient address rejected: Verisign wild-card; from=<foo@verisign.com> to=<foo@verisign-wildcard.com> proto=SMTP helo=<example.tld>
|
||||||
|
554 <foo@verisign-wildcard.com>: Recipient address rejected: Verisign wild-card
|
||||||
|
>>> rcpt foo@verisign.com
|
||||||
|
OK
|
||||||
|
>>> #
|
||||||
|
>>> # Check NS access
|
||||||
|
>>> #
|
||||||
|
>>> helo_restrictions check_helo_ns_access,hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> helo email-publisher.com
|
||||||
|
./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.189.2]: 554 <email-publisher.com>: Helo command rejected: Access denied; from=<foo@verisign.com> proto=SMTP helo=<email-publisher.com>
|
||||||
|
554 <email-publisher.com>: Helo command rejected: Access denied
|
||||||
|
>>> helo ns1.topica.com
|
||||||
|
./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.189.2]: 554 <ns1.topica.com>: Helo command rejected: Access denied; from=<foo@verisign.com> proto=SMTP helo=<ns1.topica.com>
|
||||||
|
554 <ns1.topica.com>: Helo command rejected: Access denied
|
||||||
|
>>> helo verisign-wildcard.com
|
||||||
|
OK
|
||||||
|
>>> helo example.tld
|
||||||
|
OK
|
||||||
|
>>> sender_restrictions check_sender_ns_access,hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> mail foo@email-publisher.com
|
||||||
|
./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.189.2]: 554 <foo@email-publisher.com>: Sender address rejected: Access denied; from=<foo@email-publisher.com> proto=SMTP helo=<example.tld>
|
||||||
|
554 <foo@email-publisher.com>: Sender address rejected: Access denied
|
||||||
|
>>> mail foo@ns1.topica.com
|
||||||
|
./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.189.2]: 554 <foo@ns1.topica.com>: Sender address rejected: Access denied; from=<foo@ns1.topica.com> proto=SMTP helo=<example.tld>
|
||||||
|
554 <foo@ns1.topica.com>: Sender address rejected: Access denied
|
||||||
|
>>> mail foo@verisign-wildcard.com
|
||||||
|
OK
|
||||||
|
>>> recipient_restrictions check_recipient_ns_access,hash:smtpd_check_access
|
||||||
|
OK
|
||||||
|
>>> rcpt foo@email-publisher.com
|
||||||
|
./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 <foo@email-publisher.com>: Recipient address rejected: Access denied; from=<foo@verisign-wildcard.com> to=<foo@email-publisher.com> proto=SMTP helo=<example.tld>
|
||||||
|
554 <foo@email-publisher.com>: Recipient address rejected: Access denied
|
||||||
|
>>> rcpt foo@ns1.topica.com
|
||||||
|
./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 <foo@ns1.topica.com>: Recipient address rejected: Access denied; from=<foo@verisign-wildcard.com> to=<foo@ns1.topica.com> proto=SMTP helo=<example.tld>
|
||||||
|
554 <foo@ns1.topica.com>: Recipient address rejected: Access denied
|
||||||
|
>>> rcpt foo@verisign-wildcard.com
|
||||||
|
OK
|
||||||
|
@@ -409,9 +409,11 @@ static void resolve_addr(RES_CONTEXT *rp, char *addr,
|
|||||||
msg_warn("do not list domain %s in BOTH %s and %s",
|
msg_warn("do not list domain %s in BOTH %s and %s",
|
||||||
rcpt_domain, VAR_VIRT_ALIAS_DOMS,
|
rcpt_domain, VAR_VIRT_ALIAS_DOMS,
|
||||||
VAR_RELAY_DOMAINS);
|
VAR_RELAY_DOMAINS);
|
||||||
|
#if 0
|
||||||
if (strcasecmp(rcpt_domain, var_myorigin) == 0)
|
if (strcasecmp(rcpt_domain, var_myorigin) == 0)
|
||||||
msg_warn("do not list $%s (%s) in %s",
|
msg_warn("do not list $%s (%s) in %s",
|
||||||
VAR_MYORIGIN, var_myorigin, VAR_VIRT_ALIAS_DOMS);
|
VAR_MYORIGIN, var_myorigin, VAR_VIRT_ALIAS_DOMS);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
vstring_strcpy(channel, MAIL_SERVICE_ERROR);
|
vstring_strcpy(channel, MAIL_SERVICE_ERROR);
|
||||||
vstring_sprintf(nexthop, "User unknown%s",
|
vstring_sprintf(nexthop, "User unknown%s",
|
||||||
|
@@ -180,11 +180,17 @@
|
|||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
#include "dict_ldap.h"
|
#include "dict_ldap.h"
|
||||||
#include "stringops.h"
|
#include "stringops.h"
|
||||||
|
#include "binhash.h"
|
||||||
|
|
||||||
/* AAARGH!! */
|
/* AAARGH!! */
|
||||||
|
|
||||||
#include "../global/mail_conf.h"
|
#include "../global/mail_conf.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LDAP *conn_ld;
|
||||||
|
int conn_refcount;
|
||||||
|
} LDAP_CONN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure containing all the configuration parameters for a given
|
* Structure containing all the configuration parameters for a given
|
||||||
* LDAP source, plus its connection handle.
|
* LDAP source, plus its connection handle.
|
||||||
@@ -223,9 +229,14 @@ typedef struct {
|
|||||||
char *tls_random_file;
|
char *tls_random_file;
|
||||||
char *tls_cipher_suite;
|
char *tls_cipher_suite;
|
||||||
#endif
|
#endif
|
||||||
LDAP *ld;
|
BINHASH_INFO *ht; /* hash entry for LDAP connection */
|
||||||
|
LDAP *ld; /* duplicated from conn->conn_ld */
|
||||||
} DICT_LDAP;
|
} DICT_LDAP;
|
||||||
|
|
||||||
|
#define DICT_LDAP_CONN(d) ((LDAP_CONN *)((d)->ht->value))
|
||||||
|
|
||||||
|
static BINHASH *conn_hash = 0;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *(*get_str) (const char *, const char *, const char *, int, int);
|
char *(*get_str) (const char *, const char *, const char *, int, int);
|
||||||
int (*get_int) (const char *, const char *, int, int, int);
|
int (*get_int) (const char *, const char *, int, int, int);
|
||||||
@@ -641,6 +652,9 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
|||||||
msg_info("%s: Successful bind to server %s as %s ",
|
msg_info("%s: Successful bind to server %s as %s ",
|
||||||
myname, dict_ldap->server_host, dict_ldap->bind_dn);
|
myname, dict_ldap->server_host, dict_ldap->bind_dn);
|
||||||
}
|
}
|
||||||
|
/* Save connection handle in shared container */
|
||||||
|
DICT_LDAP_CONN(dict_ldap)->conn_ld = dict_ldap->ld;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: Cached connection handle for LDAP source %s",
|
msg_info("%s: Cached connection handle for LDAP source %s",
|
||||||
myname, dict_ldap->ldapsource);
|
myname, dict_ldap->ldapsource);
|
||||||
@@ -648,6 +662,58 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locate or allocate connection cache entry.
|
||||||
|
*/
|
||||||
|
static void dict_ldap_conn_find(DICT_LDAP *dict_ldap)
|
||||||
|
{
|
||||||
|
VSTRING *keybuf = vstring_alloc(10);
|
||||||
|
char *key;
|
||||||
|
int len;
|
||||||
|
int sslon = dict_ldap->start_tls || dict_ldap->ldap_ssl;
|
||||||
|
LDAP_CONN *conn;
|
||||||
|
|
||||||
|
#define ADDSTR(vp, s) vstring_memcat((vp), (s), strlen((s))+1)
|
||||||
|
#define ADDINT(vp, i) vstring_sprintf_append((vp), "%lu", (unsigned long)(i))
|
||||||
|
|
||||||
|
ADDSTR(keybuf, dict_ldap->server_host);
|
||||||
|
ADDINT(keybuf, dict_ldap->server_port);
|
||||||
|
ADDINT(keybuf, dict_ldap->bind);
|
||||||
|
ADDSTR(keybuf, dict_ldap->bind ? dict_ldap->bind_dn : "");
|
||||||
|
ADDSTR(keybuf, dict_ldap->bind ? dict_ldap->bind_pw : "");
|
||||||
|
ADDINT(keybuf, dict_ldap->dereference);
|
||||||
|
ADDINT(keybuf, dict_ldap->chase_referrals);
|
||||||
|
ADDINT(keybuf, dict_ldap->debuglevel);
|
||||||
|
ADDINT(keybuf, dict_ldap->version);
|
||||||
|
#ifdef LDAP_API_FEATURE_X_OPENLDAP
|
||||||
|
ADDINT(keybuf, dict_ldap->ldap_ssl);
|
||||||
|
ADDINT(keybuf, dict_ldap->start_tls);
|
||||||
|
ADDINT(keybuf, sslon ? dict_ldap->tls_require_cert : 0);
|
||||||
|
ADDSTR(keybuf, sslon ? dict_ldap->tls_ca_cert_file : "");
|
||||||
|
ADDSTR(keybuf, sslon ? dict_ldap->tls_ca_cert_dir : "");
|
||||||
|
ADDSTR(keybuf, sslon ? dict_ldap->tls_cert : "");
|
||||||
|
ADDSTR(keybuf, sslon ? dict_ldap->tls_key : "");
|
||||||
|
ADDSTR(keybuf, sslon ? dict_ldap->tls_random_file : "");
|
||||||
|
ADDSTR(keybuf, sslon ? dict_ldap->tls_cipher_suite : "");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
key = vstring_str(keybuf);
|
||||||
|
len = VSTRING_LEN(keybuf);
|
||||||
|
|
||||||
|
if (conn_hash == 0)
|
||||||
|
conn_hash = binhash_create(0);
|
||||||
|
|
||||||
|
if ((dict_ldap->ht = binhash_locate(conn_hash, key, len)) == 0) {
|
||||||
|
conn = (LDAP_CONN *) mymalloc(sizeof(LDAP_CONN));
|
||||||
|
conn->conn_ld = 0;
|
||||||
|
conn->conn_refcount = 0;
|
||||||
|
dict_ldap->ht = binhash_enter(conn_hash, key, len, (char *) conn);
|
||||||
|
}
|
||||||
|
++DICT_LDAP_CONN(dict_ldap)->conn_refcount;
|
||||||
|
|
||||||
|
vstring_free(keybuf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* expand a filter (lookup or result)
|
* expand a filter (lookup or result)
|
||||||
*/
|
*/
|
||||||
@@ -907,6 +973,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||||||
VSTRING *escaped_name = 0,
|
VSTRING *escaped_name = 0,
|
||||||
*filter_buf = 0;
|
*filter_buf = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
int sizelimit;
|
||||||
char *sub,
|
char *sub,
|
||||||
*end;
|
*end;
|
||||||
|
|
||||||
@@ -923,11 +990,8 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||||||
if (dict_ldap->domain) {
|
if (dict_ldap->domain) {
|
||||||
const char *p = strrchr(name, '@');
|
const char *p = strrchr(name, '@');
|
||||||
|
|
||||||
if (p != 0)
|
if (p == 0 || p == name ||
|
||||||
p = p + 1;
|
match_list_match(dict_ldap->domain, ++p) == 0) {
|
||||||
else
|
|
||||||
p = name;
|
|
||||||
if (match_list_match(dict_ldap->domain, p) == 0) {
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: domain of %s not found in domain list", myname,
|
msg_info("%s: domain of %s not found in domain list", myname,
|
||||||
name);
|
name);
|
||||||
@@ -942,6 +1006,13 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||||||
result = vstring_alloc(2);
|
result = vstring_alloc(2);
|
||||||
vstring_strcpy(result, "");
|
vstring_strcpy(result, "");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because the connection may be shared and invalidated via queries for
|
||||||
|
* another map, update private copy of "ld" from shared connection
|
||||||
|
* container.
|
||||||
|
*/
|
||||||
|
dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect to the LDAP server, if necessary.
|
* Connect to the LDAP server, if necessary.
|
||||||
*/
|
*/
|
||||||
@@ -962,6 +1033,18 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||||||
msg_info("%s: Using existing connection for LDAP source %s",
|
msg_info("%s: Using existing connection for LDAP source %s",
|
||||||
myname, dict_ldap->ldapsource);
|
myname, dict_ldap->ldapsource);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connection caching, means that the connection handle may have the
|
||||||
|
* wrong size limit. Re-adjust before each query. This is cheap, just
|
||||||
|
* sets a field in the ldap connection handle. We also do this in the
|
||||||
|
* connect code, because we sometimes reconnect (below) in the middle of
|
||||||
|
* a query.
|
||||||
|
*/
|
||||||
|
sizelimit = dict_ldap->size_limit ? dict_ldap->size_limit : LDAP_NO_LIMIT;
|
||||||
|
if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT, &sizelimit)
|
||||||
|
!= LDAP_OPT_SUCCESS)
|
||||||
|
msg_warn("%s: %s: Unable to set query result size limit to %ld.",
|
||||||
|
myname, dict_ldap->ldapsource, dict_ldap->size_limit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the query.
|
* Prepare the query.
|
||||||
@@ -1046,7 +1129,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||||||
myname, dict_ldap->ldapsource);
|
myname, dict_ldap->ldapsource);
|
||||||
|
|
||||||
ldap_unbind(dict_ldap->ld);
|
ldap_unbind(dict_ldap->ld);
|
||||||
dict_ldap->ld = NULL;
|
dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0;
|
||||||
dict_ldap_connect(dict_ldap);
|
dict_ldap_connect(dict_ldap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1098,7 +1181,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||||||
* next lookup.
|
* next lookup.
|
||||||
*/
|
*/
|
||||||
ldap_unbind(dict_ldap->ld);
|
ldap_unbind(dict_ldap->ld);
|
||||||
dict_ldap->ld = NULL;
|
dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And tell the caller to try again later.
|
* And tell the caller to try again later.
|
||||||
@@ -1129,10 +1212,18 @@ static void dict_ldap_close(DICT *dict)
|
|||||||
{
|
{
|
||||||
char *myname = "dict_ldap_close";
|
char *myname = "dict_ldap_close";
|
||||||
DICT_LDAP *dict_ldap = (DICT_LDAP *) dict;
|
DICT_LDAP *dict_ldap = (DICT_LDAP *) dict;
|
||||||
|
LDAP_CONN *conn = DICT_LDAP_CONN(dict_ldap);
|
||||||
|
BINHASH_INFO *ht = dict_ldap->ht;
|
||||||
|
|
||||||
if (dict_ldap->ld)
|
if (--conn->conn_refcount == 0) {
|
||||||
ldap_unbind(dict_ldap->ld);
|
if (conn->conn_ld) {
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: Closed connection handle for LDAP source %s",
|
||||||
|
myname, dict_ldap->ldapsource);
|
||||||
|
ldap_unbind(conn->conn_ld);
|
||||||
|
}
|
||||||
|
binhash_delete(conn_hash, ht->key, ht->key_len, myfree);
|
||||||
|
}
|
||||||
myfree(dict_ldap->ldapsource);
|
myfree(dict_ldap->ldapsource);
|
||||||
myfree(dict_ldap->server_host);
|
myfree(dict_ldap->server_host);
|
||||||
myfree(dict_ldap->search_base);
|
myfree(dict_ldap->search_base);
|
||||||
@@ -1272,6 +1363,11 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dict_ldap->server_host = mystrdup(vstring_str(url_list) + 1);
|
dict_ldap->server_host = mystrdup(vstring_str(url_list) + 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With URL scheme, clear port to normalize connection cache key
|
||||||
|
*/
|
||||||
|
dict_ldap->server_port = 0;
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s server_host URL is %s", myname, ldapsource,
|
msg_info("%s: %s server_host URL is %s", myname, ldapsource,
|
||||||
dict_ldap->server_host);
|
dict_ldap->server_host);
|
||||||
@@ -1534,6 +1630,11 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
|
|||||||
dict_ldap->debuglevel);
|
dict_ldap->debuglevel);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find or allocate shared LDAP connection container.
|
||||||
|
*/
|
||||||
|
dict_ldap_conn_find(dict_ldap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the new dict_ldap structure.
|
* Return the new dict_ldap structure.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user