Prereq: "Postfix-20010228-pl03"
diff -cr --new-file ../postfix-20010228-pl03/src/global/mail_version.h ./src/global/mail_version.h
*** ../postfix-20010228-pl03/src/global/mail_version.h Tue May 1 12:58:10 2001
--- ./src/global/mail_version.h Tue Jul 31 14:47:45 2001
***************
*** 15,21 ****
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
! #define DEF_MAIL_VERSION "Postfix-20010228-pl03"
extern char *var_mail_version;
/* LICENSE
--- 15,21 ----
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
! #define DEF_MAIL_VERSION "Postfix-20010228-pl04"
extern char *var_mail_version;
/* LICENSE
diff -cr --new-file ../postfix-20010228-pl03/HISTORY ./HISTORY
*** ../postfix-20010228-pl03/HISTORY Sat May 26 19:03:33 2001
--- ./HISTORY Tue Jul 31 17:13:42 2001
***************
*** 5063,5065 ****
--- 5063,5098 ----
sending QUIT after process idle timeout while the LMTP
server had disconnected. Files: smtp/smtp_proto.c,
lmtp/lmtp_proto.c.
+
+ 20010727
+
+ Bugfix: updated LDAP client module from LaMont Jones, HP.
+ This also introduces new LDAP query filter patterns: %u
+ (address localpart) and %d (domain part). Files:
+ conf/sample-ldap.cf, util/dict_ldap.c.
+
+ 20010729
+
+ Bugfix: recursive smtpd_whatever_restrictions clobbered
+ intermediate results when switching between sender and
+ recipient address restrictions. Problem found by Victor
+ Duchovni, morganstanley.com. In order to fix, introduced
+ address resolver result caching, which should also help to
+ speed up sender/recipient address restriction processing.
+
+ Bugfix: the not yet announced DUNNO access table lookup
+ result did not prevent lookups with substrings of the same
+ lookup key. Found by Victor Duchovni, morganstanley.com.
+
+ 20010730
+
+ Robustness: trim trailing whitespace from regexp and pcre
+ right-hand sides, for consistency with DB/DBM tables.
+ Files: util/dict_pcre.c, util/dict_regexp.c.
+
+ 20010731
+
+ Robustness: eliminate duplicate IP addresses after expansion
+ of hostnames in $inet_interfaces, so that Postfix does not
+ suddenly refuse to start up after someone changes the DNS.
+ Files: util/inet_addr_list.c global/own_inet_addr.c.
diff -cr --new-file ../postfix-20010228-pl03/MYSQL_README ./MYSQL_README
*** ../postfix-20010228-pl03/MYSQL_README Thu Mar 29 13:57:38 2001
--- ./MYSQL_README Sun Jul 29 09:48:29 2001
***************
*** 12,20 ****
make -f Makefile.init makefiles \
'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \
! 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lm'
! then, just run 'make'.
Postfix installations which may benefit from using mysql map types
include sites that have a need for instantaneous updates of
--- 12,21 ----
make -f Makefile.init makefiles \
'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \
! 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lz -lm'
! then, just run 'make'. This requires libz, the compression library.
! Older mysql implementations build without libz.
Postfix installations which may benefit from using mysql map types
include sites that have a need for instantaneous updates of
diff -cr --new-file ../postfix-20010228-pl03/conf/sample-ldap.cf ./conf/sample-ldap.cf
*** ../postfix-20010228-pl03/conf/sample-ldap.cf Mon May 21 20:04:52 2001
--- ./conf/sample-ldap.cf Fri Jul 20 13:07:50 2001
***************
*** 23,28 ****
--- 23,35 ----
#ldap_server_port = 389
# The ldap_query_filter parameter specifies the filter used for queries.
+ # The replacement for "%s" is the address input into the map; e.g.
+ # for alias maps, the "user" part (the RFC 2822 local-part) of
+ # "user@domain.com" for To: addresses destined for local delivery
+ # (those matching $mydestination or a virtual domain), and all of
+ # "user@domain.com" (the RFC 2822 addr-spec) for other addresses.
+ # "%u" provides just the user portion of the input, and "%d" provides
+ # just the hostname.
#
#ldap_query_filter = (mailacceptinggeneralid=%s)
***************
*** 30,35 ****
--- 37,49 ----
# the search.
#
#ldap_result_attribute = maildrop
+
+ # The ldap_special_result_attribute lists the attribute(s) of an
+ # entry which contain links, either ldap url's or distinguished names.
+ # The entries referenced by these links are (recursively) treated as if
+ # they were contained in the referencing entity.
+ #
+ # ldap_special_result_attribute =
# The ldap_scope parameter specifies the LDAP search scope: sub, base, or one.
#
diff -cr --new-file ../postfix-20010228-pl03/html/faq.html ./html/faq.html
*** ../postfix-20010228-pl03/html/faq.html Sat May 19 11:08:25 2001
--- ./html/faq.html Tue Jun 12 07:19:44 2001
***************
*** 1027,1033 ****
! sendmail has set-uid root file permissions, or is run from a
set-uid root process
Traditionally, the UNIX sendmail command is installed with
--- 1027,1033 ----
! sendmail has set-uid root file permissions, or is run from a
set-uid root process
Traditionally, the UNIX sendmail command is installed with
diff -cr --new-file ../postfix-20010228-pl03/src/global/own_inet_addr.c ./src/global/own_inet_addr.c
*** ../postfix-20010228-pl03/src/global/own_inet_addr.c Sat Feb 24 20:51:39 2001
--- ./src/global/own_inet_addr.c Tue Jul 31 14:38:29 2001
***************
*** 107,112 ****
--- 107,120 ----
VAR_INET_INTERFACES, host);
myfree(hosts);
+ /*
+ * Weed out duplicate IP addresses. Duplicates happen when the same
+ * IP address is listed under multiple hostnames. If we don't weed
+ * out duplicates, Postfix can suddenly stop working after the DNS is
+ * changed.
+ */
+ inet_addr_list_uniq(addr_list);
+
inet_addr_list_init(&local_addrs);
inet_addr_list_init(&local_masks);
if (inet_addr_local(&local_addrs, &local_masks) == 0)
diff -cr --new-file ../postfix-20010228-pl03/src/smtp/smtp_connect.c ./src/smtp/smtp_connect.c
*** ../postfix-20010228-pl03/src/smtp/smtp_connect.c Sat Jan 20 18:36:00 2001
--- ./src/smtp/smtp_connect.c Sun Jul 8 15:41:03 2001
***************
*** 394,400 ****
char *save;
char *dest;
char *cp;
! int found_myself;
/*
* First try to deliver to the indicated destination, then try to deliver
--- 394,400 ----
char *save;
char *dest;
char *cp;
! int found_myself = 0;
/*
* First try to deliver to the indicated destination, then try to deliver
diff -cr --new-file ../postfix-20010228-pl03/src/smtpd/Makefile.in ./src/smtpd/Makefile.in
*** ../postfix-20010228-pl03/src/smtpd/Makefile.in Fri Apr 27 15:16:03 2001
--- ./src/smtpd/Makefile.in Tue Jul 31 10:43:31 2001
***************
*** 67,73 ****
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
! tests: smtpd_check_test smtpd_check_test2 smtpd_token_test
smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref
../postmap/postmap smtpd_check_access
--- 67,73 ----
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
@$(EXPORT) make -f Makefile.in Makefile 1>&2
! tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_token_test
smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref
../postmap/postmap smtpd_check_access
***************
*** 81,86 ****
--- 81,92 ----
diff smtpd_check.ref2 smtpd_check.tmp
rm -f smtpd_check.tmp smtpd_check_access.*
+ smtpd_acl_test: smtpd_check smtpd_acl.in smtpd_acl.ref
+ ../postmap/postmap smtpd_check_access
+ ./smtpd_check smtpd_check.tmp 2>&1
+ diff smtpd_acl.ref smtpd_check.tmp
+ rm -f smtpd_check.tmp smtpd_check_access.*
+
smtpd_token_test: smtpd_token smtpd_token.in smtpd_token.ref
./smtpd_token smtpd_token.tmp 2>&1
diff smtpd_token.ref smtpd_token.tmp
***************
*** 164,169 ****
--- 170,176 ----
smtpd_check.o: ../../include/dict.h
smtpd_check.o: ../../include/vstream.h
smtpd_check.o: ../../include/htable.h
+ smtpd_check.o: ../../include/ctable.h
smtpd_check.o: ../../include/dns.h
smtpd_check.o: ../../include/namadr_list.h
smtpd_check.o: ../../include/domain_list.h
diff -cr --new-file ../postfix-20010228-pl03/src/smtpd/smtpd_acl.in ./src/smtpd/smtpd_acl.in
*** ../postfix-20010228-pl03/src/smtpd/smtpd_acl.in Wed Dec 31 19:00:00 1969
--- ./src/smtpd/smtpd_acl.in Mon Jul 30 18:37:25 2001
***************
*** 0 ****
--- 1,107 ----
+ #
+ # Initialize
+ #
+ smtpd_delay_reject 0
+ mynetworks 127.0.0.0/8,168.100.189.0/28
+ relay_domains porcupine.org
+ #
+ # Test check_domain_access()
+ #
+ helo_restrictions hash:./smtpd_check_access
+ # Expect: REJECT
+ helo foo.dunno.com
+ # Expect: OK
+ helo bar.dunno.com
+ # Expect: OK
+ helo foo.duuno.com
+ #
+ # Test check_namadr_access(), domain part
+ #
+ client_restrictions hash:./smtpd_check_access
+ # Expect: REJECT
+ client foo.dunno.com 131.155.210.17
+ # Expect: OK
+ client bar.dunno.com 131.155.210.17
+ # Expect: OK
+ client bar.dunno.com 131.155.210.19
+ #
+ # Test check_namadr_access(), address part
+ #
+ # Expect: OK
+ client bar.duno.com 131.155.210.17
+ # Expect: REJECT
+ client bar.duno.com 131.155.210.19
+ # Expect: REJECT
+ client bar.duno.com 44.33.22.11
+ # Expect: OK
+ client bar.duno.com 44.33.22.55
+ # Expect: REJECT
+ client bar.duno.com 44.33.44.33
+ #
+ # Test check_mail_access()
+ #
+ sender_restrictions hash:./smtpd_check_access
+ # Expect: REJECT
+ mail reject@dunno.domain
+ # Expect: OK
+ mail ok@dunno.domain
+ # Expect: OK
+ mail anyone@dunno.domain
+ # Expect: OK
+ mail bad-sender@dunno.domain
+ #
+ # Again, with a domain that rejects by default
+ #
+ # Expect: REJECT
+ mail reject@reject.domain
+ # Expect: OK
+ mail ok@reject.domain
+ # Expect: REJECT
+ mail anyone@reject.domain
+ # Expect: REJECT
+ mail good-sender@reject.domain
+ #
+ # Again, with a domain that accepts by default
+ #
+ # Expect: REJECT
+ mail reject@ok.domain
+ # Expect: OK
+ mail ok@ok.domain
+ # Expect: OK
+ mail anyone@ok.domain
+ # Expect: OK
+ mail bad-sender@ok.domain
+ #
+ # Test check_mail_access()
+ #
+ recipient_restrictions hash:./smtpd_check_access
+ # Expect: REJECT
+ rcpt reject@dunno.domain
+ # Expect: OK
+ rcpt ok@dunno.domain
+ # Expect: OK
+ rcpt anyone@dunno.domain
+ # Expect: OK
+ rcpt bad-sender@dunno.domain
+ #
+ # Again, with a domain that rejects by default
+ #
+ # Expect: REJECT
+ rcpt reject@reject.domain
+ # Expect: OK
+ rcpt ok@reject.domain
+ # Expect: REJECT
+ rcpt anyone@reject.domain
+ # Expect: REJECT
+ rcpt good-sender@reject.domain
+ #
+ # Again, with a domain that accepts by default
+ #
+ # Expect: REJECT
+ rcpt reject@ok.domain
+ # Expect: OK
+ rcpt ok@ok.domain
+ # Expect: OK
+ rcpt anyone@ok.domain
+ # Expect: OK
+ rcpt bad-sender@ok.domain
diff -cr --new-file ../postfix-20010228-pl03/src/smtpd/smtpd_acl.ref ./src/smtpd/smtpd_acl.ref
*** ../postfix-20010228-pl03/src/smtpd/smtpd_acl.ref Wed Dec 31 19:00:00 1969
--- ./src/smtpd/smtpd_acl.ref Mon Jul 30 18:37:59 2001
***************
*** 0 ****
--- 1,164 ----
+ >>> #
+ >>> # Initialize
+ >>> #
+ >>> smtpd_delay_reject 0
+ OK
+ >>> mynetworks 127.0.0.0/8,168.100.189.0/28
+ OK
+ >>> relay_domains porcupine.org
+ OK
+ >>> #
+ >>> # Test check_domain_access()
+ >>> #
+ >>> helo_restrictions hash:./smtpd_check_access
+ OK
+ >>> # Expect: REJECT
+ >>> helo foo.dunno.com
+ ./smtpd_check: reject: HELO from localhost[127.0.0.1]: 554 : Helo command rejected: Access denied
+ 554 : Helo command rejected: Access denied
+ >>> # Expect: OK
+ >>> helo bar.dunno.com
+ OK
+ >>> # Expect: OK
+ >>> helo foo.duuno.com
+ OK
+ >>> #
+ >>> # Test check_namadr_access(), domain part
+ >>> #
+ >>> client_restrictions hash:./smtpd_check_access
+ OK
+ >>> # Expect: REJECT
+ >>> client foo.dunno.com 131.155.210.17
+ ./smtpd_check: reject: CONNECT from foo.dunno.com[131.155.210.17]: 554 : Client host rejected: Access denied
+ 554 : Client host rejected: Access denied
+ >>> # Expect: OK
+ >>> client bar.dunno.com 131.155.210.17
+ OK
+ >>> # Expect: OK
+ >>> client bar.dunno.com 131.155.210.19
+ OK
+ >>> #
+ >>> # Test check_namadr_access(), address part
+ >>> #
+ >>> # Expect: OK
+ >>> client bar.duno.com 131.155.210.17
+ OK
+ >>> # Expect: REJECT
+ >>> client bar.duno.com 131.155.210.19
+ ./smtpd_check: reject: CONNECT from bar.duno.com[131.155.210.19]: 554 : Client host rejected: Access denied
+ 554 : Client host rejected: Access denied
+ >>> # Expect: REJECT
+ >>> client bar.duno.com 44.33.22.11
+ ./smtpd_check: reject: CONNECT from bar.duno.com[44.33.22.11]: 554 : Client host rejected: Access denied
+ 554 : Client host rejected: Access denied
+ >>> # Expect: OK
+ >>> client bar.duno.com 44.33.22.55
+ OK
+ >>> # Expect: REJECT
+ >>> client bar.duno.com 44.33.44.33
+ ./smtpd_check: reject: CONNECT from bar.duno.com[44.33.44.33]: 554 : Client host rejected: Access denied
+ 554 : Client host rejected: Access denied
+ >>> #
+ >>> # Test check_mail_access()
+ >>> #
+ >>> sender_restrictions hash:./smtpd_check_access
+ OK
+ >>> # Expect: REJECT
+ >>> mail reject@dunno.domain
+ ./smtpd_check: reject: MAIL from bar.duno.com[44.33.44.33]: 554 : Sender address rejected: Access denied; from=
+ 554 : Sender address rejected: Access denied
+ >>> # Expect: OK
+ >>> mail ok@dunno.domain
+ OK
+ >>> # Expect: OK
+ >>> mail anyone@dunno.domain
+ OK
+ >>> # Expect: OK
+ >>> mail bad-sender@dunno.domain
+ OK
+ >>> #
+ >>> # Again, with a domain that rejects by default
+ >>> #
+ >>> # Expect: REJECT
+ >>> mail reject@reject.domain
+ ./smtpd_check: reject: MAIL from bar.duno.com[44.33.44.33]: 554 : Sender address rejected: Access denied; from=
+ 554 : Sender address rejected: Access denied
+ >>> # Expect: OK
+ >>> mail ok@reject.domain
+ OK
+ >>> # Expect: REJECT
+ >>> mail anyone@reject.domain
+ ./smtpd_check: reject: MAIL from bar.duno.com[44.33.44.33]: 554 : Sender address rejected: Access denied; from=
+ 554 : Sender address rejected: Access denied
+ >>> # Expect: REJECT
+ >>> mail good-sender@reject.domain
+ ./smtpd_check: reject: MAIL from bar.duno.com[44.33.44.33]: 554 : Sender address rejected: Access denied; from=
+ 554 : Sender address rejected: Access denied
+ >>> #
+ >>> # Again, with a domain that accepts by default
+ >>> #
+ >>> # Expect: REJECT
+ >>> mail reject@ok.domain
+ ./smtpd_check: reject: MAIL from bar.duno.com[44.33.44.33]: 554 : Sender address rejected: Access denied; from=
+ 554 : Sender address rejected: Access denied
+ >>> # Expect: OK
+ >>> mail ok@ok.domain
+ OK
+ >>> # Expect: OK
+ >>> mail anyone@ok.domain
+ OK
+ >>> # Expect: OK
+ >>> mail bad-sender@ok.domain
+ OK
+ >>> #
+ >>> # Test check_mail_access()
+ >>> #
+ >>> recipient_restrictions hash:./smtpd_check_access
+ OK
+ >>> # Expect: REJECT
+ >>> rcpt reject@dunno.domain
+ ./smtpd_check: reject: RCPT from bar.duno.com[44.33.44.33]: 554 : Recipient address rejected: Access denied; from= to=
+ 554 : Recipient address rejected: Access denied
+ >>> # Expect: OK
+ >>> rcpt ok@dunno.domain
+ OK
+ >>> # Expect: OK
+ >>> rcpt anyone@dunno.domain
+ OK
+ >>> # Expect: OK
+ >>> rcpt bad-sender@dunno.domain
+ OK
+ >>> #
+ >>> # Again, with a domain that rejects by default
+ >>> #
+ >>> # Expect: REJECT
+ >>> rcpt reject@reject.domain
+ ./smtpd_check: reject: RCPT from bar.duno.com[44.33.44.33]: 554 : Recipient address rejected: Access denied; from= to=
+ 554 : Recipient address rejected: Access denied
+ >>> # Expect: OK
+ >>> rcpt ok@reject.domain
+ OK
+ >>> # Expect: REJECT
+ >>> rcpt anyone@reject.domain
+ ./smtpd_check: reject: RCPT from bar.duno.com[44.33.44.33]: 554 : Recipient address rejected: Access denied; from= to=
+ 554 : Recipient address rejected: Access denied
+ >>> # Expect: REJECT
+ >>> rcpt good-sender@reject.domain
+ ./smtpd_check: reject: RCPT from bar.duno.com[44.33.44.33]: 554 : Recipient address rejected: Access denied; from= to=
+ 554 : Recipient address rejected: Access denied
+ >>> #
+ >>> # Again, with a domain that accepts by default
+ >>> #
+ >>> # Expect: REJECT
+ >>> rcpt reject@ok.domain
+ ./smtpd_check: reject: RCPT from bar.duno.com[44.33.44.33]: 554 : Recipient address rejected: Access denied; from= to=
+ 554 : Recipient address rejected: Access denied
+ >>> # Expect: OK
+ >>> rcpt ok@ok.domain
+ OK
+ >>> # Expect: OK
+ >>> rcpt anyone@ok.domain
+ OK
+ >>> # Expect: OK
+ >>> rcpt bad-sender@ok.domain
+ OK
diff -cr --new-file ../postfix-20010228-pl03/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c
*** ../postfix-20010228-pl03/src/smtpd/smtpd_check.c Mon May 7 18:27:58 2001
--- ./src/smtpd/smtpd_check.c Tue Jul 31 10:26:41 2001
***************
*** 269,274 ****
--- 269,275 ----
#include
#include
#include
+ #include
/* DNS library. */
***************
*** 310,318 ****
* Intermediate results. These are static to avoid unnecessary stress on the
* memory manager routines.
*/
- static RESOLVE_REPLY reply;
- static VSTRING *query;
static VSTRING *error_text;
/*
* Pre-opened SMTP recipient maps so we can reject mail for unknown users.
--- 311,318 ----
* Intermediate results. These are static to avoid unnecessary stress on the
* memory manager routines.
*/
static VSTRING *error_text;
+ static CTABLE *smtpd_resolve_cache;
/*
* Pre-opened SMTP recipient maps so we can reject mail for unknown users.
***************
*** 345,351 ****
/*
* The routine that recursively applies restrictions.
*/
! static int generic_checks(SMTPD_STATE *, ARGV *, char *, char *, char *);
/*
* Reject context.
--- 345,351 ----
/*
* The routine that recursively applies restrictions.
*/
! static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, const char *);
/*
* Reject context.
***************
*** 360,365 ****
--- 360,408 ----
* YASLM.
*/
#define STR vstring_str
+ #define CONST_STR(x) ((const char *) vstring_str(x))
+
+ /* resolve_pagein - page in an address resolver result */
+
+ static void *resolve_pagein(const char *addr, void *unused_context)
+ {
+ static VSTRING *query;
+ RESOLVE_REPLY *reply;
+
+ /*
+ * Initialize on the fly.
+ */
+ if (query == 0)
+ query = vstring_alloc(10);
+
+ /*
+ * Initialize.
+ */
+ reply = (RESOLVE_REPLY *) mymalloc(sizeof(*reply));
+ resolve_clnt_init(reply);
+
+ /*
+ * Resolve the address.
+ */
+ canon_addr_internal(query, addr);
+ resolve_clnt_query(STR(query), reply);
+ lowercase(STR(reply->recipient));
+
+ /*
+ * Save the result.
+ */
+ return ((void *) reply);
+ }
+
+ /* resolve_pageout - page out an address resolver result */
+
+ static void resolve_pageout(void *data, void *unused_context)
+ {
+ RESOLVE_REPLY *reply = (RESOLVE_REPLY *) data;
+
+ resolve_clnt_free(reply);
+ myfree((void *) reply);
+ }
/* smtpd_check_parse - pre-parse restrictions */
***************
*** 471,484 ****
DICT_FLAG_LOCK);
/*
! * Reply is used as a cache for resolved addresses, and error_text is
! * used for returning error responses.
*/
- resolve_clnt_init(&reply);
- query = vstring_alloc(10);
error_text = vstring_alloc(10);
/*
* Pre-parse the restriction lists. At the same time, pre-open tables
* before going to jail.
*/
--- 514,530 ----
DICT_FLAG_LOCK);
/*
! * error_text is used for returning error responses.
*/
error_text = vstring_alloc(10);
/*
+ * Initialize the resolved address cache.
+ */
+ smtpd_resolve_cache = ctable_create(100, resolve_pagein,
+ resolve_pageout, (void *) 0);
+
+ /*
* Pre-parse the restriction lists. At the same time, pre-open tables
* before going to jail.
*/
***************
*** 620,627 ****
/* check_mail_addr_find - reject with temporary failure if dict lookup fails */
! static const char *check_mail_addr_find(SMTPD_STATE *state, const char *reply_name,
! MAPS *maps, const char *key, char **ext)
{
const char *result;
--- 666,675 ----
/* check_mail_addr_find - reject with temporary failure if dict lookup fails */
! static const char *check_mail_addr_find(SMTPD_STATE *state,
! const char *reply_name,
! MAPS *maps, const char *key,
! char **ext)
{
const char *result;
***************
*** 816,823 ****
/* reject_unknown_mailhost - fail if name has no A or MX record */
! static int reject_unknown_mailhost(SMTPD_STATE *state, char *name,
! char *reply_name, char *reply_class)
{
char *myname = "reject_unknown_mailhost";
int dns_status;
--- 864,871 ----
/* reject_unknown_mailhost - fail if name has no A or MX record */
! static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
! const char *reply_name, const char *reply_class)
{
char *myname = "reject_unknown_mailhost";
int dns_status;
***************
*** 873,879 ****
static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
{
char *myname = "permit_auth_destination";
! char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, recipient);
--- 921,928 ----
static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
{
char *myname = "permit_auth_destination";
! const RESOLVE_REPLY *reply;
! const char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, recipient);
***************
*** 881,894 ****
/*
* Resolve the address.
*/
! canon_addr_internal(query, recipient);
! resolve_clnt_query(STR(query), &reply);
! lowercase(STR(reply.recipient));
/*
* Handle special case that is not supposed to happen.
*/
! if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
--- 930,942 ----
/*
* Resolve the address.
*/
! reply = (const RESOLVE_REPLY *)
! ctable_locate(smtpd_resolve_cache, recipient);
/*
* Handle special case that is not supposed to happen.
*/
! if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
***************
*** 904,910 ****
/*
* Skip source-routed mail (uncertain destination).
*/
! if (var_allow_untrust_route == 0 && (reply.flags & RESOLVE_FLAG_ROUTED))
return (SMTPD_CHECK_DUNNO);
/*
--- 952,958 ----
/*
* Skip source-routed mail (uncertain destination).
*/
! if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
return (SMTPD_CHECK_DUNNO);
/*
***************
*** 963,969 ****
/* has_my_addr - see if this host name lists one of my network addresses */
! static int has_my_addr(char *host)
{
char *myname = "has_my_addr";
struct in_addr addr;
--- 1011,1017 ----
/* has_my_addr - see if this host name lists one of my network addresses */
! static int has_my_addr(const char *host)
{
char *myname = "has_my_addr";
struct in_addr addr;
***************
*** 1007,1013 ****
static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
{
char *myname = "permit_mx_backup";
! char *domain;
DNS_RR *mx_list;
DNS_RR *mx;
--- 1055,1062 ----
static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
{
char *myname = "permit_mx_backup";
! const RESOLVE_REPLY *reply;
! const char *domain;
DNS_RR *mx_list;
DNS_RR *mx;
***************
*** 1019,1033 ****
/*
* Resolve the address.
*/
! canon_addr_internal(query, recipient);
! resolve_clnt_query(STR(query), &reply);
! lowercase(STR(reply.recipient));
/*
* If the destination is local, it is acceptable, because we are
* supposedly MX for our own address.
*/
! if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
if (resolve_local(domain)
--- 1068,1081 ----
/*
* Resolve the address.
*/
! reply = (const RESOLVE_REPLY *)
! ctable_locate(smtpd_resolve_cache, recipient);
/*
* If the destination is local, it is acceptable, because we are
* supposedly MX for our own address.
*/
! if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
if (resolve_local(domain)
***************
*** 1041,1047 ****
/*
* Skip source-routed mail (uncertain destination).
*/
! if (var_allow_untrust_route == 0 && (reply.flags & RESOLVE_FLAG_ROUTED))
return (SMTPD_CHECK_DUNNO);
/*
--- 1089,1095 ----
/*
* Skip source-routed mail (uncertain destination).
*/
! if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
return (SMTPD_CHECK_DUNNO);
/*
***************
*** 1150,1160 ****
/* reject_unknown_address - fail if address does not resolve */
! static int reject_unknown_address(SMTPD_STATE *state, char *addr,
! char *reply_name, char *reply_class)
{
char *myname = "reject_unknown_address";
! char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, addr);
--- 1198,1209 ----
/* reject_unknown_address - fail if address does not resolve */
! static int reject_unknown_address(SMTPD_STATE *state, const char *addr,
! const char *reply_name, const char *reply_class)
{
char *myname = "reject_unknown_address";
! const RESOLVE_REPLY *reply;
! const char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, addr);
***************
*** 1162,1175 ****
/*
* Resolve the address.
*/
! canon_addr_internal(query, addr);
! resolve_clnt_query(STR(query), &reply);
! lowercase(STR(reply.recipient));
/*
* Skip local destinations and non-DNS forms.
*/
! if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
if (resolve_local(domain)
--- 1211,1222 ----
/*
* Resolve the address.
*/
! reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr);
/*
* Skip local destinations and non-DNS forms.
*/
! if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
if (resolve_local(domain)
***************
*** 1189,1198 ****
/* check_table_result - translate table lookup result into pass/reject */
! static int check_table_result(SMTPD_STATE *state, char *table,
const char *value, const char *datum,
! char *reply_name, char *reply_class,
! char *def_acl)
{
char *myname = "check_table_result";
int code;
--- 1236,1246 ----
/* check_table_result - translate table lookup result into pass/reject */
! static int check_table_result(SMTPD_STATE *state, const char *table,
const char *value, const char *datum,
! const char *reply_name,
! const char *reply_class,
! const char *def_acl)
{
char *myname = "check_table_result";
int code;
***************
*** 1287,1303 ****
/* check_access - table lookup without substring magic */
! static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
! char *reply_name, char *reply_class, char *def_acl)
{
char *myname = "check_access";
char *low_name = lowercase(mystrdup(name));
const char *value;
DICT *dict;
! #define CHK_ACCESS_RETURN(x) { myfree(low_name); return(x); }
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
if (msg_verbose)
msg_info("%s: %s", myname, name);
--- 1335,1354 ----
/* check_access - table lookup without substring magic */
! static int check_access(SMTPD_STATE *state, const char *table, const char *name,
! int flags, int *found, const char *reply_name,
! const char *reply_class, const char *def_acl)
{
char *myname = "check_access";
char *low_name = lowercase(mystrdup(name));
const char *value;
DICT *dict;
! #define CHK_ACCESS_RETURN(x,y) { *found = y; myfree(low_name); return(x); }
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
+ #define FOUND 1
+ #define MISSED 0
if (msg_verbose)
msg_info("%s: %s", myname, name);
***************
*** 1308,1326 ****
if ((value = dict_get(dict, low_name)) != 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
reply_name, reply_class,
! def_acl));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
! CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO);
}
/* check_domain_access - domainname-based table lookup */
! static int check_domain_access(SMTPD_STATE *state, char *table,
! char *domain, int flags,
! char *reply_name, char *reply_class,
! char *def_acl)
{
char *myname = "check_domain_access";
char *low_domain = lowercase(mystrdup(domain));
--- 1359,1378 ----
if ((value = dict_get(dict, low_name)) != 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
reply_name, reply_class,
! def_acl), FOUND);
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
! CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO, MISSED);
}
/* check_domain_access - domainname-based table lookup */
! static int check_domain_access(SMTPD_STATE *state, const char *table,
! const char *domain, int flags,
! int *found, const char *reply_name,
! const char *reply_class,
! const char *def_acl)
{
char *myname = "check_domain_access";
char *low_domain = lowercase(mystrdup(domain));
***************
*** 1335,1341 ****
/*
* Try the name and its parent domains. Including top-level domains.
*/
! #define CHK_DOMAIN_RETURN(x) { myfree(low_domain); return(x); }
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
--- 1387,1393 ----
/*
* Try the name and its parent domains. Including top-level domains.
*/
! #define CHK_DOMAIN_RETURN(x,y) { *found = y; myfree(low_domain); return(x); }
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
***************
*** 1344,1350 ****
if ((value = dict_get(dict, name)) != 0)
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
domain, reply_name, reply_class,
! def_acl));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
--- 1396,1402 ----
if ((value = dict_get(dict, name)) != 0)
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
domain, reply_name, reply_class,
! def_acl), FOUND);
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
***************
*** 1352,1366 ****
break;
flags = PARTIAL;
}
! CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO);
}
/* check_addr_access - address-based table lookup */
! static int check_addr_access(SMTPD_STATE *state, char *table,
! char *address, int flags,
! char *reply_name, char *reply_class,
! char *def_acl)
{
char *myname = "check_addr_access";
char *addr;
--- 1404,1419 ----
break;
flags = PARTIAL;
}
! CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED);
}
/* check_addr_access - address-based table lookup */
! static int check_addr_access(SMTPD_STATE *state, const char *table,
! const char *address, int flags,
! int *found, const char *reply_name,
! const char *reply_class,
! const char *def_acl)
{
char *myname = "check_addr_access";
char *addr;
***************
*** 1373,1378 ****
--- 1426,1433 ----
/*
* Try the address and its parent networks.
*/
+ #define CHK_ADDR_RETURN(x,y) { *found = y; return(x); }
+
addr = STR(vstring_strcpy(error_text, address));
if ((dict = dict_handle(table)) == 0)
***************
*** 1380,1403 ****
do {
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, addr)) != 0)
! return (check_table_result(state, table, value, address,
! reply_name, reply_class,
! def_acl));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
flags = PARTIAL;
} while (split_at_right(addr, '.'));
! return (SMTPD_CHECK_DUNNO);
}
/* check_namadr_access - OK/FAIL based on host name/address lookup */
! static int check_namadr_access(SMTPD_STATE *state, char *table,
! char *name, char *addr, int flags,
! char *reply_name, char *reply_class,
! char *def_acl)
{
char *myname = "check_namadr_access";
int status;
--- 1435,1460 ----
do {
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, addr)) != 0)
! CHK_ADDR_RETURN(check_table_result(state, table, value, address,
! reply_name, reply_class,
! def_acl), FOUND);
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
flags = PARTIAL;
} while (split_at_right(addr, '.'));
! CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
}
/* check_namadr_access - OK/FAIL based on host name/address lookup */
! static int check_namadr_access(SMTPD_STATE *state, const char *table,
! const char *name, const char *addr,
! int flags, int *found,
! const char *reply_name,
! const char *reply_class,
! const char *def_acl)
{
char *myname = "check_namadr_access";
int status;
***************
*** 1410,1425 ****
* wildcard may pre-empt a more specific address table entry.
*/
if ((status = check_domain_access(state, table, name, flags,
! reply_name, reply_class,
! def_acl)) != 0)
return (status);
/*
* Look up the network address, or parent networks thereof.
*/
if ((status = check_addr_access(state, table, addr, flags,
! reply_name, reply_class,
! def_acl)) != 0)
return (status);
/*
--- 1467,1482 ----
* wildcard may pre-empt a more specific address table entry.
*/
if ((status = check_domain_access(state, table, name, flags,
! found, reply_name, reply_class,
! def_acl)) != 0 || *found)
return (status);
/*
* Look up the network address, or parent networks thereof.
*/
if ((status = check_addr_access(state, table, addr, flags,
! found, reply_name, reply_class,
! def_acl)) != 0 || *found)
return (status);
/*
***************
*** 1430,1441 ****
/* check_mail_access - OK/FAIL based on mail address lookup */
! static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
! char *reply_name, char *reply_class,
! char *def_acl)
{
char *myname = "check_mail_access";
! char *ratsign;
int status;
char *local_at;
--- 1487,1501 ----
/* check_mail_access - OK/FAIL based on mail address lookup */
! static int check_mail_access(SMTPD_STATE *state, const char *table,
! const char *addr, int *found,
! const char *reply_name,
! const char *reply_class,
! const char *def_acl)
{
char *myname = "check_mail_access";
! const RESOLVE_REPLY *reply;
! const char *ratsign;
int status;
char *local_at;
***************
*** 1445,1486 ****
/*
* Resolve the address.
*/
! canon_addr_internal(query, addr);
! resolve_clnt_query(STR(query), &reply);
! lowercase(STR(reply.recipient));
/*
* Garbage in, garbage out. Every address from canon_addr_internal() and
* from resolve_clnt_query() must be fully qualified.
*/
! if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) {
! msg_warn("%s: no @domain in address: %s", myname, STR(reply.recipient));
return (0);
}
/*
* Look up the full address.
*/
! if ((status = check_access(state, table, STR(reply.recipient), FULL,
! reply_name, reply_class, def_acl)) != 0)
return (status);
/*
* Look up the domain name, or parent domains thereof.
*/
if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL,
! reply_name, reply_class, def_acl)) != 0)
return (status);
/*
* Look up localpart@
*/
! local_at = mystrndup(STR(reply.recipient),
! ratsign - STR(reply.recipient) + 1);
! status = check_access(state, table, local_at, PARTIAL,
reply_name, reply_class, def_acl);
myfree(local_at);
! if (status != 0)
return (status);
/*
--- 1505,1546 ----
/*
* Resolve the address.
*/
! reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr);
/*
* Garbage in, garbage out. Every address from canon_addr_internal() and
* from resolve_clnt_query() must be fully qualified.
*/
! if ((ratsign = strrchr(CONST_STR(reply->recipient), '@')) == 0) {
! msg_warn("%s: no @domain in address: %s", myname, CONST_STR(reply->recipient));
return (0);
}
/*
* Look up the full address.
*/
! if ((status = check_access(state, table, CONST_STR(reply->recipient), FULL,
! found, reply_name, reply_class, def_acl)) != 0
! || *found)
return (status);
/*
* Look up the domain name, or parent domains thereof.
*/
if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL,
! found, reply_name, reply_class, def_acl)) != 0
! || *found)
return (status);
/*
* Look up localpart@
*/
! local_at = mystrndup(CONST_STR(reply->recipient),
! ratsign - CONST_STR(reply->recipient) + 1);
! status = check_access(state, table, local_at, PARTIAL, found,
reply_name, reply_class, def_acl);
myfree(local_at);
! if (status != 0 || *found)
return (status);
/*
***************
*** 1573,1579 ****
/* is_map_command - restriction has form: check_xxx_access type:name */
! static int is_map_command(char *name, char *command, char ***argp)
{
/*
--- 1633,1639 ----
/* is_map_command - restriction has form: check_xxx_access type:name */
! static int is_map_command(const char *name, const char *command, char ***argp)
{
/*
***************
*** 1596,1608 ****
/* generic_checks - generic restrictions */
static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
! char *reply_name, char *reply_class, char *def_acl)
{
char *myname = "generic_checks";
char **cpp;
! char *name;
int status = 0;
ARGV *list;
if (msg_verbose)
msg_info("%s: START", myname);
--- 1656,1671 ----
/* generic_checks - generic restrictions */
static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
! const char *reply_name,
! const char *reply_class,
! const char *def_acl)
{
char *myname = "generic_checks";
char **cpp;
! const char *name;
int status = 0;
ARGV *list;
+ int found;
if (msg_verbose)
msg_info("%s: START", myname);
***************
*** 1649,1655 ****
status = permit_mynetworks(state);
} else if (is_map_command(name, CHECK_CLIENT_ACL, &cpp)) {
status = check_namadr_access(state, *cpp, state->name, state->addr,
! FULL, state->namaddr,
SMTPD_NAME_CLIENT, def_acl);
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
status = reject_maps_rbl(state);
--- 1712,1718 ----
status = permit_mynetworks(state);
} else if (is_map_command(name, CHECK_CLIENT_ACL, &cpp)) {
status = check_namadr_access(state, *cpp, state->name, state->addr,
! FULL, &found, state->namaddr,
SMTPD_NAME_CLIENT, def_acl);
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
status = reject_maps_rbl(state);
***************
*** 1661,1667 ****
else if (is_map_command(name, CHECK_HELO_ACL, &cpp)) {
if (state->helo_name)
status = check_domain_access(state, *cpp, state->helo_name,
! FULL, state->helo_name,
SMTPD_NAME_HELO, def_acl);
} else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
if (state->helo_name) {
--- 1724,1730 ----
else if (is_map_command(name, CHECK_HELO_ACL, &cpp)) {
if (state->helo_name)
status = check_domain_access(state, *cpp, state->helo_name,
! FULL, &found, state->helo_name,
SMTPD_NAME_HELO, def_acl);
} else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
if (state->helo_name) {
***************
*** 1705,1711 ****
else if (is_map_command(name, CHECK_SENDER_ACL, &cpp)) {
if (state->sender && *state->sender)
status = check_mail_access(state, *cpp, state->sender,
! state->sender,
SMTPD_NAME_SENDER, def_acl);
} else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
if (state->sender && *state->sender)
--- 1768,1774 ----
else if (is_map_command(name, CHECK_SENDER_ACL, &cpp)) {
if (state->sender && *state->sender)
status = check_mail_access(state, *cpp, state->sender,
! &found, state->sender,
SMTPD_NAME_SENDER, def_acl);
} else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
if (state->sender && *state->sender)
***************
*** 1727,1733 ****
else if (is_map_command(name, CHECK_RECIP_ACL, &cpp)) {
if (state->recipient)
status = check_mail_access(state, *cpp, state->recipient,
! state->recipient,
SMTPD_NAME_RECIPIENT, def_acl);
} else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
if (state->recipient)
--- 1790,1796 ----
else if (is_map_command(name, CHECK_RECIP_ACL, &cpp)) {
if (state->recipient)
status = check_mail_access(state, *cpp, state->recipient,
! &found, state->recipient,
SMTPD_NAME_RECIPIENT, def_acl);
} else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
if (state->recipient)
***************
*** 1767,1773 ****
else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
if (state->etrn_name)
status = check_domain_access(state, *cpp, state->etrn_name,
! FULL, state->etrn_name,
SMTPD_NAME_ETRN, def_acl);
}
--- 1830,1836 ----
else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
if (state->etrn_name)
status = check_domain_access(state, *cpp, state->etrn_name,
! FULL, &found, state->etrn_name,
SMTPD_NAME_ETRN, def_acl);
}
***************
*** 2002,2008 ****
{
char *myname = "smtpd_check_rcptmap";
char *saved_recipient;
! char *domain;
int status;
/*
--- 2065,2072 ----
{
char *myname = "smtpd_check_rcptmap";
char *saved_recipient;
! const RESOLVE_REPLY *reply;
! const char *domain;
int status;
/*
***************
*** 2029,2042 ****
/*
* Resolve the address.
*/
! canon_addr_internal(query, recipient);
! resolve_clnt_query(STR(query), &reply);
! lowercase(STR(reply.recipient));
/*
* Skip non-DNS forms. Skip non-local numerical forms.
*/
! if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
SMTPD_CHECK_RCPT_RETURN(0);
domain += 1;
if (domain[0] == '#' || domain[0] == '[')
--- 2093,2105 ----
/*
* Resolve the address.
*/
! reply = (const RESOLVE_REPLY *)
! ctable_locate(smtpd_resolve_cache, recipient);
/*
* Skip non-DNS forms. Skip non-local numerical forms.
*/
! if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
SMTPD_CHECK_RCPT_RETURN(0);
domain += 1;
if (domain[0] == '#' || domain[0] == '[')
***************
*** 2051,2060 ****
*/
if (*var_virtual_maps
&& (check_maps_find(state, recipient, virtual_maps, domain, 0))) {
! if (NOMATCH(rcpt_canon_maps, STR(reply.recipient))
! && NOMATCH(canonical_maps, STR(reply.recipient))
! && NOMATCH(relocated_maps, STR(reply.recipient))
! && NOMATCH(virtual_maps, STR(reply.recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown", 550, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text));
--- 2114,2123 ----
*/
if (*var_virtual_maps
&& (check_maps_find(state, recipient, virtual_maps, domain, 0))) {
! if (NOMATCH(rcpt_canon_maps, CONST_STR(reply->recipient))
! && NOMATCH(canonical_maps, CONST_STR(reply->recipient))
! && NOMATCH(relocated_maps, CONST_STR(reply->recipient))
! && NOMATCH(virtual_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown", 550, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text));
***************
*** 2067,2077 ****
* Sendmail-style virtual domains.
*/
if (*var_local_rcpt_maps && resolve_local(domain)) {
! if (NOMATCH(rcpt_canon_maps, STR(reply.recipient))
! && NOMATCH(canonical_maps, STR(reply.recipient))
! && NOMATCH(relocated_maps, STR(reply.recipient))
! && NOMATCH(virtual_maps, STR(reply.recipient))
! && NOMATCH(local_rcpt_maps, STR(reply.recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown", 550, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text));
--- 2130,2140 ----
* Sendmail-style virtual domains.
*/
if (*var_local_rcpt_maps && resolve_local(domain)) {
! if (NOMATCH(rcpt_canon_maps, CONST_STR(reply->recipient))
! && NOMATCH(canonical_maps, CONST_STR(reply->recipient))
! && NOMATCH(relocated_maps, CONST_STR(reply->recipient))
! && NOMATCH(virtual_maps, CONST_STR(reply->recipient))
! && NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown", 550, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text));
***************
*** 2336,2346 ****
--- 2399,2417 ----
void resolve_clnt_init(RESOLVE_REPLY *reply)
{
+ reply->flags = 0;
reply->transport = vstring_alloc(100);
reply->nexthop = vstring_alloc(100);
reply->recipient = vstring_alloc(100);
}
+ void resolve_clnt_free(RESOLVE_REPLY *reply)
+ {
+ vstring_free(reply->transport);
+ vstring_free(reply->nexthop);
+ vstring_free(reply->recipient);
+ }
+
#ifdef USE_SASL_AUTH
bool var_smtpd_sasl_enable = 0;
***************
*** 2383,2389 ****
void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
{
! if (addr == STR(reply->recipient))
msg_panic("resolve_clnt_query: result clobbers input");
vstring_strcpy(reply->transport, "foo");
vstring_strcpy(reply->nexthop, "foo");
--- 2454,2460 ----
void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
{
! if (addr == CONST_STR(reply->recipient))
msg_panic("resolve_clnt_query: result clobbers input");
vstring_strcpy(reply->transport, "foo");
vstring_strcpy(reply->nexthop, "foo");
***************
*** 2405,2411 ****
msg_fatal("usage: %s", myname);
}
! main(int argc, char **argv)
{
VSTRING *buf = vstring_alloc(100);
SMTPD_STATE state;
--- 2476,2482 ----
msg_fatal("usage: %s", myname);
}
! int main(int argc, char **argv)
{
VSTRING *buf = vstring_alloc(100);
SMTPD_STATE state;
diff -cr --new-file ../postfix-20010228-pl03/src/smtpd/smtpd_check_access ./src/smtpd/smtpd_check_access
*** ../postfix-20010228-pl03/src/smtpd/smtpd_check_access Sat Nov 20 20:08:31 1999
--- ./src/smtpd/smtpd_check_access Mon Jul 30 18:37:01 2001
***************
*** 2,10 ****
--- 2,31 ----
friend.bad.domain OK
bad-sender@ 554 match bad-sender@
bad-sender@good.domain OK
+ good-sender@ OK
131.155.210 554 match 131.155.210
131.155.210.17 OK
+ 131.155.210.19 REJECT
reject@this.address 554 match reject@this.address
open_user@some.site open
strict_user@some.site strict
auth_client 123456
+
+ dunno.com dunno
+ foo.dunno.com reject
+
+ 44.33.22 dunno
+ 44.33.22.11 REJECT
+ 44.33 REJECT
+
+ reject@dunno.domain REJECT
+ ok@dunno.domain OK
+ dunno.domain DUNNO
+
+ reject@reject.domain REJECT
+ ok@reject.domain OK
+ reject.domain REJECT
+
+ reject@ok.domain REJECT
+ ok@ok.domain OK
+ ok.domain OK
diff -cr --new-file ../postfix-20010228-pl03/src/util/Makefile.in ./src/util/Makefile.in
*** ../postfix-20010228-pl03/src/util/Makefile.in Fri Apr 27 15:14:30 2001
--- ./src/util/Makefile.in Tue Jul 31 14:26:11 2001
***************
*** 23,29 ****
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
! sane_socketpair.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
--- 23,29 ----
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
! sane_socketpair.c ctable.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
***************
*** 48,54 ****
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \
! sane_socketpair.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
--- 48,54 ----
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \
! sane_socketpair.o ctable.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
***************
*** 64,70 ****
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \
watchdog.h spawn_command.h sane_fsops.h dict_tcp.h hex_quote.h \
! sane_time.h sane_socketpair.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
--- 64,70 ----
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \
watchdog.h spawn_command.h sane_fsops.h dict_tcp.h hex_quote.h \
! sane_time.h sane_socketpair.h ctable.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
***************
*** 80,86 ****
inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
mystrtok sigdelay translit valid_hostname vstream_popen \
vstring vstring_vstream doze select_bug stream_test mac_expand \
! watchdog unescape hex_quote name_mask rand_sleep sane_time
LIB_DIR = ../../lib
INC_DIR = ../../include
--- 80,87 ----
inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
mystrtok sigdelay translit valid_hostname vstream_popen \
vstring vstring_vstream doze select_bug stream_test mac_expand \
! watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
! inet_addr_list
LIB_DIR = ../../lib
INC_DIR = ../../include
***************
*** 274,279 ****
--- 275,290 ----
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+ ctable: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
+ inet_addr_list: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
***************
*** 286,292 ****
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
! hex_quote_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname valid_hostname.tmp
--- 297,303 ----
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
! hex_quote_test ctable_test inet_addr_list_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname valid_hostname.tmp
***************
*** 309,314 ****
--- 320,335 ----
cmp hex_quote.ref hex_quote.tmp
rm -f hex_quote.ref hex_quote.tmp
+ ctable_test: ctable
+ ./ctable ctable.tmp 2>&1
+ diff ctable.ref ctable.tmp
+ rm -f ctable.tmp
+
+ inet_addr_list_test: inet_addr_list
+ ./inet_addr_list `cat inet_addr_list.in` >inet_addr_list.tmp 2>&1
+ diff inet_addr_list.ref inet_addr_list.tmp
+ rm -f inet_addr_list.tmp
+
DB_TYPE = `../postconf/postconf -h default_database_type`
dict_test: dict_open testdb dict_test.in dict_test.ref
***************
*** 368,373 ****
--- 389,401 ----
concatenate.o: stringops.h
concatenate.o: vstring.h
concatenate.o: vbuf.h
+ ctable.o: ctable.c
+ ctable.o: sys_defs.h
+ ctable.o: msg.h
+ ctable.o: mymalloc.h
+ ctable.o: ring.h
+ ctable.o: htable.h
+ ctable.o: ctable.h
dict.o: dict.c
dict.o: sys_defs.h
dict.o: msg.h
diff -cr --new-file ../postfix-20010228-pl03/src/util/ctable.c ./src/util/ctable.c
*** ../postfix-20010228-pl03/src/util/ctable.c Wed Dec 31 19:00:00 1969
--- ./src/util/ctable.c Sun Jul 29 17:23:01 2001
***************
*** 0 ****
--- 1,273 ----
+ /*++
+ /* NAME
+ /* ctable 3
+ /* SUMMARY
+ /* cache manager
+ /* SYNOPSIS
+ /* #include
+ /*
+ /* CTABLE *ctable_create(limit, create, delete, context)
+ /* int limit;
+ /* void *(*create)(const char *key, void *context);
+ /* void (*delete)(void *value, void *context);
+ /* void *context;
+ /*
+ /* const void *ctable_locate(cache, key)
+ /* CTABLE *cache;
+ /* const char *key;
+ /*
+ /* void ctable_free(cache)
+ /* CTABLE *cache;
+ /*
+ /* void ctable_walk(cache, action)
+ /* CTABLE *cache;
+ /* void (*action)(const char *key, const void *value);
+ /* DESCRIPTION
+ /* This module maintains multiple caches. Cache items are purged
+ /* automatically when the number of items exceeds a configurable
+ /* limit. Caches never shrink. Each cache entry consists of a
+ /* string-valued lookup key and a generic data pointer value.
+ /*
+ /* ctable_create() creates a cache with the specified size limit, and
+ /* returns a pointer to the result. The create and delete arguments
+ /* specify pointers to call-back functions that create a value, given
+ /* a key, and delete a given value, respectively. The context argument
+ /* is passed on to the call-back routines.
+ /*
+ /* ctable_locate() looks up or generates the value that corresponds to
+ /* the specified key, and returns that value.
+ /*
+ /* ctable_free() destroys the specified cache, including its contents.
+ /*
+ /* ctable_walk() iterates over all elements in the cache, and invokes
+ /* the action function for each cache element with the corresponding
+ /* key and value as arguments. This function is useful mainly for
+ /* cache performance debugging.
+ /* DIAGNOSTICS
+ /* Fatal errors: out of memory. Panic: interface violation.
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ /* System library. */
+
+ #include
+ #include
+ #include
+
+ /* Utility library. */
+
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ /*
+ * Cache entries are kept in most-recently used order. We use a hash table
+ * to quickly locate cache entries.
+ */
+ #define CTABLE_ENTRY struct ctable_entry
+
+ struct ctable_entry {
+ RING ring; /* MRU linkage */
+ const char *key; /* lookup key */
+ void *value; /* corresponding value */
+ };
+
+ #define RING_TO_CTABLE_ENTRY(ring_ptr) \
+ RING_TO_APPL(ring_ptr, CTABLE_ENTRY, ring)
+ #define RING_PTR_OF(x) (&((x)->ring))
+
+ struct ctable {
+ HTABLE *table; /* table with key, ctable_entry pairs */
+ unsigned limit; /* max nr of entries */
+ unsigned used; /* current nr of entries */
+ CTABLE_CREATE_FN create; /* constructor */
+ CTABLE_DELETE_FN delete; /* destructor */
+ RING ring; /* MRU linkage */
+ void *context; /* application context */
+ };
+
+ #define CTABLE_MIN_SIZE 5
+
+ /* ctable_create - create empty cache */
+
+ CTABLE *ctable_create(int limit, CTABLE_CREATE_FN create,
+ CTABLE_DELETE_FN delete, void *context)
+ {
+ CTABLE *cache = (CTABLE *) mymalloc(sizeof(CTABLE));
+ char *myname = "ctable_create";
+
+ if (limit < 1)
+ msg_panic("%s: bad cache limit: %d", myname, limit);
+
+ cache->table = htable_create(limit);
+ cache->limit = (limit < CTABLE_MIN_SIZE ? CTABLE_MIN_SIZE : limit);
+ cache->used = 0;
+ cache->create = create;
+ cache->delete = delete;
+ ring_init(RING_PTR_OF(cache));
+ cache->context = context;
+ return (cache);
+ }
+
+ /* ctable_locate - look up or create cache item */
+
+ const void *ctable_locate(CTABLE *cache, const char *key)
+ {
+ char *myname = "ctable_locate";
+ CTABLE_ENTRY *entry;
+
+ /*
+ * If the entry is not in the cache, make sure there is room for a new
+ * entry and install it at the front of the MRU chain. Otherwise, move
+ * the entry to the front of the MRU chain if it is not already there.
+ * All this means that the cache never shrinks.
+ */
+ if ((entry = (CTABLE_ENTRY *) htable_find(cache->table, key)) == 0) {
+ if (cache->used >= cache->limit) {
+ entry = RING_TO_CTABLE_ENTRY(ring_pred(RING_PTR_OF(cache)));
+ if (msg_verbose)
+ msg_info("%s: purge entry key %s", myname, entry->key);
+ ring_detach(RING_PTR_OF(entry));
+ cache->delete(entry->value, cache->context);
+ htable_delete(cache->table, entry->key, (void (*) (char *)) 0);
+ } else {
+ entry = (CTABLE_ENTRY *) mymalloc(sizeof(CTABLE_ENTRY));
+ cache->used++;
+ }
+ entry->value = cache->create(key, cache->context);
+ entry->key = htable_enter(cache->table, key, (char *) entry)->key;
+ ring_append(RING_PTR_OF(cache), RING_PTR_OF(entry));
+ if (msg_verbose)
+ msg_info("%s: install entry key %s", myname, entry->key);
+ } else if (entry == RING_TO_CTABLE_ENTRY(ring_succ(RING_PTR_OF(cache)))) {
+ if (msg_verbose)
+ msg_info("%s: leave existing entry key %s", myname, entry->key);
+ } else {
+ ring_detach(RING_PTR_OF(entry));
+ ring_append(RING_PTR_OF(cache), RING_PTR_OF(entry));
+ if (msg_verbose)
+ msg_info("%s: move existing entry key %s", myname, entry->key);
+ }
+ return (entry->value);
+ }
+
+ static CTABLE *ctable_free_cache;
+
+ /* ctable_free_callback - callback function */
+
+ static void ctable_free_callback(char *ptr)
+ {
+ CTABLE_ENTRY *entry = (CTABLE_ENTRY *) ptr;
+
+ ctable_free_cache->delete(entry->value, ctable_free_cache->context);
+ myfree((char *) entry);
+ }
+
+ /* ctable_free - destroy cache and contents */
+
+ void ctable_free(CTABLE *cache)
+ {
+ CTABLE *saved_cache = ctable_free_cache;
+
+ /*
+ * XXX the hash table does not pass application context so we have to
+ * store it in a global variable.
+ */
+ ctable_free_cache = cache;
+ htable_free(cache->table, ctable_free_callback);
+ myfree((char *) cache);
+ ctable_free_cache = saved_cache;
+ }
+
+ /* ctable_walk - iterate over all cache entries */
+
+ void ctable_walk(CTABLE *cache, void (*action) (const char *, const void *))
+ {
+ RING *entry = RING_PTR_OF(cache);
+
+ /* Walking down the MRU chain is less work than using ht_walk(). */
+
+ while ((entry = ring_succ(entry)) != RING_PTR_OF(cache))
+ action((RING_TO_CTABLE_ENTRY(entry)->key),
+ (RING_TO_CTABLE_ENTRY(entry)->value));
+ }
+
+ #ifdef TEST
+
+ /*
+ * Proof-of-concept test program. Read keys from stdin, ask for values not
+ * in cache.
+ */
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #define STR(x) vstring_str(x)
+
+ static void *ask(const char *key, void *context)
+ {
+ VSTRING *data_buf = (VSTRING *) context;
+
+ vstream_printf("ask: %s = ", key);
+ vstream_fflush(VSTREAM_OUT);
+ if (vstring_get_nonl(data_buf, VSTREAM_IN) == VSTREAM_EOF)
+ vstream_longjmp(VSTREAM_IN, 1);
+ if (!isatty(0)) {
+ vstream_printf("%s\n", STR(data_buf));
+ vstream_fflush(VSTREAM_OUT);
+ }
+ return (mystrdup(STR(data_buf)));
+ }
+
+ static void drop(void *data, void *unused_context)
+ {
+ myfree(data);
+ }
+
+ int main(int unused_argc, char **argv)
+ {
+ VSTRING *key_buf;
+ VSTRING *data_buf;
+ CTABLE *cache;
+ const char *value;
+
+ msg_vstream_init(argv[0], VSTREAM_ERR);
+ key_buf = vstring_alloc(100);
+ data_buf = vstring_alloc(100);
+ cache = ctable_create(1, ask, drop, (void *) data_buf);
+ msg_verbose = 1;
+ vstream_control(VSTREAM_IN, VSTREAM_CTL_EXCEPT, VSTREAM_CTL_END);
+
+ if (vstream_setjmp(VSTREAM_IN) == 0) {
+ for (;;) {
+ vstream_printf("key = ");
+ vstream_fflush(VSTREAM_OUT);
+ if (vstring_get_nonl(key_buf, VSTREAM_IN) == VSTREAM_EOF)
+ vstream_longjmp(VSTREAM_IN, 1);
+ if (!isatty(0)) {
+ vstream_printf("%s\n", STR(key_buf));
+ vstream_fflush(VSTREAM_OUT);
+ }
+ value = ctable_locate(cache, STR(key_buf));
+ vstream_printf("result: %s\n", value);
+ }
+ }
+ ctable_free(cache);
+ vstring_free(key_buf);
+ vstring_free(data_buf);
+ return (0);
+ }
+
+ #endif
diff -cr --new-file ../postfix-20010228-pl03/src/util/ctable.h ./src/util/ctable.h
*** ../postfix-20010228-pl03/src/util/ctable.h Wed Dec 31 19:00:00 1969
--- ./src/util/ctable.h Sun Jul 29 14:31:44 2001
***************
*** 0 ****
--- 1,39 ----
+ #ifndef _CTABLE_H_INCLUDED_
+ #define _CTABLE_H_INCLUDED_
+
+ /*++
+ /* NAME
+ /* ctable 5
+ /* SUMMARY
+ /* cache manager
+ /* SYNOPSIS
+ /* #include
+ /* DESCRIPTION
+ /* .nf
+
+ /*
+ * Interface of the cache manager. The structure of a cache is not visible
+ * to the caller.
+ */
+
+ #define CTABLE struct ctable
+ typedef void *(*CTABLE_CREATE_FN) (const char *, void *);
+ typedef void (*CTABLE_DELETE_FN) (void *, void *);
+
+ extern CTABLE *ctable_create(int, CTABLE_CREATE_FN, CTABLE_DELETE_FN, void *);
+ extern void ctable_free(CTABLE *);
+ extern void ctable_walk(CTABLE *, void (*) (const char *, const void *));
+ extern const void *ctable_locate(CTABLE *, const char *);
+
+ /* LICENSE
+ /* .ad
+ /* .fi
+ /* The Secure Mailer license must be distributed with this software.
+ /* AUTHOR(S)
+ /* Wietse Venema
+ /* IBM T.J. Watson Research
+ /* P.O. Box 704
+ /* Yorktown Heights, NY 10598, USA
+ /*--*/
+
+ #endif
diff -cr --new-file ../postfix-20010228-pl03/src/util/ctable.in ./src/util/ctable.in
*** ../postfix-20010228-pl03/src/util/ctable.in Wed Dec 31 19:00:00 1969
--- ./src/util/ctable.in Sun Jul 29 12:15:18 2001
***************
*** 0 ****
--- 1,39 ----
+ a
+ 1
+ b
+ 2
+ c
+ 3
+ d
+ 4
+ e
+ 5
+ f
+ 6
+ f
+ a
+ 1
+ b
+ 2
+ c
+ 3
+ d
+ 4
+ e
+ 5
+ f
+ 6
+ f
+ e
+ d
+ c
+ b
+ a
+ 1
+ b
+ c
+ d
+ e
+ f
+ 6
+ f
diff -cr --new-file ../postfix-20010228-pl03/src/util/ctable.ref ./src/util/ctable.ref
*** ../postfix-20010228-pl03/src/util/ctable.ref Wed Dec 31 19:00:00 1969
--- ./src/util/ctable.ref Sun Jul 29 12:15:20 2001
***************
*** 0 ****
--- 1,99 ----
+ key = a
+ ask: a = 1
+ ./ctable: ctable_locate: install entry key a
+ result: 1
+ key = b
+ ask: b = 2
+ ./ctable: ctable_locate: install entry key b
+ result: 2
+ key = c
+ ask: c = 3
+ ./ctable: ctable_locate: install entry key c
+ result: 3
+ key = d
+ ask: d = 4
+ ./ctable: ctable_locate: install entry key d
+ result: 4
+ key = e
+ ask: e = 5
+ ./ctable: ctable_locate: install entry key e
+ result: 5
+ key = f
+ ./ctable: ctable_locate: purge entry key a
+ ask: f = 6
+ ./ctable: ctable_locate: install entry key f
+ result: 6
+ key = f
+ ./ctable: ctable_locate: leave existing entry key f
+ result: 6
+ key = a
+ ./ctable: ctable_locate: purge entry key b
+ ask: a = 1
+ ./ctable: ctable_locate: install entry key a
+ result: 1
+ key = b
+ ./ctable: ctable_locate: purge entry key c
+ ask: b = 2
+ ./ctable: ctable_locate: install entry key b
+ result: 2
+ key = c
+ ./ctable: ctable_locate: purge entry key d
+ ask: c = 3
+ ./ctable: ctable_locate: install entry key c
+ result: 3
+ key = d
+ ./ctable: ctable_locate: purge entry key e
+ ask: d = 4
+ ./ctable: ctable_locate: install entry key d
+ result: 4
+ key = e
+ ./ctable: ctable_locate: purge entry key f
+ ask: e = 5
+ ./ctable: ctable_locate: install entry key e
+ result: 5
+ key = f
+ ./ctable: ctable_locate: purge entry key a
+ ask: f = 6
+ ./ctable: ctable_locate: install entry key f
+ result: 6
+ key = f
+ ./ctable: ctable_locate: leave existing entry key f
+ result: 6
+ key = e
+ ./ctable: ctable_locate: move existing entry key e
+ result: 5
+ key = d
+ ./ctable: ctable_locate: move existing entry key d
+ result: 4
+ key = c
+ ./ctable: ctable_locate: move existing entry key c
+ result: 3
+ key = b
+ ./ctable: ctable_locate: move existing entry key b
+ result: 2
+ key = a
+ ./ctable: ctable_locate: purge entry key f
+ ask: a = 1
+ ./ctable: ctable_locate: install entry key a
+ result: 1
+ key = b
+ ./ctable: ctable_locate: move existing entry key b
+ result: 2
+ key = c
+ ./ctable: ctable_locate: move existing entry key c
+ result: 3
+ key = d
+ ./ctable: ctable_locate: move existing entry key d
+ result: 4
+ key = e
+ ./ctable: ctable_locate: move existing entry key e
+ result: 5
+ key = f
+ ./ctable: ctable_locate: purge entry key a
+ ask: f = 6
+ ./ctable: ctable_locate: install entry key f
+ result: 6
+ key = f
+ ./ctable: ctable_locate: leave existing entry key f
+ result: 6
+ key =
diff -cr --new-file ../postfix-20010228-pl03/src/util/dict_ldap.c ./src/util/dict_ldap.c
*** ../postfix-20010228-pl03/src/util/dict_ldap.c Thu May 24 15:36:42 2001
--- ./src/util/dict_ldap.c Tue Jul 17 15:56:27 2001
***************
*** 151,156 ****
--- 151,160 ----
void (*saved_alarm) (int);
int rc = 0;
+ #ifdef LDAP_API_FEATURE_X_MEMCACHE
+ LDAPMemCache *dircache;
+ #endif
+
#ifdef LDAP_OPT_NETWORK_TIMEOUT
struct timeval mytimeval;
***************
*** 162,168 ****
msg_info("%s: Connecting to server %s", myname,
dict_ldap->server_host);
! #ifdef UNTESTED_LDAP_OPT_NETWORK_TIMEOUT
dict_ldap->ld = ldap_init(dict_ldap->server_host,
(int) dict_ldap->server_port);
if (dict_ldap->ld == NULL) {
--- 166,172 ----
msg_info("%s: Connecting to server %s", myname,
dict_ldap->server_host);
! #ifdef LDAP_OPT_NETWORK_TIMEOUT
dict_ldap->ld = ldap_init(dict_ldap->server_host,
(int) dict_ldap->server_port);
if (dict_ldap->ld == NULL) {
***************
*** 247,252 ****
--- 251,277 ----
myname, dict_ldap->cache_size, dict_ldap->ldapsource,
dict_ldap->cache_expiry);
+ #ifdef LDAP_API_FEATURE_X_MEMCACHE
+ rc = ldap_memcache_init(dict_ldap->cache_expiry, dict_ldap->cache_size,
+ NULL, NULL, &dircache);
+ if (rc != LDAP_SUCCESS) {
+ msg_warn
+ ("%s: Unable to configure cache for %s: %d (%s) -- continuing",
+ myname, dict_ldap->ldapsource, rc, ldap_err2string(rc));
+ } else {
+ rc = ldap_memcache_set(dict_ldap->ld, dircache);
+ if (rc != LDAP_SUCCESS) {
+ msg_warn
+ ("%s: Unable to configure cache for %s: %d (%s) -- continuing",
+ myname, dict_ldap->ldapsource, rc, ldap_err2string(rc));
+ } else {
+ if (msg_verbose)
+ msg_info("%s: Caching enabled for %s",
+ myname, dict_ldap->ldapsource);
+ }
+ }
+ #else
+
rc = ldap_enable_cache(dict_ldap->ld, dict_ldap->cache_expiry,
dict_ldap->cache_size);
if (rc != LDAP_SUCCESS) {
***************
*** 258,263 ****
--- 283,290 ----
msg_info("%s: Caching enabled for %s",
myname, dict_ldap->ldapsource);
}
+
+ #endif
}
if (msg_verbose)
msg_info("%s: Cached connection handle for LDAP source %s",
***************
*** 315,321 ****
if (strcasecmp(dict_ldap->result_attributes->argv[i],
attr) == 0) {
if (msg_verbose)
! msg_info("%s: search returned value(s) for requested result attribute %s", myname, attr);
break;
}
}
--- 342,348 ----
if (strcasecmp(dict_ldap->result_attributes->argv[i],
attr) == 0) {
if (msg_verbose)
! msg_info("%s: search returned %d value(s) for requested result attribute %s", myname, i, attr);
break;
}
}
***************
*** 390,396 ****
* load on the LDAP server.
*/
if (dict_ldap->domain) {
! char *p=strrchr(name,'@');
if (p != 0)
p=p+1;
else
--- 417,423 ----
* load on the LDAP server.
*/
if (dict_ldap->domain) {
! const char *p=strrchr(name,'@');
if (p != 0)
p=p+1;
else
***************
*** 482,488 ****
/*
* Does the supplied query_filter even include a substitution?
*/
! if ((char *) strstr(dict_ldap->query_filter, "%s") == NULL) {
/*
* No, log the fact and continue.
--- 509,515 ----
/*
* Does the supplied query_filter even include a substitution?
*/
! if ((char *) strchr(dict_ldap->query_filter, '%') == NULL) {
/*
* No, log the fact and continue.
***************
*** 494,514 ****
/*
* Yes, replace all instances of %s with the address to look up.
*/
sub = dict_ldap->query_filter;
end = sub + strlen(dict_ldap->query_filter);
while (sub < end) {
/*
! * Make sure it's %s and not something else, though it wouldn't
! * really matter; the token could be any single character.
*/
if (*(sub) == '%') {
! if ((sub + 1) != end && *(sub + 1) != 's')
! msg_warn
! ("%s: Invalid lookup substitution format '%%%c'!",
! myname, *(sub + 1));
! vstring_strcat(filter_buf, vstring_str(escaped_name));
sub++;
} else
vstring_strncat(filter_buf, sub, 1);
--- 521,560 ----
/*
* Yes, replace all instances of %s with the address to look up.
+ * Replace %u with the user portion, and %d with the domain portion.
*/
sub = dict_ldap->query_filter;
end = sub + strlen(dict_ldap->query_filter);
while (sub < end) {
/*
! * Make sure it's %[sud] and not something else. For backward
! * compatibilty, treat anything other than %u or %d as %s, with
! * a warning.
*/
if (*(sub) == '%') {
! char *u=vstring_str(escaped_name);
! char *p=strchr(u,'@');
! switch (*(sub+1)) {
! case 'd':
! if (p)
! vstring_strcat(filter_buf, p+1);
! break;
! case 'u':
! if (p)
! vstring_strncat(filter_buf, u, p-u);
! else
! vstring_strcat(filter_buf, u);
! break;
! default:
! msg_warn
! ("%s: Invalid lookup substitution format '%%%c'!",
! myname, *(sub + 1));
! /* fall through */
! case 's':
! vstring_strcat(filter_buf, u);
! break;
! }
sub++;
} else
vstring_strncat(filter_buf, sub, 1);
***************
*** 607,613 ****
myfree(dict_ldap->ldapsource);
myfree(dict_ldap->server_host);
myfree(dict_ldap->search_base);
! match_list_free(dict_ldap->domain);
myfree(dict_ldap->query_filter);
argv_free(dict_ldap->result_attributes);
myfree(dict_ldap->bind_dn);
--- 653,660 ----
myfree(dict_ldap->ldapsource);
myfree(dict_ldap->server_host);
myfree(dict_ldap->search_base);
! if (dict_ldap->domain)
! match_list_free(dict_ldap->domain);
myfree(dict_ldap->query_filter);
argv_free(dict_ldap->result_attributes);
myfree(dict_ldap->bind_dn);
***************
*** 626,639 ****
char *scope;
char *attr;
dict_ldap = (DICT_LDAP *) dict_alloc(DICT_TYPE_LDAP, ldapsource,
sizeof(*dict_ldap));
dict_ldap->dict.lookup = dict_ldap_lookup;
dict_ldap->dict.close = dict_ldap_close;
dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED;
-
- if (msg_verbose)
- msg_info("%s: Using LDAP source %s", myname, ldapsource);
dict_ldap->ldapsource = mystrdup(ldapsource);
--- 673,686 ----
char *scope;
char *attr;
+ if (msg_verbose)
+ msg_info("%s: Using LDAP source %s", myname, ldapsource);
+
dict_ldap = (DICT_LDAP *) dict_alloc(DICT_TYPE_LDAP, ldapsource,
sizeof(*dict_ldap));
dict_ldap->dict.lookup = dict_ldap_lookup;
dict_ldap->dict.close = dict_ldap_close;
dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED;
dict_ldap->ldapsource = mystrdup(ldapsource);
diff -cr --new-file ../postfix-20010228-pl03/src/util/dict_pcre.c ./src/util/dict_pcre.c
*** ../postfix-20010228-pl03/src/util/dict_pcre.c Sun Feb 4 13:09:48 2001
--- ./src/util/dict_pcre.c Mon Jul 30 13:51:56 2001
***************
*** 266,271 ****
--- 266,272 ----
continue;
p = vstring_str(line_buffer);
+ trimblanks(p, 0)[0] = 0; /* Trim space at end */
re_delimiter = *p++;
regexp = p;
diff -cr --new-file ../postfix-20010228-pl03/src/util/dict_regexp.c ./src/util/dict_regexp.c
*** ../postfix-20010228-pl03/src/util/dict_regexp.c Sun Feb 4 13:09:52 2001
--- ./src/util/dict_regexp.c Mon Jul 30 13:51:15 2001
***************
*** 365,370 ****
--- 365,372 ----
if (*p == 0) /* Skip blank lines */
continue;
+ trimblanks(p, 0)[0] = 0; /* Trim space at end */
+
rule = dict_regexp_parseline(lineno, p, &nsub, map_fp);
if (rule) {
if (nsub > max_nsub)
diff -cr --new-file ../postfix-20010228-pl03/src/util/inet_addr_list.c ./src/util/inet_addr_list.c
*** ../postfix-20010228-pl03/src/util/inet_addr_list.c Mon Nov 20 13:06:30 2000
--- ./src/util/inet_addr_list.c Tue Jul 31 14:13:41 2001
***************
*** 13,18 ****
--- 13,21 ----
/* INET_ADDR_LIST *list;
/* struct in_addr *addr;
/*
+ /* void inet_addr_list_uniq(list)
+ /* INET_ADDR_LIST *list;
+ /*
/* void inet_addr_list_free(list)
/* INET_ADDR_LIST *list;
/* DESCRIPTION
***************
*** 25,30 ****
--- 28,36 ----
/* inet_addr_list_append() appends the specified address to
/* the specified list, extending the list on the fly.
/*
+ /* inet_addr_list_uniq() sorts the specified address list and
+ /* eliminates duplicates.
+ /*
/* inet_addr_list_free() reclaims memory used for the
/* specified address list.
/* LICENSE
***************
*** 43,48 ****
--- 49,55 ----
#include
#include
#include
+ #include
/* Utility library. */
***************
*** 77,85 ****
--- 84,164 ----
list->addrs[list->used++] = *addr;
}
+ /* inet_addr_list_comp - compare addresses */
+
+ static int inet_addr_list_comp(const void *a, const void *b)
+ {
+ const struct in_addr *a_addr = (const struct in_addr *) a;
+ const struct in_addr *b_addr = (const struct in_addr *) b;
+
+ return (a_addr->s_addr - b_addr->s_addr);
+ }
+
+ /* inet_addr_list_uniq - weed out duplicates */
+
+ void inet_addr_list_uniq(INET_ADDR_LIST *list)
+ {
+ int n;
+ int m;
+
+ /*
+ * Put the identical members right next to each other.
+ */
+ qsort((void *) list->addrs, list->used,
+ sizeof(list->addrs[0]), inet_addr_list_comp);
+
+ /*
+ * Nuke the duplicates. Postcondition after while loop: m is the largest
+ * index for which list->addrs[n] == list->addrs[m].
+ */
+ for (m = n = 0; m < list->used; m++, n++) {
+ if (m != n)
+ list->addrs[n] = list->addrs[m];
+ while (m + 1 < list->used
+ && inet_addr_list_comp((void *) &(list->addrs[n]),
+ (void *) &(list->addrs[m + 1])) == 0)
+ m += 1;
+ }
+ list->used = n;
+ }
+
/* inet_addr_list_free - destroy internet address list */
void inet_addr_list_free(INET_ADDR_LIST *list)
{
myfree((char *) list->addrs);
}
+
+ #ifdef TEST
+
+ /*
+ * Duplicate elimination needs to be tested.
+ */
+ #include
+
+ static void inet_addr_list_print(INET_ADDR_LIST *list)
+ {
+ int n;
+
+ for (n = 0; n < list->used; n++)
+ msg_info("%s", inet_ntoa(list->addrs[n]));
+ }
+
+ int main(int argc, char **argv)
+ {
+ INET_ADDR_LIST list;
+
+ inet_addr_list_init(&list);
+ while (--argc && *++argv)
+ if (inet_addr_host(&list, *argv) == 0)
+ msg_fatal("host not found: %s", *argv);
+ msg_info("list before sort/uniq");
+ inet_addr_list_print(&list);
+ inet_addr_list_uniq(&list);
+ msg_info("list after sort/uniq");
+ inet_addr_list_print(&list);
+ inet_addr_list_free(&list);
+ return (0);
+ }
+
+ #endif
diff -cr --new-file ../postfix-20010228-pl03/src/util/inet_addr_list.h ./src/util/inet_addr_list.h
*** ../postfix-20010228-pl03/src/util/inet_addr_list.h Fri Dec 11 13:55:35 1998
--- ./src/util/inet_addr_list.h Tue Jul 31 13:56:47 2001
***************
*** 27,32 ****
--- 27,33 ----
extern void inet_addr_list_init(INET_ADDR_LIST *);
extern void inet_addr_list_free(INET_ADDR_LIST *);
+ extern void inet_addr_list_uniq(INET_ADDR_LIST *);
extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
/* LICENSE
diff -cr --new-file ../postfix-20010228-pl03/src/util/inet_addr_list.in ./src/util/inet_addr_list.in
*** ../postfix-20010228-pl03/src/util/inet_addr_list.in Wed Dec 31 19:00:00 1969
--- ./src/util/inet_addr_list.in Tue Jul 31 13:55:21 2001
***************
*** 0 ****
--- 1,9 ----
+ 168.100.189.2
+ 168.100.189.2
+ 168.100.189.1
+ 168.100.189.3
+ 168.100.189.3
+ 168.100.189.3
+ 168.100.189.4
+ 168.100.189.1
+ 168.100.189.4
diff -cr --new-file ../postfix-20010228-pl03/src/util/inet_addr_list.ref ./src/util/inet_addr_list.ref
*** ../postfix-20010228-pl03/src/util/inet_addr_list.ref Wed Dec 31 19:00:00 1969
--- ./src/util/inet_addr_list.ref Tue Jul 31 13:59:49 2001
***************
*** 0 ****
--- 1,15 ----
+ unknown: list before sort/uniq
+ unknown: 168.100.189.2
+ unknown: 168.100.189.2
+ unknown: 168.100.189.1
+ unknown: 168.100.189.3
+ unknown: 168.100.189.3
+ unknown: 168.100.189.3
+ unknown: 168.100.189.4
+ unknown: 168.100.189.1
+ unknown: 168.100.189.4
+ unknown: list after sort/uniq
+ unknown: 168.100.189.1
+ unknown: 168.100.189.2
+ unknown: 168.100.189.3
+ unknown: 168.100.189.4
diff -cr --new-file ../postfix-20010228-pl03/src/util/ring.h ./src/util/ring.h
*** ../postfix-20010228-pl03/src/util/ring.h Fri Dec 11 13:55:30 1998
--- ./src/util/ring.h Sun Jul 29 11:35:58 2001
***************
*** 29,34 ****
--- 29,45 ----
#define ring_succ(c) ((c)->succ)
#define ring_pred(c) ((c)->pred)
+ /*
+ * Typically, an application will embed a RING structure into a larger
+ * structure that also contains application-specific members. This approach
+ * gives us the best of both worlds. The application can still use the
+ * generic RING primitives for manipulating RING structures. The macro below
+ * transforms a pointer from RING structure to the structure that contains
+ * it.
+ */
+ #define RING_TO_APPL(ring_ptr,app_type,ring_member) \
+ ((app_type *) (((char *) (ring_ptr)) - offsetof(app_type,ring_member)))
+
/* LICENSE
/* .ad
/* .fi