diff --git a/gnu/dist/postfix/HISTORY b/gnu/dist/postfix/HISTORY index 13a9bcfad571..ab2d0fbb550c 100644 --- a/gnu/dist/postfix/HISTORY +++ b/gnu/dist/postfix/HISTORY @@ -5063,3 +5063,36 @@ Apologies for any names omitted. 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 --git a/gnu/dist/postfix/MYSQL_README b/gnu/dist/postfix/MYSQL_README index faecf80a2631..2f11bd9566eb 100644 --- a/gnu/dist/postfix/MYSQL_README +++ b/gnu/dist/postfix/MYSQL_README @@ -12,9 +12,10 @@ the mysqlclient library (and libm) to AUXLIBS, for example: make -f Makefile.init makefiles \ 'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \ - 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lm' + 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lz -lm' -then, just run 'make'. +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 --git a/gnu/dist/postfix/conf/sample-ldap.cf b/gnu/dist/postfix/conf/sample-ldap.cf index c503df0bc66c..8badb4026091 100644 --- a/gnu/dist/postfix/conf/sample-ldap.cf +++ b/gnu/dist/postfix/conf/sample-ldap.cf @@ -23,6 +23,13 @@ #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) @@ -31,6 +38,13 @@ # #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. # #ldap_scope = sub diff --git a/gnu/dist/postfix/html/faq.html b/gnu/dist/postfix/html/faq.html index a2b8b627a8f1..425304fddb95 100644 --- a/gnu/dist/postfix/html/faq.html +++ b/gnu/dist/postfix/html/faq.html @@ -1027,7 +1027,7 @@ Berkeley DB library version.
-

sendmail has set-uid root file permissions, or is run from a +

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 --git a/gnu/dist/postfix/src/global/mail_version.h b/gnu/dist/postfix/src/global/mail_version.h index f725dbca0f66..4ccf192f8c4e 100644 --- a/gnu/dist/postfix/src/global/mail_version.h +++ b/gnu/dist/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Postfix-20010228-pl03" +#define DEF_MAIL_VERSION "Postfix-20010228-pl04" extern char *var_mail_version; /* LICENSE diff --git a/gnu/dist/postfix/src/smtpd/Makefile.in b/gnu/dist/postfix/src/smtpd/Makefile.in index 90d9aa96bbc2..aebfcaeac19b 100644 --- a/gnu/dist/postfix/src/smtpd/Makefile.in +++ b/gnu/dist/postfix/src/smtpd/Makefile.in @@ -67,7 +67,7 @@ depend: $(MAKES) 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 +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,6 +81,12 @@ smtpd_check_test2: smtpd_check smtpd_check.in2 smtpd_check.ref2 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,6 +170,7 @@ smtpd_check.o: ../../include/mymalloc.h 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 --git a/gnu/dist/postfix/src/smtpd/smtpd_acl.in b/gnu/dist/postfix/src/smtpd/smtpd_acl.in new file mode 100644 index 000000000000..e633c48d5610 --- /dev/null +++ b/gnu/dist/postfix/src/smtpd/smtpd_acl.in @@ -0,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 --git a/gnu/dist/postfix/src/smtpd/smtpd_acl.ref b/gnu/dist/postfix/src/smtpd/smtpd_acl.ref new file mode 100644 index 000000000000..34e351866272 --- /dev/null +++ b/gnu/dist/postfix/src/smtpd/smtpd_acl.ref @@ -0,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 --git a/gnu/dist/postfix/src/smtpd/smtpd_check_access b/gnu/dist/postfix/src/smtpd/smtpd_check_access index f7f6e42d7fc3..afb5487c9656 100644 --- a/gnu/dist/postfix/src/smtpd/smtpd_check_access +++ b/gnu/dist/postfix/src/smtpd/smtpd_check_access @@ -2,9 +2,30 @@ bad.domain 554 match bad.domain 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 --git a/gnu/dist/postfix/src/util/ctable.c b/gnu/dist/postfix/src/util/ctable.c new file mode 100644 index 000000000000..4e6d18f5e455 --- /dev/null +++ b/gnu/dist/postfix/src/util/ctable.c @@ -0,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 --git a/gnu/dist/postfix/src/util/ctable.h b/gnu/dist/postfix/src/util/ctable.h new file mode 100644 index 000000000000..7e3d899b3f0c --- /dev/null +++ b/gnu/dist/postfix/src/util/ctable.h @@ -0,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 --git a/gnu/dist/postfix/src/util/ctable.in b/gnu/dist/postfix/src/util/ctable.in new file mode 100644 index 000000000000..78763cfaf2ec --- /dev/null +++ b/gnu/dist/postfix/src/util/ctable.in @@ -0,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 --git a/gnu/dist/postfix/src/util/ctable.ref b/gnu/dist/postfix/src/util/ctable.ref new file mode 100644 index 000000000000..34e8a951abd7 --- /dev/null +++ b/gnu/dist/postfix/src/util/ctable.ref @@ -0,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 = \ No newline at end of file diff --git a/gnu/dist/postfix/src/util/dict_ldap.c b/gnu/dist/postfix/src/util/dict_ldap.c index 776a437db560..528769248962 100644 --- a/gnu/dist/postfix/src/util/dict_ldap.c +++ b/gnu/dist/postfix/src/util/dict_ldap.c @@ -151,6 +151,10 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap) 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,7 +166,7 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap) msg_info("%s: Connecting to server %s", myname, dict_ldap->server_host); -#ifdef UNTESTED_LDAP_OPT_NETWORK_TIMEOUT +#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,6 +251,27 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap) 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,6 +283,8 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap) 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,7 +342,7 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res, 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); + msg_info("%s: search returned %d value(s) for requested result attribute %s", myname, i, attr); break; } } @@ -390,7 +417,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) * load on the LDAP server. */ if (dict_ldap->domain) { - char *p=strrchr(name,'@'); + const char *p=strrchr(name,'@'); if (p != 0) p=p+1; else @@ -482,7 +509,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) /* * Does the supplied query_filter even include a substitution? */ - if ((char *) strstr(dict_ldap->query_filter, "%s") == NULL) { + if ((char *) strchr(dict_ldap->query_filter, '%') == NULL) { /* * No, log the fact and continue. @@ -494,21 +521,40 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) /* * 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 %s and not something else, though it wouldn't - * really matter; the token could be any single character. + * 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) == '%') { - 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)); + 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,7 +653,8 @@ static void dict_ldap_close(DICT *dict) myfree(dict_ldap->ldapsource); myfree(dict_ldap->server_host); myfree(dict_ldap->search_base); - match_list_free(dict_ldap->domain); + 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,15 +673,15 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) 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; - if (msg_verbose) - msg_info("%s: Using LDAP source %s", myname, ldapsource); - dict_ldap->ldapsource = mystrdup(ldapsource); config_param = vstring_alloc(15); diff --git a/gnu/dist/postfix/src/util/dict_pcre.c b/gnu/dist/postfix/src/util/dict_pcre.c index 1e8e84b6bf5a..6d3c6f523932 100644 --- a/gnu/dist/postfix/src/util/dict_pcre.c +++ b/gnu/dist/postfix/src/util/dict_pcre.c @@ -266,6 +266,7 @@ DICT *dict_pcre_open(const char *map, int unused_flags, int dict_flags) continue; p = vstring_str(line_buffer); + trimblanks(p, 0)[0] = 0; /* Trim space at end */ re_delimiter = *p++; regexp = p; diff --git a/gnu/dist/postfix/src/util/dict_regexp.c b/gnu/dist/postfix/src/util/dict_regexp.c index 0d4eaf852352..1debbe96ff2c 100644 --- a/gnu/dist/postfix/src/util/dict_regexp.c +++ b/gnu/dist/postfix/src/util/dict_regexp.c @@ -365,6 +365,8 @@ DICT *dict_regexp_open(const char *map, int unused_flags, int dict_flags) 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 --git a/gnu/dist/postfix/src/util/inet_addr_list.in b/gnu/dist/postfix/src/util/inet_addr_list.in new file mode 100644 index 000000000000..742281fae146 --- /dev/null +++ b/gnu/dist/postfix/src/util/inet_addr_list.in @@ -0,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 --git a/gnu/dist/postfix/src/util/inet_addr_list.ref b/gnu/dist/postfix/src/util/inet_addr_list.ref new file mode 100644 index 000000000000..0a8a56e1ad95 --- /dev/null +++ b/gnu/dist/postfix/src/util/inet_addr_list.ref @@ -0,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 --git a/gnu/dist/postfix/src/util/ring.h b/gnu/dist/postfix/src/util/ring.h index a96fe2696af4..d0219cf804cc 100644 --- a/gnu/dist/postfix/src/util/ring.h +++ b/gnu/dist/postfix/src/util/ring.h @@ -29,6 +29,17 @@ extern void ring_detach(RING *); #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